Add badgeview on ActionBarSherlock MenuItem - android

I would like to add a badge over ActionBar MenuItem
But the digit icon didn't shows.
Here's what I have done so far
public class Main extends SherlockFragmentActivity
{
private Fragment menuFrag=null;
private MenuItem menuMsg=null;
private BadgeView badge=null;
#Override
protected void onCreate(Bundle savedInstanceState)
{
//Do my stuff...
initUI();
}
private void initUI()
{
FragmentManager fm=getSupportFragmentManager();
FragmentTransaction ft=fm.beginTransaction();
menuFrag=fm.findFragmentByTag("f1");
if(menuFrag==null)
{
menuFrag=new MenuFragment();
ft.add(menuFrag, "f1");
}
ft.commit();
// badge=new BadgeView(Main.this, (View)menuMsg); //Not working
badge=new BadgeView(Main.this, menuMsg.getActionView()); //Not working as well
badge.setBackgroundResource(R.drawable.badge_ifaux);
badge.setTextSize(10);
badge.setBadgeMargin(2);
badge.setText("1");
badge.show();
}
private class MenuFragment extends SherlockFragment
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
menu.add("Cloud").setIcon(R.drawable.icon_cloud).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menu.add("List").setIcon(R.drawable.icon_list).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menuMsg=menu.add("Msg");
menuMsg.setIcon(R.drawable.icon_msg).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
Toast.makeText(Main.this, "Got click: " + item.toString(), Toast.LENGTH_SHORT).show();
return true;
}
}
}
Where do I did wrong ?

RRTW,
The library you are using doesn't support badging Actionbar menu items natively.
https://github.com/jgilfelt/android-viewbadger/commit/e08c3a78cb92c0c8587790b15e73434f972912cf
However, it doesn't mean you can't get it to work.
The setup is going to be as follows (this assumes you already have the viewbager library setup in your project)
(1) onCreateOptionsMenu --> (2) Add a R.menu.your_place_holder_item --> (3) setActionView with custom xml layout --> (4) findViewById of the MenuItem object to get your button/view to set the badge.
1) setup your onCreateOptionsMenu and create a the R.menu.actionbar_menu_messages
R.menu.actionbar_menu_messages:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
>
<item android:showAsAction="ifRoom" android:icon="#drawable/action_bar_pk_content_email"
android:id="#+id/menuMessages" android:title="More"></item>
</menu>
onCreateOptionsMenu:
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getSupportMenuInflater(); //If you are using the support library otherwise use: getMenuInflater();
inflater.inflate(R.menu.actionbar_menu_messages, menu);
this.setupMessagesBadge(menu.findItem(R.id.menuMessages)); //This is part of step 2
return true;
}
2) Defined the common_messages_indicator
R.layout.common_messages_indicator:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="64dp"
android:layout_height="fill_parent"
android:paddingTop="10dp"
android:gravity="center">
<ImageView
android:id="#+id/imgMessagesIcon"
android:layout_width="32dp"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:scaleType="fitCenter"
android:src="#drawable/messages_button"
android:background="#android:color/transparent"
android:focusable="false"
/>
</FrameLayout>
perform setActionView to add your custom xml layout to the ActionView
private void setupMessagesBadge(final MenuItem msgItem) {
msgItem.setActionView(R.layout.common_messages_indicator);
if(msgItem.getActionView().findViewById(R.id.imgMessagesIcon) != null)
{
ImageView imgMessagesIcon = ((ImageView)msgItem.getActionView().findViewById(R.id.imgMessagesIcon));
imgMessagesIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Your click on the action bar item will be captured here
}
});
int badgeCnt = 20;// Add your count here
if(messageCenterBadge == null && badgeCnt > 0)
{
//imgMessagesIcon is the imageview in your custom view, apply the badge to this view.
messageCenterBadge = new BadgeView(this, imgMessagesIcon);
messageCenterBadge.setBadgePosition(BadgeView.POSITION_TOP_RIGHT);
messageCenterBadge.setBadgeMargin(0);
messageCenterBadge.setTextSize(12);
messageCenterBadge.setText(String.valueOf(badgeCnt));
messageCenterBadge.show();
}
else if(messageCenterBadge != null && badgeCnt > 0 )
{
messageCenterBadge.setText(String.valueOf(badgeCnt));
messageCenterBadge.show();
}
else if(messageCenterBadge != null && badgeCnt == 0) {
messageCenterBadge.hide();
}
}
}

Related

Switch onCheckedChangedListner not registering clicks inside toolbar menu

