Android bottomNavlationView Một tab với các màu không được chọn / chọn khác nhau


8

Tôi đang cố gắng để phù hợp với một thiết kế như thế này ..

nhập mô tả hình ảnh ở đây

Lưu ý rằng "tông màu của tab đã chọn" là màu xanh lam, nhưng biểu tượng của tab trung tâm phải luôn là vòng tròn màu xanh lá cây với đồng hồ màu trắng ở giữa.

Tôi đã thử một số thứ. Trước tiên, hãy thử làm điều đó bằng lập trình bằng cách sử dụng tài nguyên XML trong danh sách lớp có tài nguyên PNG vòng tròn màu xanh lá cây và đồng hồ, không hoạt động. Sau đó, tôi đã nhờ nhà thiết kế đưa cho tôi biểu tượng đầy đủ (đồng hồ và vòng tròn màu xanh lá cây), nhưng bây giờ tôi đang gặp phải vấn đề này ..

(Không được chọn)

nhập mô tả hình ảnh ở đây

(Đã chọn)

nhập mô tả hình ảnh ở đây

Tôi không tìm được thuật ngữ chính xác để tìm kiếm trên Google để sửa lỗi này.

Cuối cùng, tôi cần màu tab đã chọn là màu xanh lam, nhưng tôi cần biểu tượng tab trung tâm luôn là biểu tượng thực tế không có màu bổ sung (về cơ bản nó cần trông giống hệt như .png).

PS: Tôi đang sử dụng Xamarin.Forms, FreshMvvm và FreshTabbedFONavlationContainer. Tuy nhiên, thông qua Trình kết xuất, tôi có quyền truy cập trực tiếp vào bottomNavlationView và tất cả các thành phần Android gốc khác. Vì vậy, giải pháp không phải là một giải pháp Xamarin. Một giải pháp java / kotlin cũng sẽ hoạt động và tôi chỉ có thể chuyển đổi nó thành Xamarin.

======================

EDITED:

======================

Vì vậy, tôi đã nhận được nhiều hơn nữa bằng cách sử dụng mã của Andres Castro dưới đây, nhưng tôi vẫn gặp vấn đề tương tự như trước đây. Sử dụng mã của Andres bên dưới, tôi quay lại sử dụng FontAwgie cho các biểu tượng (hoạt động rất tốt), nhưng khi làm như vậy có nghĩa là tôi cần sử dụng một LayerDrawableđể tạo biểu tượng tab vòng tròn / biểu tượng trung tâm.

Vì vậy, đây là những gì tôi có cho đến nay ..

Biểu tượng trung tâm không được chọn

nhập mô tả hình ảnh ở đây

Biểu tượng trung tâm được chọn

nhập mô tả hình ảnh ở đây

Như bạn có thể thấy, biểu tượng trung tâm vẫn có màu xám khi không được chọn và màu xanh lam khi được chọn (màu được chọn / không được chọn đúng của 4 biểu tượng khác).

Đây là mã tôi có liên quan đến biểu tượng trung tâm ..

Cập nhậtTabbedIcons

private void UpdateTabbedIcons()
{
    for (var i = 0; i < Element.Children.Count; i++) {
        var tab = _bottomNavigationView.Menu.GetItem(i);

        var element = Element.Children[i];
        if (element is NavigationPage navigationPage) {
            //if the child page is a navigation page get its root page
            element = navigationPage.RootPage;
        }

        UpdateTabIcon(tab, element);
    }
}

Cập nhậtTabIcon

public void UpdateTabIcon(IMenuItem menuItem, Page page)
{
    var icon = page?.Icon;
    if (icon == null) return;

    var drawable = new IconDrawable(Context, icon, "fa-regular-pro-400.ttf");

    var element = Element.CurrentPage;
    if (element is NavigationPage navigationPage) {
        //if the child page is a navigation page get its root page
        element = navigationPage.RootPage;
    }

    if (page is DoNowTabPage) { //Page for center icon
        drawable.Color(Helpers.Resources.White.ToAndroid());
        var finalDrawable = GetCombinedDrawable(drawable);
        menuItem.SetIcon(finalDrawable);
        return;
    } else if (element == page) {
        drawable.Color(BarSelectedItemColor.ToAndroid());
    } else {
        drawable.Color(BarItemColor.ToAndroid());
    }

    menuItem.SetIcon(drawable);
}

