I was following this article. Unfortunatelly, badge isn't drawn. Of course I changed invalidateOptionsMenu
method to supportInvalidateOptionsMenu
method.
I was checking the log, step by step and found out that draw
method in custom Drawable
named BadgeDrawable
is never called. Why is that?
I'm trying to use it in AppCompatActivity using Support Design Library version 23.0.1
I saw this answer but it seems to be out of date.
Is there anyone who managed to implement badger counter for MenuItem icon inside android.support.v7.widget.Toolbar
?
If the way shown in the article is wrong then could you suggest other way to achieve the result as in example below?:
Here is a setup inside my application:
LayerDrawable XML ic_filter_notifications.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/ic_filter_notification"
android:drawable="@drawable/ic_filter_grey600_18dp"
android:gravity="center"/>
<!-- set a place holder Drawable so android:drawable isn't null -->
<item android:id="@+id/ic_filter_badge"
android:drawable="@drawable/ic_filter_grey600_18dp">
</item>
</layer-list>
Menu that I use in the Toolbar menu_activity_main.xml
:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cobytu="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/menu_settings"
android:orderInCategory="100"
android:title="@string/menu_settings"
cobytu:showAsAction="never"/>
<item
android:id="@+id/menu_logout"
android:orderInCategory="1000000"
android:title="@string/menu_logout"
cobytu:showAsAction="never"/>
<item
android:id="@+id/action_filter"
android:title="@string/filters"
android:icon="@drawable/ic_filter_notifications"
cobytu:showAsAction="always"/>
<item
android:id="@+id/action_location"
android:icon="@drawable/ic_map_marker_radius_grey600_18dp"
android:title="@string/location"
cobytu:showAsAction="always"/>
</menu>
This is function sets the count int for new BadgeDrawable inside UsefulFunctions class - UsefulFunctions.java
:
public class UsefulFunctions {
private Context ctx;
public UsefulFunctions(Context context){
ctx = context;
}
public static void setBadgeCount(Context context, LayerDrawable icon,
int count) {
BadgeDrawable badge;
// Reuse drawable if possible
Drawable reuse = icon.findDrawableByLayerId(R.id.ic_filter_badge);
if (reuse != null && reuse instanceof BadgeDrawable) {
badge = (BadgeDrawable) reuse;
} else {
Log.d("mTAG", UsefulFunctions.class.getName()
+ " I'm creating new BadgeDrawable!");
badge = new BadgeDrawable(context);
}
badge.setCount(count);
icon.mutate();
Log.d("mTAG",
UsefulFunctions.class.getName() + " badge: " + badge.toString()
+ " count: " + count);
icon.setDrawableByLayerId(R.id.ic_filter_badge, badge);
}
}
This is the important scrap of my MainActivity where I invoke BadgeDrawable creation. I also show what's inside onCreate and in onOptionsItemSelected, may be needed - MainActivity.java
:
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, DialogFragmentFilters.FiltersRefreshInterface{
public String username;
//CollapsingToolbarLayout
private CollapsingToolbarLayout mCollapsingToolbarLayout;
//Toolbar
private Toolbar mToolbar;
//TabLayout
private TabLayout mTabLayout;
private ViewPager mPager;
private MyPagerAdapter mAdapter;
//NavigationDraver
private static final String SELECTED_ITEM_ID = "selected_item_id";
private static final String FIRST_TIME = "first_time";
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private NavigationView mNavigationView;
private int mSelectedId;
private boolean mUserSawDrawer = false;
private TextView mNavHeaderNameText;
private TextView mNavHeaderEmailText;
private DatabaseHandler db;
private UserFunctions userFunctions;
private AlertDialog.Builder dialogBuilder;
private AlertDialog alertDialog;
private JSONObject jsonLocation = new JSONObject();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
userFunctions = new UserFunctions();
db = new DatabaseHandler(getApplicationContext());
username = db.getUserDetails().get(DatabaseHandler.getKEY_USER_LOGIN());
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
setupToolbar();
setupTablayout();
mNavigationView = (NavigationView) findViewById(R.id.navigation_view);
mNavigationView.setNavigationItemSelectedListener(this);
View header = LayoutInflater.from(MainActivity.this).inflate(R.layout.nav_header, null);
mNavHeaderNameText = (TextView) header.findViewById(R.id.tv_nav_header_name);
mNavHeaderNameText.setText("Siema "+username+"!");
mNavHeaderEmailText = (TextView) header.findViewById(R.id.tv_nav_header_email);
mNavHeaderEmailText.setText(db.getUserDetails().get(DatabaseHandler.getKEY_USER_EMAIL()));
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,mToolbar, R.string.drawer_open, R.string.drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerToggle.syncState();
if (!didUserSeeDrawer()) {
showDrawer();
markDrawerSeen();
} else {
hideDrawer();
}
mSelectedId = savedInstanceState == null ? R.id.navigation_item_4 : savedInstanceState.getInt(SELECTED_ITEM_ID);
navigate(mSelectedId);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(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();
showActionDialog(id);
//noinspection SimplifiableIfStatement
switch (id) {
case R.id.menu_settings:
return true;
case R.id.menu_logout:
dialogBuilder = new AlertDialog.Builder(new ContextThemeWrapper(
MainActivity.this, R.style.Theme_AppCompat_Light_Dialog));
dialogBuilder
.setTitle(getResources().getString(R.string.logoutAlertTitle))
.setIcon(R.drawable.ic_logout).setMessage(getResources().getString(R.string.logoutAlertMessage)).setPositiveButton(getResources().getString(R.string.logoutAlertYesButton),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
((RelativeLayout) findViewById(R.id.fl_mainContent))
.animate()
.alpha(0f)
.setListener(
new AnimatorListenerAdapter() {
public void onAnimationEnd(
Animator animation) {
mDrawerLayout
.setVisibility(View.INVISIBLE);
mDrawerLayout
.setAlpha(1f);
mDrawerLayout
.animate()
.setListener(null);
}
});
userFunctions.logoutUser(getApplicationContext());
Intent i = new Intent(MainActivity.this, LoginActivity.class);
// MainActivity.this.deleteDatabase("cobytu_db");
startActivity(i);
finish();
}
})
.setNegativeButton(getResources().getString(R.string.logoutAlertNoButton),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
dialog.dismiss();
}
});
alertDialog = dialogBuilder.create();
alertDialog.show();
return true;
}
return false;
}
public int filterCounter = 0;
class FetchCountTask extends AsyncTask<Void, Void, Integer> {
@Override
protected Integer doInBackground(Void... params) {
// example count. This is where you'd
// query your data store for the actual count.
return 5;
}
@Override
public void onPostExecute(Integer count) {
setNotifCount(count);
}
}
private void setNotifCount(int count){
filterCounter = count;
supportInvalidateOptionsMenu();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_activity_main, menu);
MenuItem item = menu.findItem(R.id.action_filter);
LayerDrawable icon = (LayerDrawable) item.getIcon();
// Update LayerDrawable's BadgeDrawable
Log.d("mTag", "onCreateOptionsMenu: this: " + this.toString());
UsefulFunctions.setBadgeCount(this, icon, filterCounter);
return true;
}
@Override
public void onRefreshFilters(int counter) {
setupTablayout();
Toast.makeText(MainActivity.this, "List has been refreshed! " + counter, Toast.LENGTH_SHORT).show();
filterCounter = counter;
new FetchCountTask.execute();
}
}