I have a switch in my app toolbar to provide an option to the user to change the language.
When I am using the switch, the onCheckedChanged method is not working.
Further, it looks to me that onOptionsItemSelected is also not being hit as I don't see any log message on the screen.
Please note that the app is not crashing when I use the switch.
The clicks on options present inside the overflow menu are working properly. I am getting the log in those cases.
Switch aSwitch;
RelativeLayout langSwitch;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
context = this;
// Removed non relevant code here.
}
#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_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
Log.d("tag_id",String.valueOf(id));
langSwitch = findViewById(R.id.app_bar_switch);
aSwitch = langSwitch.findViewById(R.id.langSwitch);
aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (!b){
//Language1 code
Toast.makeText(context,"Language1 Selected",Toast.LENGTH_SHORT).show();
}else{
//Language2 code
Toast.makeText(context,"Language2 Selected",Toast.LENGTH_SHORT).show();
}
}
});
if (id == R.id.action_settings) {
return true;
}
if (id == R.id.savedPost){
Intent intent = new Intent(this,SavedPost.class);
startActivity(intent);
}
return super.onOptionsItemSelected(item);
}
Below is my menu_main.xml
<menu 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"
tools:context="com.app_name.android.app_name.MainActivity">
<item
android:id="#+id/app_bar_switch"
android:orderInCategory="2"
android:title=""
app:actionLayout="#layout/switch_item"
app:showAsAction="always" />
<item
android:id="#+id/action_settings"
android:orderInCategory="100"
android:title="#string/action_settings"
app:showAsAction="never" />
<item
android:id="#+id/savedPost"
android:checkable="false"
android:orderInCategory="4"
android:title="#string/saved_post" />
</menu>
This is my layout file for switch item.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Switch
android:id="#+id/langSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textOff="#string/switch_text_off"
android:textOn="#string/switch_text_on"
android:focusable="true"
android:clickable="true"/>
</RelativeLayout>
Additional information.
If I create another menu item (code below) with showAsAction 'always' and click on this once, now when I use the switch the Toast message comes. I am clueless here as to why is it not happening for the first time. Also, how do I make it work without this menu item.
<item
android:id="#+id/english"
android:orderInCategory="3"
android:title="#string/switch_text_on"
app:showAsAction="always" />
To inflate an external layout over ActionBar that seems to first creating a view that holds your ChildView for your layout
like Example
RelativeLayout item = (RelativeLayout)findViewById(R.id.item);
View child = getLayoutInflater().inflate(R.layout.child, null);
item.addView(child);
Try this in your code
Switch aSwitch;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
View sw = menu.findItem(R.id.app_bar_switch).getActionView();
aSwitch = (Switch) sw.findViewById(R.id.langSwitch);
aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (!b){
//Language1 code
Toast.makeText(context,"Language1 Selected",Toast.LENGTH_SHORT).show();
}else{
//Language2 code
Toast.makeText(context,"Language2 Selected",Toast.LENGTH_SHORT).show();
}
}
});
return true;
}
Try
(compoundButton.isChecked())
In boolean
Or
just try another version of setonCheckedChangedListner
Example:
aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){#Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { if (!compoundButton.isSelected()) { Log.i("Yeah" , "Is Not Selected"); invertLock(-1); } else { if (Utilities.isLockEnabled(context)) { Log.i("Yeah" , "Is Locked"); Utilities.showLockEnabled(context); } else { Log.i("Yeah" , "Is Not Locked"); invertLock(1); } } }

SearchView Menu Item Not Overriding Custom AppCompatToolbar

I'm working to implement a SearchView on my Fragment's RecyclerView as shown here. When the user taps the search button I want the Menu Item for the SearchView to Override the toolbar and display the area for them to search. If I don't use my custom style for the toolbar it works fine but when I do it get the images below.
Here is what I am currently getting:
This is the class that the EventListActivity inherits from:
public abstract class SingleFragmentActivity extends AppCompatActivity {
protected abstract Fragment createFragment();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.eventcalendar_activity_fragment);
// Manages our fragments. We can call it to add a fragment to an activity in code
FragmentManager fm = getSupportFragmentManager();
// Check if fragment of R.id already exits
// The FragmentManager saves out the list of fragments on rotation destruction or memory reclaim
Fragment fragment = fm.findFragmentById(R.id.fragment_container);
// If the the fragment does not exist, create it
if(fragment == null) {
fragment = createFragment();
// Create a new fragment transaction, include one add operation in it, and then commit it
fm.beginTransaction().add(R.id.fragment_container, fragment).commit();
}
}
}
This creates the fragment that manages and works with the RecyclerView:
public class EventListActivity extends SingleFragmentActivity {
#Override
protected Fragment createFragment() {
// Setting arguments for the new fragment created from the intent from EventFeedResultWrapper
EventListFragment fragment = new EventListFragment();
fragment.setArguments(getIntent().getExtras());
return fragment;
}
}
Fragment that holds the RecyclerViewthat the SearchView will interface with. This is where the search menu button is inflated. It is where I've been trying to modify the toolbar:
public class EventListFragment extends Fragment {
private RecyclerView mEventRecyclerView;
private EventAdapter mAdapter;
// Telling the FragmentManager that it is
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
((AppCompatActivity)getActivity()).getSupportActionBar().setCustomView(R.layout.action_bar_center);
View sabView = ((AppCompatActivity)getActivity()).getSupportActionBar().getCustomView();
TextView titleTxtView = (TextView) sabView.findViewById(R.id.action_bar_title);
titleTxtView.setText("Events Calendar");
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayShowCustomEnabled(true);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.eventcalendar_fragment_event_list, container, false);
mEventRecyclerView = (RecyclerView) view.findViewById(R.id.event_recycler_view);
// RecyclerView requires a layout manager to work, layout manager is in charge of position items on screen
mEventRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
updateUI();
return view;
}
// Populate the menu instance
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.eventcalendar_menu, menu);
}
// When we edit a EventActivity this saves it back to the EventListActivity
// onResume over onStart because we cannot assume the activity will be stopped
// when another activity is in front of it. If the other activity is transparent
// then the activity might just get paused. If it is paused then onStart() will not be called
// but on resume will be called.
// NOTE: In general onResume() is the safest place to take action to update a fragment's view
#Override
public void onResume() {
super.onResume();
updateUI();
}
private void updateUI() {
// Read in the events saved in to EventFeedResultWrapper by the Async task in ParseEventFeedTask
EventFeedResultWrapper wrapper = (EventFeedResultWrapper) getArguments().getSerializable(ParseEventFeedTask.EXTRA_RESULTS_LIST);
// Make sure wrapper is not null, it will NEVER be null
if(wrapper == null){
throw new RuntimeException("Error: The wrapper is null!");
}
// Get all the events from the wrapper/serializable
List<Event> events = wrapper.getEventFeedResults();
// Gets the context that we don't use rofl
EventCal eventCal = EventCal.get(getActivity());
// Add all the events we got from the wrapper to our event manager eventCal
eventCal.addEvents(events);
// Check to see if the EventAdapter is already setup
if(mAdapter == null) {
mAdapter = new EventAdapter(events);
mEventRecyclerView.setAdapter(mAdapter);
} else {
mAdapter.notifyDataSetChanged();
}
}
//Adapter here - removed code since it doesn't do anything with the toolbar
//RecycleView onClickLister - removed code since it doesn't do anything with the toolbar
}
This is the custom XML Style
<?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="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/action_bar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#ffffff"
android:textSize="24dp"/>
</LinearLayout>
Event Menu XML
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/action_search"
android:title="Search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/>
</menu>
Did you missed android:orientation="vertical". The text is displaying vertically. You want horizontal right?
Oh nvm i didn't understood it at first. The problem must be the inflating of the custom view, for some reason it seems it keeps the original view there and inflated it somewhere else. Give me 1s i'll update the answer when i find the issue
Check here: getSupportActionBar().setCustomView(view) does not fill entire actionbar
Similar problem. First and Second answer
EDIT2: Remove the code from EventListFragment onCreate. You don't need to inflate a searchView, you can use the default one.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_main, menu);
super.onCreateOptionsMenu(menu, inflater);
setOptionsMenu(menu);
}
public void setOptionsMenu(Menu menu) {
MenuItem search = menu.findItem(R.id.search);
SearchView searchView;
/**
* Setup the SearchView
*/
SearchManager searchManager = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
final boolean[] modifiedOriginal = {false};
searchView = (SearchView) search.getActionView();
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(((Activity) context).getComponentName()));
MenuItemCompat.setOnActionExpandListener(search, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
...
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
...
return true;
}
});
final EditText et = ButterKnife.findById(searchView, android.support.v7.appcompat.R.id.search_src_text);
et.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
String s = editable.toString();
if (!s.equals("") && !s.equals(" ")) {
...
}
}
});
ButterKnife.findById(searchView, android.support.v7.appcompat.R.id.search_close_btn).setOnClickListener(
view -> {
...
et.setText("");
}
);
}
}
You can leave your menu xml as it is.