GetCombinedDrawable

private Drawable GetCombinedDrawable(IconDrawable iconDrawable)
{
    var displayMetrics = Resources.DisplayMetrics;

    GradientDrawable circleDrawable = new GradientDrawable();
    circleDrawable.SetColor(Helpers.Resources.Green.ToAndroid());
    circleDrawable.SetShape(ShapeType.Oval);
    circleDrawable.SetSize((int)TypedValue.ApplyDimension(ComplexUnitType.Dip, 500, displayMetrics), (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, 500, displayMetrics));
    circleDrawable.Alpha = 1;

    var inset = (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, 140, displayMetrics);
    var bottomInset = (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, 40, displayMetrics);
    LayerDrawable finalDrawable = new LayerDrawable(new Drawable[] { circleDrawable, iconDrawable });
    finalDrawable.SetLayerHeight(1, iconDrawable.IntrinsicHeight);
    finalDrawable.SetLayerWidth(1, iconDrawable.IntrinsicWidth);
    finalDrawable.SetLayerInset(1, inset, inset, inset, inset + bottomInset);
    finalDrawable.SetLayerInsetBottom(0, bottomInset);
    finalDrawable.ClearColorFilter();

    return finalDrawable;
}

Như bạn có thể thấy trong phần GradientDrawabletôi đang tạo cho vòng tròn, tôi đang đặt màu của nó thành màu Xanh lục của mình (Tôi có một lớp tùy chỉnh được gọi là Tài nguyên..không phải là Resourceslớp Android ).

Vì vậy, đó là nơi tôi bị mắc kẹt. Tôi đang đặt vòng tròn có thể vẽ thành màu xanh lục, nhưng một lần trong bottomNavulationView, màu của nó luôn khớp với các màu không được chọn / chọn của các biểu tượng khác.

Hy vọng sẽ vượt qua vấn đề cuối cùng này. Cảm ơn vì bất kì sự giúp đỡ.


Một giải pháp đơn giản là sử dụng một mục trống ở giữa và đặt một chế độ xem hình ảnh riêng biệt trên bottomNavlationView với hình ảnh màu xanh lá cây.
Shivam Yadav

1
Tại sao bạn không thay đổi màu sắc / màu đã chọn theo chương trình tùy thuộc vào chỉ mục của chế độ xem điều hướng phía dưới?
Saamer

1
@Saamer Bạn nhận xét có vẻ đơn giản quá haha. Bạn có thể đăng nó như một câu trả lời để tôi có thể trao giải thưởng không? Đây là mã tôi đã sử dụng ..._bottomNavigationView.ItemIconTintList = null;
Ryan Alford

Nó làm việc cho bạn? BottomNavulationView khó khăn hơn nhiều so với việc triển khai iOS. Tôi đã thực hiện một số nghiên cứu để xem liệu những gì bạn đang hỏi có khả thi hay không, và sau đó khi tôi thấy nó trong bản địa Android, tôi bắt đầu nghĩ cách để làm cho nó xảy ra.
Saamer

1
Vâng, nó đã làm việc. Tôi không chắc nhưng có vẻ như sự thay đổi của tôi sẽ thiết lập lại TẤT CẢ các sắc thái biểu tượng vật phẩm, nhưng thực tế không phải vậy. Tất cả các tab khác vẫn hoạt động vì tôi cài đặt thủ công mỗi lần và trung tâm có màu xanh khi được chọn và không được chọn.
Ryan Alford

Câu trả lời:


1

BottomNavulationView khó khăn hơn nhiều so với việc triển khai iOS. Tôi đã thực hiện một số nghiên cứu để xem liệu những gì bạn đang hỏi có khả thi hay không, và sau đó khi tôi thấy nó trong bản địa Android, tôi bắt đầu nghĩ cách để làm cho nó xảy ra.

