ActionView set to an item in support NavigationVie

2019-05-22 14:07发布

I'm using the support NavigationView in my navigation drawer to display menu of items.

<android.support.design.widget.NavigationView
    android:id="@+id/drawer_navigation"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:background="@drawable/drawable_background"
    app:headerLayout="@layout/drawer_header"
    app:itemBackground="@drawable/drawer_item_background"
    app:itemIconTint="@color/drawer_item"
    app:itemTextColor="@color/drawer_item"
    app:menu="@menu/drawer"
    app:theme="@style/Text.DrawerItem"/>

I want to display a counter of connection requests next to a menu item.

I've tried to set the actionLayout in XML menu definition like this

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">

  <group android:checkableBehavior="single">
    ...
    <item
        android:id="@+id/navigation_requests"
        android:icon="@drawable/ic_swap_horiz_24dp"
        android:title="@string/connect_menu_connection_requests"
        app:actionLayout="@layout/connection_request_counter"
        app:showAsAction="always"/>
    ...
  </group>
</menu>

Layout of the ActionView connection_request_counter.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="wrap_content"
      android:layout_height="match_parent"
      android:gravity="center_vertical"
      android:textColor="@color/brand_blue"
      android:text="5"/>

But at this point I can't see number 5 next to the item.

I've tried to set ActionLayout programatically as well:

MenuItemCompat.setActionView(mMenu.findItem(R.id.navigation_requests), R.layout.connection_request_counter);

But still no luck.

I can get reference to the TextView like

final TextView connectionRequestCounterView
            = (TextView) MenuItemCompat.getActionView(mMenu.findItem(R.id.navigation_requests));

Which actually returns a TextView instance, but even if I set a text to it, I can't see anything in the layout. Could that be related to the fact that I'm styling the menu items? (I set text color, tint and background of the menu items)

Here are my styles:

<style name="Text.DrawerItem">
    <item name="android:textColor">@color/text_color_dark_grey</item>
    <item name="android:textSize">@dimen/text_size_default</item>
    <item name="android:clickable">false</item>
    <item name="android:textColorLink">@color/text_color_dark_grey</item>
    <item name="fontPath">@string/font_aller_light</item>
    <!--<item name="android:background">@color/background_activity_default</item>-->
    <!--<item name="background">@color/background_activity_default</item>-->
</style>

drawer_item_background.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <!--To override the default grey background for selected item-->
  <item android:drawable="@android:color/transparent" android:state_checked="true"/>
  <item android:drawable="@android:color/transparent"/>
</selector>

and drawer_drawablbe.xml:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

  <item>
    <shape android:shape="rectangle">
        <solid android:color="@color/background_activity_default"/>
    </shape>
  </item>
  <item
    android:bottom="24dp"
    android:left="16dp">
      <bitmap
        android:gravity="left|bottom"
        android:src="@drawable/my_drawer_logo"/>
  </item>

</layer-list>

Where @drawable/my_drawer_logo is a PNG in different densities.

Any other ideas why I can't see the action view?

2条回答
老娘就宠你
2楼-- · 2019-05-22 14:24

I can change the text of the counter easily enough. However, The text view that I use is within a LinearLayout, and it has an android:id as well (I tried this without the LinearLayout without issue):

 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/textCounter"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:textColor="@color/colorPrimary"
        android:text="5"/>
</LinearLayout>

Given that, I am able to see, access and modify the text view within the main activity using the following :

TextView countText = (TextView)findViewById(R.id.textCounter);

countText.setText("6");

Of course, I'm using a trivial method to calculate the value, just setting it to the value "6", but, I don't know what your counter structure actually looks like, and those are not the main concern of your question.

The issue with your ability to view the counter number remains a mystery. See my questions above and we'll hammer out that element as well.

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

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        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.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
}
查看更多
劳资没心,怎么记你
3楼-- · 2019-05-22 14:31

I eventually found out what was causing the issue. For NavigationView to work properly with action views, you must use AppCompat support library version 23.1

So instead of

compile 'com.android.support:appcompat-v7:22.3.0'

I had to update to

compile 'com.android.support:appcompat-v7:23.1.1'

which made the trick and the action view in navigation drawer's navigation view started showing properly, exactly as I wanted.


When updating to the new AppCompat version I came across several more problems like ClassNotFoundException showing up when starting the app, which I fixed by updating all com.android.support libraries to the latest version:

compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'com.android.support:support-annotations:23.1.1'
...

Then I was still getting NullPointerException in my header layout set to the NavigationView. If you're setting app:headerLayout="@layout/drawer_header" or similarly in code, in AppCompat version 22 it was possible to get the header view by findViewById().

AppCompat version 23, though, uses RecyclerView for all the items including the header view, so the way to get reference to its views is following:

 mHeaderView = navigationView.getHeaderView(HEADER_INDEX);

Where HEADER_INDEX is most likely 0 if you're not adding multiple headers.

查看更多
登录 后发表回答