Menu item from fragment can not trigger onOptionsItemSelected in activity

I want my activity to handle click on options menu items from fragment. and menu item from fragment showed at activity's menu. However, onOptionsItemSelected is not triggered when I click the button. I followed instructions from [this]([1]: (Deprecated) Fragment onOptionsItemSelected not being called) but it not work. The code is as following:
Activity:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
case R.id.action_save:
L.d("appointment: action save clicked");
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Fragment:
#Override
protected void doOnCreate(Bundle savedInstanceState) {
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.make_appointment_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
Menu:
<?xml version="1.0" encoding="utf-8"?>
<menu 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"
tools:context=".appointment.MakeAppointmentActivity">
<item
android:id="#+id/action_save"
android:title="#string/action_save"
app:actionLayout="#layout/menu_item_save_btn"
app:showAsAction="always" />
</menu>
edit:
The fragment is added through transaction, I guess it was the culprit?
onCreate from Activity:
#Override
protected void doOnCreate(Bundle savedInstanceState) {
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(R.string.make_appointment_edit_title);
}
// 创建并初始化Fragment
// savedInstanceState != null的时候,是指onSaveInstanceState被调用,此时UI部分会被恢复
if (savedInstanceState == null && getIntent() != null) {
String buyerName = getIntent().getStringExtra(EXTRA_BUYER_NAME);
String listingTitle = getIntent().getStringExtra(EXTRA_LISTING_TITLE);
String appointmentStatus = getIntent().getStringExtra(EXTRA_APPOINTMENT_STATUS);
float oppositeUserLatitude
= (float) getIntent().getDoubleExtra(EXTRA_LOCATION_LATITUDE, DEFAULT_UNKNOW_LATITUDE);
float oppositeUserLongitude
= (float) getIntent().getDoubleExtra(EXTRA_LOCATION_LONGITUDE, DEFAULT_UNKNOW_LONGITUDE);
MakeAppointmentFragment makeAppointmentFragment
= MakeAppointmentFragment.newInstance(buyerName, listingTitle
, appointmentStatus, oppositeUserLatitude, oppositeUserLongitude);
getSupportFragmentManager().beginTransaction()
.replace(R.id.make_appointment_fragment_placeholder, makeAppointmentFragment)
.commit();
}
}
I think you should override public boolean onOptionsItemSelected (MenuItem item) inside your Fragment if I do not miss remember. In case of you want to handle it in your Activity, cast and call ((YourActivity)getActivity). onOptionsItemSelected(item); inside your overrided onOptionsItemSelected fragment.