Để thực hiện thử thách cuối cùng của bạn, bạn sẽ phải lập trình thay đổi màu / màu đã chọn theo chương trình tùy thuộc vào chỉ mục của chế độ xem điều hướng phía dưới.


2

Vì bạn có quyền truy cập vào chế độ xem điều hướng phía dưới, bạn chỉ có thể "vẽ lại" thanh công cụ dưới cùng của mình mỗi khi bạn chuyển trang. Chúng tôi đã làm một cái gì đó tương tự và không nhận thấy bất kỳ vấn đề hiệu suất.

Trước tiên bạn sẽ muốn theo dõi các thay đổi của trang bằng cách đăng ký thay đổi trang bên trong OnElementChanged

Element.CurrentPageChanged += ElementOnCurrentPageChanged;

Sau đó, bên trong ElementOnCurrentPageChangedbạn có thể duyệt qua từng trang và nhận mục menu cho trang đó

private void UpdateTabbedIcons()
{
    for (var i = 0; i < Element.Children.Count; i++)
    {
        var tab = _bottomNavigationView.Menu.GetItem(i);

        var element = Element.Children[i];
        if (element is NavigationPage navigationPage)
        {
            //if the child page is a navigation page get its root page
            element = navigationPage.RootPage;
        }

        UpdateTabIcon(tab, element);
    }
}

Trong trường hợp của chúng tôi, chúng tôi đã sử dụng các biểu tượng phông chữ để chúng tôi vẽ các biểu tượng và đặt màu mỗi lần.

public void UpdateTabIcon(IMenuItem menuItem, Page page)
{
    var icon = page?.Icon?.File;
    if (icon == null) return;

    var drawable = new IconDrawable(Context, "FontAwesome.ttf", icon).SizeDp(20);

    var element = Element.CurrentPage;
    if (element is NavigationPage navigationPage)
    {
        //if the child page is a navigation page get its root page
        element = navigationPage.RootPage;
    }

    if (element == page)
    {
        drawable.Color(BarSelectedItemColor.ToAndroid());
    }
    else
    {
        drawable.Color(BarItemColor.ToAndroid());
    }

    menuItem.SetIcon(drawable);
}

Chúng tôi cũng phải ghi đè OnAttachedToWindow để đảm bảo các biểu tượng được vẽ lại khi quay lại ứng dụng từ các trạng thái khác nhau.

protected override void OnAttachedToWindow()
{
    UpdateTabbedIcons();

    base.OnAttachedToWindow();
}

Bạn sẽ phải sửa đổi một số điều này để phù hợp với trường hợp sử dụng của bạn nhưng tôi nghĩ phương pháp này sẽ thực hiện được những gì bạn đang tìm kiếm.


Tuyệt vời. Tôi sẽ cho nó một shot tối nay. Nếu bạn có mã làm việc sử dụng FontAwgie (hoặc các phông chữ đồ họa vector khác) cho bottomNavlationView, bạn thực sự nên làm một bài đăng blog ở đâu đó. Tôi không thể tìm thấy bất kỳ ví dụ nào và những nỗ lực của tôi sẽ không bao giờ hiển thị biểu tượng.
Ryan Alford

1

bạn có thể sử dụng hình ảnh SVG và tạo thuộc tính màu của riêng bạn và tạo bộ chọn có thể vẽ cho biểu tượng trung tâm cũng như biểu tượng xem điều hướng phía dưới khác như sau:

trong tập tin colors.xml

    <color name="color_bottom_selected">#44C8F5</color>
 <color name="color_bottom_unselected">#c0c0c0</color>

trong tệp attrs.xml

   <attr name="color_bottom_unselected" format="color" />
    <attr name="color_bottom_selected" format="color" />

trong tệp hình ảnh SVG

thay thế giá trị màu được mã hóa cứng bằng thuộc tính của bạn

android:fillColor="#fff" to android:fillColor="?attr/color_bottom_unselected"

và đừng quên làm cho bộ chọn


1

