Search code examples
androidandroid-appbarlayoutandroid-vectordrawable

Drawable Vector Icon defined in menu.xml doesn't show up in appBar?


Drawable vector icon in menu.xml doesnt show up in appBar, there are two of them, one is a search Icon, the other is a filter Icon. I cant figure out where I got it wrong. This is a snipet of my Activity:

static String query;
static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
Toolbar myToolbar;
SearchView searchView = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_search);
    //Set custom AppBar
    myToolbar = findViewById(R.id.search_toolbar);
    //myToolbar.inflateMenu(R.menu.menu_search);
    initToolBarMenuIcons();
    setSupportActionBar(myToolbar);

    myToolbar.setOnMenuItemClickListener(this);
    setupViews();

    //Check internet connection
    new InternetCheck(internet -> {
        //Display no internet Toast if there's no internet
        if (!internet) {
            Toast.makeText(this, "no internet", Toast.LENGTH_SHORT).show();
        }
    });
}

@MainThread
@SuppressLint("NewApi") //suppress warning, since using DrawableCompat to set tint
public void initToolBarMenuIcons() {
    myToolbar.inflateMenu(R.menu.menu_search);
    //Manually adding icon since it's a vector drawable and we can't currently inflate from XML into menuitems
    Drawable wrappedFilterIcon = DrawableCompat
            .wrap(Objects.requireNonNull(AppCompatResources
                    .getDrawable(getBaseContext(), R.drawable.ic_filter_list_white_24dp)));
    Drawable wrappedSearchIcon = DrawableCompat
            .wrap(Objects.requireNonNull(AppCompatResources
                    .getDrawable(getBaseContext(), R.drawable.ic_search_white_24dp)));
    //Tint it too
    DrawableCompat.setTint(wrappedFilterIcon, Color.WHITE);
    DrawableCompat.setTint(wrappedSearchIcon, Color.WHITE);
    //Set the tinted vector drawable to the item
    myToolbar.getMenu().findItem(R.id.action_filter).setIcon(wrappedFilterIcon);
    myToolbar.getMenu().findItem(R.id.action_search).setIcon(wrappedSearchIcon);
}
[snip...]

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is  present.
    getMenuInflater().inflate(R.menu.menu_search, menu);
    MenuItem searchItem = menu.findItem(R.id.action_search);
    searchView = (SearchView) searchItem.getActionView();
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            onArticleSearch(null);
            searchView.clearFocus();
            return true;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            return false;
        }
    });
    return super.onCreateOptionsMenu(menu);
}

This is the menu.xml where the item and icon source specified. I use app:srcCompat for icon path.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
    android:id="@+id/action_filter"
    app:showAsAction="always"
    app:srcCompat="@drawable/ic_filter_list_white_24dp"
    tools:ignore="MenuTitle"
    android:orderInCategory="2" />

<item android:id="@+id/action_search"
    android:orderInCategory="1"
    android:title="Search Article"
    app:srcCompat="@drawable/ic_search_white_24dp"
    app:showAsAction="always|collapseActionView"
    app:actionViewClass="android.support.v7.widget.SearchView" />

I imported the following libraries: implementation "com.android.support:support-vector-drawable:27.1.1" implementation "com.android.support:animated-vector-drawable:27.1.1"

and I set that in my app Gradle file:

android {
compileSdkVersion 27
defaultConfig {
    applicationId "com.realty.drake.newyorktimessearcher"
    minSdkVersion 16
    targetSdkVersion 27
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    vectorDrawables.useSupportLibrary true
}

Please help me guys


Solution

  • Seems like I dont understand your question. Try to set drawable to your menu like so:

      <item
            android:id="@+id/menuItem"
            android:icon="@drawable/yourdrawable"
            />
    

    Sorry bro, bellow text is about using animateddrawable in menu.

    Files with vector animation implement the Animatable interface and to start the animation, you need to request Drawable, bring it to Animatable and call the start () method. I do it in onOptionsItemSelected:

      override fun onOptionsItemSelected(item: MenuItem?): Boolean {
            when (item?.itemId) {
               ..........
                R.id.editNotification -> {
                    (item.icon as Animatable).start()
                }
            }
            return super.onOptionsItemSelected(item)
        } 
    

    For Java use:

    ((Animatable) item.getIcon()).start();
    

    But you may faced fith a problem I've faced: How to animate it backward. I don't have native solution, but you can do it like this: 1. Create drawable with backward animation 2. Implement AnimationCallback and on the end of animation switch those drawables. For example:

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
            menuInflater.inflate(R.menu.menu_edit_notification, menu)
            animDrawable = AnimatedVectorDrawableCompat.create(this, R.drawable.avd_edit_to_close)!!
            menu?.getItem(0)?.icon = animDrawable
            return true
        }
    
        override fun onOptionsItemSelected(item: MenuItem?): Boolean {
            when (item?.itemId) {
               ..............................
                R.id.editNotification -> {
                    animDrawable.registerAnimationCallback(object : Animatable2Compat.AnimationCallback() {
                        override fun onAnimationEnd(drawable: Drawable?) {
                            animDrawable = AnimatedVectorDrawableCompat.create(this@NotificationActivity, if (inEditMode) R.drawable.avd_edit_to_close else R.drawable.avd_close_to_edit)!!
                            inEditMode = !inEditMode
                            item.icon = animDrawable
                        }
                    })
                    animDrawable.start()
                }
            }
            return super.onOptionsItemSelected(item)
        }
    

    Where: animDrawable - is instance of AnimatedVectorDrawableCompat inEditMode - just my boolean flag Sorry, but for now I dont have time to write it in Java, but fill free to ask questions