Android BottomNavigationView一个选项卡,具有不同的未选择/选择的颜色

问题描述 投票:2回答:2

我正在尝试匹配这样的设计。。

enter image description here

请注意,“选定的标签颜色”为蓝色,但中间标签的图标应始终为绿色圆圈,中间带有白色时钟。

我已经尝试了很多东西。首先,尝试使用具有绿色圆圈和时钟PNG资源的图层列表XML资源以编程方式进行此操作,该资源根本无法使用。然后,我让设计师给了我完整的图标(时钟和绿色圆圈),但是现在我遇到了这个问题。

(未选中)

enter image description here

(已选择)

enter image description here

我无法在Google上找到正确的词来搜索以解决此问题。

最后,我需要选择的选项卡颜色为蓝色,但是我需要中心选项卡图标始终是实际的图标,并且没有其他颜色(本质上,它看起来必须与.png一样。

PS:我正在使用Xamarin.Forms,FreshMvvm和FreshTabbedFONavigationContainer。但是,通过Renderer,我可以直接访问BottomNavigationView和所有其他本机Android组件。因此,解决方案不必是Xamarin解决方案。 Java / kotlin解决方案也可以工作,我可以将其转换为Xamarin。

=========================>

编辑:

=========================>

因此,我在下面使用Andres Castro代码做了很多事情,但是我仍然遇到和以前一样的问题。使用下面的安德列斯(Andres)代码,我切换回使用FontAwesome作为图标(效果很好),但是这样做意味着我需要使用LayerDrawable创建圆圈/图标中心选项卡图标。

所以这就是我到目前为止的情况。

未选择的中心图标

enter image description here

选定的中心图标

enter image description here

如您所见,未选择时,中心图标仍为灰色,而被选中时,中心图标仍为蓝色(其他4个图标的正确选择/未选择的颜色)。

这是我到目前为止与中心图标有关的代码。

UpdateTabbedIcons

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);
    }
}

UpdateTabIcon

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;
}

正如您在为圆圈创建的GradientDrawable中看到的那样,我将其颜色设置为我的绿色(我有一个名为Resources的自定义类。这不是Android的Resources类。] >

所以这就是我被困住的地方。我将可绘制的圆设置为绿色,但是一旦在BottomNavigationView中,它的颜色将始终与其他图标的未选中/选中的颜色匹配。

希望克服最后一个问题。感谢您的帮助。

我正在尝试匹配这样的设计。请注意,“选定的选项卡颜色”是蓝色,但中间选项卡的图标应始终是绿色圆圈,中间带有白色时钟。我是...

由于您有权访问底部导航视图,因此每次切换页面时都可以“重绘”底部的工具栏。我们做了类似的事情,没有发现任何性能问题。

您首先希望通过订阅OnElementChanged中的页面更改来监视页面更改>

Element.CurrentPageChanged += ElementOnCurrentPageChanged;

然后在ElementOnCurrentPageChanged中,您可以遍历每个页面并获得该页面的菜单项

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);
    }
}

在我们的例子中,我们使用字体图标,因此我们每次绘制图标并设置颜色。

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);
}

我们还必须重写OnAttachedToWindow以确保从不同状态返回到应用程序时图标被重绘。

protected override void OnAttachedToWindow()
{
    UpdateTabbedIcons();

    base.OnAttachedToWindow();
}

您将不得不对其进行一些修改以适合您的用例,但我认为该方法应该可以满足您的需求。

我可以为您提供帮助:

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;
}
}

这是一个自定义的TabLayout,您可以看到我在扩展TabLayout类,创建TabLayout时,我调用了initItems方法,该方法添加了addTab并为其设置了自定义视图。

getTabView返回膨胀视图,您可以通过此视图看到>]

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

如果需要的话

<?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>

放大视图后,可以使用]来获取view元素。

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

您可以检查是否选中了带有选定布尔值的视图,在这种情况下,当索引为中心时,您需要忽略颜色开关。

当您单击TabLayout图标时,请不要忘记调用

setTagIndex();

如果不这样做,图像将不会重绘

android xamarin.forms xamarin.android bottomnavigationview freshmvvm
2个回答
2
投票

由于您有权访问底部导航视图,因此每次切换页面时都可以“重绘”底部的工具栏。我们做了类似的事情,没有发现任何性能问题。

您首先希望通过订阅OnElementChanged中的页面更改来监视页面更改>

Element.CurrentPageChanged += ElementOnCurrentPageChanged;

0
投票

我可以为您提供帮助:

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;
}
}

这是一个自定义的TabLayout,您可以看到我在扩展TabLayout类,创建TabLayout时,我调用了initItems方法,该方法添加了addTab并为其设置了自定义视图。

getTabView返回膨胀视图,您可以通过此视图看到>]

 LayoutInflater.from(context).inflate(R.layout.activity_main_tab_layout, null);
© www.soinside.com 2019 - 2024. All rights reserved.