Hãy thử sử dụng chế độ màu DST , đơn giản là sẽ bỏ qua màu.

Thêm dòng này vào phương thức của bạn GetCombinedDrawable()

circleDrawable.setTintMode(PorterDuff.Mode.DST);

Nếu điều này không hiệu quả, hãy thử điều này:

finalDrawable.ClearColorFilter();
finalDrawable.setTintMode(PorterDuff.Mode.DST);

Tôi thực sự đã thử tất cả các tùy chọn PorterDuff.Mode, nhưng không có tùy chọn nào hoạt động.
Ryan Alford

0

Tôi có thể giúp bạn với điều này :

public class HomeMenuTabLayout extends TabLayout {

public static final int HOME_MENU_TABLAYOUT_COUNT = 5;

public static final int HOME_MENU_LIVE_INDEX = 0;
public static final int HOME_MENU_TEAM_INDEX = 1;
public static final int HOME_MENU_ADS_INDEX = 2;
public static final int HOME_MENU_WALLET_INDEX = 3;
public static final int HOME_MENU_POST_INDEX = 4;

public int selectedIndex = 0;
private TextView unread;

public HomeMenuTabLayout(Context context) {
    super(context);
    initItems(context);
}

public HomeMenuTabLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    initItems(context);
}

public HomeMenuTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initItems(context);
}

public void initItems(Context context) {
    for (int i = 0; i < HOME_MENU_TABLAYOUT_COUNT; i++) {
        addTab(newTab());
    }

    for (int i = 0; i < HOME_MENU_TABLAYOUT_COUNT; i++) {
        TabLayout.Tab tab = this.getTabAt(i);
        tab.setCustomView(getTabView(context, i, false));
    }
}

public void setTagIndex(Context context, int index) {
    getTabView(context, selectedIndex, false);
    selectedIndex = index;
    getTabView(context, selectedIndex, true);
}

private View getTabView(Context context, int index, boolean selected) {
    View v = null;
    TabLayout.Tab tab = this.getTabAt(index);
    if (tab != null) {
        v = tab.getCustomView();
        if (v == null) {
            v = LayoutInflater.from(context).inflate(R.layout.activity_main_tab_layout, null);
        }
    }

    if (v == null) {
        return null;
    }

    ImageView img = v.findViewById(R.id.tablayout_image);
    int color = 0;
    int color2 = 0;
    if (selected) {
        color = getResources().getColor(R.color.corn_flower_blue);
        color2 = getResources().getColor(R.color.dark_sky_blue_three);
        TmlyUtils.displayViewWithZoom(img);
    } else {
        color = getResources().getColor(R.color.battleship_grey_dark);
        color2 = getResources().getColor(R.color.battleship_grey_dark);
    }

    switch (index) {
        case HOME_MENU_ADS_INDEX:
            Bitmap offers = StyleKit.imageOfTabbarSearchActive(color, color2);
            img.setImageBitmap(offers);
            break;
        case HOME_MENU_LIVE_INDEX:

            Bitmap live = StyleKit.imageOfTabbarHomeActive(color, color2);
            img.setImageBitmap(live);
            unread = v.findViewById(R.id.tablayout_unread);
            break;
        case HOME_MENU_TEAM_INDEX:
            Bitmap team = StyleKit.imageOfTabbarSocialActive(color, color2);
            img.setImageBitmap(team);
            break;
        case HOME_MENU_WALLET_INDEX:
            Bitmap wallet = StyleKit.imageOfTabbarCaddyActive(color, color2);
            img.setImageBitmap(wallet);
            break;
        case HOME_MENU_POST_INDEX:
            Bitmap chat = StyleKit.imageOfTabbarPlusActive(getResources().getColor(R.color.white), getResources().getColor(R.color.white));
            img.setImageBitmap(chat);
            View cirle = v.findViewById(R.id.tablayout_circle);
            cirle.setVisibility(View.VISIBLE);
            break;
        default:
            break;
    }
    return v;
}
}