how to get the action bar button? findviewbyid seems doesn't work

Suppose I have two buttons, one is an action button which is in the action bar(#+id/button1). And another is common button in the layout(#+id/button2).
How can I set the button1 disabled when i click the button2?
findViewById(button1) seems not work. it will return null.
this is my menu xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/button1"
android:title="submit"
android:showAsAction="always" />
</menu>
and this is my mainacticity:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.my, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.button1 ) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
button1 = (Button) findViewById(R.id.button1);/*which return null*/
button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
button1.setEnabled(false);/*what i failed to do*/
}
});
}
1.Create a variable MenuItem in your Activity class
MenuItem menuItem;
2. Find your variable in onCreateOptionsMenu
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
menuItem = menu.findItem(R.id.item_circuit);
return super.onCreateOptionsMenu(menu);
}
Disable the item in your buttonClick method
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
menuItem.setEnabled(false);
}
});
Try this
public void button1click(View v)
{
Button button2=(Button)getActionBar().getCustomView().findViewById(R.id.button2);
button2.setClickable(false);
button2.setEnabled(false);
}
You have to inflate the layout/views before using findViewById.
Like that:
private Toolbar toolbar;
// Set a Toolbar to replace the ActionBar.
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
cartLayout = (RelativeLayout) toolbar.findViewById(R.id.rl_cart);
Your toolbar layout would be like this:
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right">
<RelativeLayout
android:id="#+id/rl_cart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:padding="5dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:src="#drawable/ic_cart" />
</RelativeLayout>
</RelativeLayout>
You can find more answer here:
How can I implement custom Action Bar with custom buttons in Android?
How to set two custom actionbar button in left and right in android?

How to change the ActionBar menu item's icon dynamically

