更改 navigationView 的单个特定菜单项的背景颜色

Posted

技术标签:

【中文标题】更改 navigationView 的单个特定菜单项的背景颜色【英文标题】:Change background color of single specific menu items of navigationView 【发布时间】:2018-10-19 13:06:37 【问题描述】:

我想在导航抽屉内的 android 菜单中设置所有标题项的背景颜色。我的布局如下:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:title="TopItem" android:id="@+id/top_item1"> // Here i want to set the background
    <menu>
      <group>
        <item android:id="@+id/sub_item1"
            android:title="SubItem" /> // Here no background
      </group>
    </menu>
  </item>
  <item android:title="TopItem" android:id="@+id/top_item2">
    <menu>
      <group>
       <item android:id="@+id/sub_item2"
            android:title="SubItem" />
        <item android:id="@+id/sub_item3"
            android:title="SubItem" />
       <item android:id="@+id/sub_item4"
            android:title="SubItem" />
      </group>
    </menu>
</menu>

结果应该是这样的:

我发现我可以通过以下方式设置文本颜色:

MenuItem menuItem = navigationView.getMenu().findItem(R.id.menu_item);
SpannableString s = new SpannableString(menuItem.getTitle());
s.setSpan(new TextAppearanceSpan(this, R.style.TextAppearance), 0, s.length(), 0);

if (menuItem.getItemId()==R.id.nav_targets)            
  menuItem.setTitle(s); 

但是如何设置填充背景颜色呢?

【问题讨论】:

我不确定这是否有效...但是在 oncreateoptionMenu 中,您可以获取菜单项...从该菜单项中,您可以使用 ..menuItem.getActionView(); 获取视图,我们可以为该视图设置背景颜色.. 【参考方案1】:

更改单个特定菜单项的背景颜色

AFAIK 使用菜单这是不可能的,您需要创建自定义navigationView

当您使用 BackgroundColorSpan 为菜单项设置背景时,它只会将背景设置为菜单项标题而不是整个视图

输出使用 BackgroundColorSpan

使用 RecyclerView 试试这种方式

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_
    android:layout_
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_
        android:layout_ />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_
        android:layout_
        android:layout_gravity="start"
        android:fitsSystemWindows="true">

        <LinearLayout
            android:layout_
            android:layout_
            android:orientation="vertical">

            <include layout="@layout/nav_header_main" />

            <android.support.v7.widget.RecyclerView
                android:id="@+id/navRecyclerView"
                android:layout_
                android:layout_ />

        </LinearLayout>
    </android.support.design.widget.NavigationView>

</android.support.v4.widget.DrawerLayout>

MainActivity

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener 

    RecyclerView navRecyclerView;
    LinearLayoutManager layoutManager;
    ArrayList<NavigationDataModel> arrayList = new ArrayList<>();
    NavigationAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);

        navigationView.setNavigationItemSelectedListener(this);

        navRecyclerView = findViewById(R.id.navRecyclerView);
        navRecyclerView.setHasFixedSize(true);
        layoutManager = new LinearLayoutManager(this);
        navRecyclerView.setLayoutManager(layoutManager);

        initArray();

        adapter = new NavigationAdapter(this, arrayList);
        navRecyclerView.setAdapter(adapter);


    

    private void initArray() 

        NavigationDataModel model = new NavigationDataModel();
        model.setColor(ContextCompat.getColor(this, R.color.colorPrimary));
        model.setIcon(R.drawable.ic_menu_gallery);
        model.setTitle("Item 1");
        arrayList.add(model);


        NavigationDataModel model2 = new NavigationDataModel();
        model2.setColor(ContextCompat.getColor(this, R.color.colorRed));
        model2.setIcon(R.drawable.ic_menu_camera);
        model2.setTitle("Item 2");
        arrayList.add(model2);

        NavigationDataModel model3 = new NavigationDataModel();
        model3.setColor(ContextCompat.getColor(this, R.color.colorGreen));
        model3.setIcon(R.drawable.ic_menu_send);
        model3.setTitle("Item 3");
        arrayList.add(model3);

        NavigationDataModel model4 = new NavigationDataModel();
        model4.setColor(ContextCompat.getColor(this, R.color.colorPink));
        model4.setIcon(R.drawable.ic_menu_share);
        model4.setTitle("Item 4");
        arrayList.add(model4);

    

    @Override
    public void onBackPressed() 
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) 
            drawer.closeDrawer(GravityCompat.START);
         else 
            super.onBackPressed();
        
    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) 
            return true;
        

        return super.onOptionsItemSelected(item);
    

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) 
        // Handle navigation view item clicks here.
        int id = item.getItemId();


        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    

导航适配器

public class NavigationAdapter extends RecyclerView.Adapter<NavigationAdapter.ViewHolder> 

    Context context;
    ArrayList<NavigationDataModel> arrayList = new ArrayList<>();

    public NavigationAdapter(Context context, ArrayList<NavigationDataModel> arrayList) 
        this.context = context;
        this.arrayList = arrayList;
    

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) 
        View view = LayoutInflater.from(context).inflate(R.layout.custom_layout, parent, false);
        return new ViewHolder(view);
    

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) 

        holder.navIcon.setImageResource(arrayList.get(position).getIcon());
        holder.rootView.setBackgroundColor(arrayList.get(position).getColor());
        holder.navTitle.setText(arrayList.get(position).getTitle());
    

    @Override
    public int getItemCount() 
        return arrayList.size();
    

    public class ViewHolder extends RecyclerView.ViewHolder 
        ImageView navIcon;
        TextView navTitle;
        LinearLayout rootView;

        public ViewHolder(View itemView) 
            super(itemView);
            rootView = itemView.findViewById(R.id.rootView);
            navIcon = itemView.findViewById(R.id.navIcon);
            navTitle = itemView.findViewById(R.id.navTitle);
        
    

导航数据模型

public class NavigationDataModel 
    private int icon, color;
    private String title;

    public int getIcon() 
        return icon;
    

    public void setIcon(int icon) 
        this.icon = icon;
    

    public int getColor() 
        return color;
    

    public void setColor(int color) 
        this.color = color;
    

    public String getTitle() 
        return title;
    

    public void setTitle(String title) 
        this.title = title;
    

输出

【讨论】:

【参考方案2】:

您可以通过BackgroundColorScan更改文本的背景颜色。

  NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
            MenuItem menuItem = navigationView.getMenu().findItem(R.id.your_menu_item_id);
            Spannable spannable = new SpannableString(menuItem.getTitle());
            spannable.setSpan(new BackgroundColorSpan(0xFF00CCCC), 0, menuItem.getTitle().length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            menuItem.setTitle(spannable);

【讨论】:

【参考方案3】:

只需在DrawerLayout 中使用RecyclerView 而不是NavigationView

【讨论】:

【参考方案4】:
navigationView.ItemBackground = new ColorDrawable(Android.Graphics.Color.Green);

这可能会有所帮助。

【讨论】:

以上是关于更改 navigationView 的单个特定菜单项的背景颜色的主要内容,如果未能解决你的问题,请参考以下文章

NavigationView更改菜单icon和title颜色变化效果

如何更改 NavigationView 中的分隔符颜色?

更改导航抽屉中菜单项的文本颜色

如何绘制 NavigationView 页面的内容?

DrawerLayout 和 NavigationView 的使用

在NavigationView中更新SelectionIndicator的颜色