Đây là một TabLayout tùy chỉnh mà bạn có thể thấy tôi mở rộng lớp TabLayout, khi TabLayout được tạo, tôi đang gọi phương thức initItems là addTab và đặt chế độ xem tùy chỉnh cho nó.

GetTabView trả về chế độ xem tăng cao như bạn có thể thấy với điều này

 LayoutInflater.from(context).inflate(R.layout.activity_main_tab_layout, null);

Nếu bạn cần nó

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="@dimen/tab_bar_height">

    <ImageView
        android:id="@+id/tablayout_circle"
        android:layout_width="@dimen/tab_bar_height"
        android:layout_height="@dimen/tab_bar_height"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:background="@drawable/circle_blue_gradient"
        android:visibility="gone"
        tools:visibility="visible" />

    <ImageView
        android:id="@+id/tablayout_image"
        android:layout_width="@dimen/tab_bar_icon_favorite_height"
        android:layout_height="@dimen/tab_bar_icon_favorite_height"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true" />

</RelativeLayout>

Sau khi tăng chế độ xem, bạn có thể có được thành phần xem của mình với

  ImageView img = v.findViewById(R.id.tablayout_image);

Bạn có thể kiểm tra xem chế độ xem có được chọn với boolean đã chọn hay không, đối với trường hợp của bạn, bạn cần bỏ qua công tắc màu khi chỉ mục là trung tâm.

Chỉ một điều khi bạn nhấp vào biểu tượng TabLayout đừng quên gọi

setTagIndex();

Nếu bạn không làm điều đó, hình ảnh sẽ không được vẽ lại


0

Giải pháp

Học sinh lớp

implementation 'com.github.armcha:SpaceNavigationView:1.6.0'

Bố trí:

<com.luseen.spacenavigation.SpaceNavigationView
        android:id="@+id/space"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentBottom="true"
        app:active_item_color="@color/color_trans"
        app:centre_button_color="@color/black"
        app:inactive_item_color="@color/color_trans"
        app:space_background_color="@color/white"
        app:space_item_icon_only_size="24dp"
        app:space_item_icon_size="@dimen/space_item_icon_default_size"
        app:space_item_text_size="@dimen/space_item_text_default_size" />

Thêm mục điều hướng không gian.

 spaceNavigationView = (SpaceNavigationView) findViewById(R.id.space);
 spaceNavigationView.initWithSaveInstanceState(savedInstanceState);

       /*Space navigation View*/
        spaceNavigationView.initWithSaveInstanceState(savedInstanceState);

        spaceNavigationView.addSpaceItem(new SpaceItem(0, "Templates", R.drawable.ic_color_template_tab, getResources().getColor(R.color.color_yellow)));
        spaceNavigationView.addSpaceItem(new SpaceItem(1, "Explore", R.drawable.ic_category_tab, getResources().getColor(R.color.color_bg)));
        spaceNavigationView.addSpaceItem(new SpaceItem(2, "Tools", R.drawable.ic_tools_tab, getResources().getColor(R.color.color_bg)));
        spaceNavigationView.addSpaceItem(new SpaceItem(3, "My Work", R.drawable.ic_my_work_tab, getResources().getColor(R.color.color_bg)));


        spaceNavigationView.setCentreButtonIconColorFilterEnabled(true);
        spaceNavigationView.setCentreButtonIcon(R.drawable.ic_create2_tab);
        spaceNavigationView.setInActiveCentreButtonIconColor(ContextCompat.getColor(this, R.color.white));
        spaceNavigationView.setActiveCentreButtonBackgroundColor(ContextCompat.getColor(this, R.color.color_yellow));
        spaceNavigationView.setCentreButtonColor(ContextCompat.getColor(this, R.color.black));
        spaceNavigationView.setCentreButtonRippleColor(ContextCompat.getColor(this, R.color.color_yellow));
        spaceNavigationView.setCentreButtonSelectable(true);

        spaceNavigationView.setSpaceBackgroundColor(ContextCompat.getColor(this, R.color.obaudiopicker_white));
    //  spaceNavigationView.setCentreButtonSelected(2, R.drawable.ic_color_template_tab, getResources().getColor(R.color.color_yellow));
        spaceNavigationView.setInActiveSpaceItemColor(ContextCompat.getColor(this, R.color.color_bg));