I want to change the menu item's icon dynamically as I get notification from a server. However, I'm getting a NullPointerException when the codes to change the menu item's icon run.
Codes I used to change the menu item's icon are defined in the onCreatOptionsMenu method as follow:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// getMenuInflater().inflate(R.menu.main, menu);
this.menu = menu;
if (mDrawerLayout != null && isDrawerOpen())
showGlobalContextActionBar();
MenuInflater menuInflater = this.getMenuInflater();
menuInflater.inflate(R.menu.notification, menu);
return super.onCreateOptionsMenu(menu);
}
}
and in the updateCount method, I am changing the icon as follow:
public void updateCount(int count) {
hot_count = count;
System.out.println("Value of count: " + count);
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
if (hot_count > 0) {
if(hot_count>0)
{
if (menu != null) {
MenuItem item = menu.findItem(R.id.menu_hotlist);
if (item != null) {
item.setIcon(R.drawable.ic_notification1);
}
}
}
}
}
});
}
Here is my menuitem "notification" file:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<item android:id="#+id/menu_hotlist"
android:actionLayout="#layout/action_bar_notification_icon"
android:showAsAction="always"
android:icon="#drawable/ic_notification"
android:title="Notification" />
</menu>
Here's my logcat:
01-20 15:03:29.811: E/AndroidRuntime(10318): java.lang.NullPointerException
01-20 15:03:29.811: E/AndroidRuntime(10318): at com.xsinfosol.helpdesk_customer.TAB_Activity$3.run(TAB_Activity.java:294)
01-20 15:03:29.811: E/AndroidRuntime(10318): at android.os.Handler.handleCallback(Handler.java:730)
01-20 15:03:29.811: E/AndroidRuntime(10318): at android.os.Handler.dispatchMessage(Handler.java:92)
01-20 15:03:29.811: E/AndroidRuntime(10318): at android.os.Looper.loop(Looper.java:137)
01-20 15:03:29.811: E/AndroidRuntime(10318): at android.os.HandlerThread.run(HandlerThread.java:61)
01-20 15:04:04.881: I/System.out(11629)
Please help.
Looks like menu.getItem(index) is returning null because menu was not inflated ( you have check mDrawerLayout != null && isDrawerOpen()) or you might have index that doesn't exists. Instead of relying on menu item index you can use resource id, also do check for null:
if (menu != null) {
MenuItem item = menu.findItem(R.id.your_menu_action);
if (item != null) {
item.setIcon(R.drawable.ic_notification1);
}
}
Update: based on you code i did example below that works. You can use it as base or for comparing to find why your code is not working. I don't know how #layout/action_bar_notification_icon looks like so in your case might be problem there.
In this example ic_menu_delete is replaced by ic_menu_edit once you click on menu item.
test_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/test_menu_item"
android:icon="#android:drawable/ic_menu_delete"
android:showAsAction="always"
android:title="Item1"/>
</menu>
Code:
private Menu menu;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
this.menu = menu;
getMenuInflater().inflate(R.menu.test_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.test_menu_item:
changeIcon();
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
changeIcon() simulates your updateCount()
public void changeIcon(){
runOnUiThread(new Runnable() {
#Override
public void run() {
if (menu != null) {
MenuItem item = menu.findItem(R.id.test_menu_item);
if (item != null) {
item.setIcon(android.R.drawable.ic_menu_edit);
}
}
}
});
}
I've also had the same problem and #Dario answers works like a charm as long as you don't call invalidateOptionsMenu()
To solve this, I assign the drawable resource to a variable and call invalidateOptionsMenu() where I want to change the icon and I set the icon in onCreateOptionsMenu(). The code should be like this:
private int drawableResourceId = R.drawable.default_menu_icon;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.test_menu, menu);
menu.findItem(R.id.change_menu_item_icon).setIcon(drawableResourceId);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.change_menu_item_icon:
drawableResourceId = R.drawable.changed_menu_icon;
invalidateOptionsMenu();
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
I've had the same problem. Please make sure you have the following in your menu item (an icon and showAsAction set to always) :
android:icon="#android:drawable/ic_menu_delete"
app:showAsAction="always"
There are 3 steps:
define a global MenuItem variable .
in onCreateOptionsMenu method assign your value (the target
menu) to it.
change the icon when required.
public class NotificationActivity extends BaseActivity {
//#1
Menu globalMenuItem;
//other variables
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.notification_menu, menu);
//#2
globalMenuItem= menu.add(Menu.NONE,menuId, Menu.NONE, title);
globalMenuItem.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS)
.setIcon(R.drawable.notification_icon_1);
//other menu items
}
//#3 call this when required
private void changeIcon(){
globalMenuItem.setIcon(R.drawable.notification_icon_2);
}
//...
}
As the docs state here, you should use onPrepareOptionsMenu() for any menu changes during the runtime of the Activity. It gets invoked whenever you call invalidateOptionsMenu().
Summary:
Do the initialization of the menu in onCreateOptionsMenu()
Whatever needs to be updated dynamically goes in onPrepareOptionsMenu()
Call invalidateOptionsMenu() when you have detected a change and want to update the options menu

Categories

Resources