Sử dụng initWithSaveInstanceState(savedInstanceState)override onSaveInstanceStatenếu bạn muốn giữ vị trí vật phẩm và huy hiệu đã chọn khi xoay thiết bị

@Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        spaceNavigationView.onSaveInstanceState(outState);
        Log.i(TAG, "onSaveInstanceState: ");
    }

Đặt trình nghe onClick

spaceNavigationView.setSpaceOnClickListener(new SpaceOnClickListener() {
            @Override
            public void onCentreButtonClick() {
                setDefaultIcon();
                new Handler().post(new Runnable() {
                    @Override
                    public void run() {
                        spaceNavigationView.setActiveCentreButtonIconColor(ContextCompat.getColor(NEWBusinessCardMainActivity.this, R.color.black));

                    }
                });
                changeCurrentFragmentTo(Constants.ITEM_CREATE);
            }

            @Override
            public void onItemClick(final int itemIndex, String itemName) {
                Log.d("onItemClick ", "" + itemIndex + " " + itemName);
                switch (itemIndex) {
                    case 0:
                        setDefaultIcon();
                        new Handler().post(new Runnable() {
                            @Override
                            public void run() {
                                spaceNavigationView.changeItemIconAtPosition(itemIndex, R.drawable.ic_color_template_tab);
                                spaceNavigationView.changeItemTextColorAtPosition(itemIndex, getResources().getColor(R.color.color_yellow));
                            }
                        });
                        changeCurrentFragmentTo(Constants.ITEM_TEMPLATE);
                        break;
                    case 1:
                        setDefaultIcon();
                        new Handler().post(new Runnable() {
                            @Override
                            public void run() {
                                spaceNavigationView.changeItemIconAtPosition(itemIndex, R.drawable.ic_color_category_tab);
                                spaceNavigationView.changeItemTextColorAtPosition(itemIndex, getResources().getColor(R.color.color_category));

                            }
                        });
                        changeCurrentFragmentTo(Constants.ITEM_CATEGORY);
                        break;
                    case 2:
                        setDefaultIcon();
                        new Handler().post(new Runnable() {
                            @Override
                            public void run() {
                                spaceNavigationView.changeItemIconAtPosition(itemIndex, R.drawable.ic_color_tool_tab);
                                spaceNavigationView.changeItemTextColorAtPosition(itemIndex, getResources().getColor(R.color.color_tools));

                            }
                        });
                        changeCurrentFragmentTo(Constants.ITEM_TOOLS);
                        break;
                    case 3:
                        setDefaultIcon();
                        new Handler().post(new Runnable() {
                            @Override
                            public void run() {
                                spaceNavigationView.changeItemIconAtPosition(itemIndex, R.drawable.ic_color_my_work_tab);
                                spaceNavigationView.changeItemTextColorAtPosition(itemIndex, getResources().getColor(R.color.color_mywork));

                            }
                        });
                        changeCurrentFragmentTo(Constants.ITEM_MY_WORK);
                        break;
                }
            }

            @Override
            public void onItemReselected(int itemIndex, String itemName) {
   //        Toast.makeText(MainActivity.this, itemIndex + " " + itemName, Toast.LENGTH_SHORT).show();

            }
        });

setDefaultIcon ()

private void setDefaultIcon() {
        spaceNavigationView.changeItemIconAtPosition(0, R.drawable.ic_template_tab, getResources().getColor(R.color.color_bg));
        spaceNavigationView.changeItemIconAtPosition(1, R.drawable.ic_category_tab, getResources().getColor(R.color.color_bg));
        spaceNavigationView.changeItemIconAtPosition(2, R.drawable.ic_tools_tab, getResources().getColor(R.color.color_bg));
        spaceNavigationView.changeItemIconAtPosition(3, R.drawable.ic_my_work_tab, getResources().getColor(R.color.color_bg));


    }

Thí dụ:

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.