I use the new NavigationView in one of my recent projects. However I have a problem for the update data.
Previously, I used a ListView in my DrawerLayout and when I needed to change my data I called notifyDataSetChanged() method of my Adapter.
Currently NavigationView does not notifyDataSetChanged() method and when I want to update an item on my menu nothing is happening, for example:
Menu menuAccount = navigationView.getMenu().findItem(R.id.drawer_item_account).getSubMenu();
menuAccount.findItem(R.id.drawer_item_login).setVisible(!isLoggedIn);
Do you have a solution ? Thanks you for your help.
UPDATE: This was fixed in v23.0.0 so you don't need to do anything by youself, just update your dependency. Got from this answer: https://stackoverflow.com/a/32181083/2489474
Old solution (just to see how stupid it could be):
But I've found working solution in this answer https://stackoverflow.com/a/30604299/2489474. It uses reflection to call updateMenuView(boolean) of NavigationView's presenter.
I've modified code from the answer for my purposes. Check also a method from the answer and choose which one is better for you.
//HACK
private void updateNavigationView() {
try {
Field presenterField = NavigationView.class.getDeclaredField("mPresenter");
presenterField.setAccessible(true);
((NavigationMenuPresenter) presenterField.get(navigationView_)).updateMenuView(false);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
P.S. it is interesting that updateMenuView ignores a value was given to it.
#Moinkhan Thanks you for your helper but doesn't work for me. Here my menu_drawer.xml
<group
android:checkableBehavior="single"
android:id="#+id/group1">
<item
android:id="#+id/drawer_item_publications_list"
android:icon="#drawable/ic_drawer_publications_24dp"
android:title="#string/drawer_menu_item_publications" />
</group>
<group android:id="#+id/drawer_group_account">
<item
android:title="#string/drawer_menu_sub_item_account"
android:id="#+id/drawer_item_account">
<menu>
<item
android:icon="#drawable/ic_drawer_login_24dp"
android:id="#+id/drawer_item_login"
android:title="#string/drawer_menu_item_login" />
<group
android:id="#+id/group_actions_user">
<item
android:icon="#drawable/ic_drawer_add_publication_24dp"
android:id="#+id/drawer_item_add_publication"
android:title="#string/drawer_menu_item_add_publication" />
<item
android:icon="#drawable/ic_drawer_my_publications_24dp"
android:id="#+id/drawer_item_my_publications"
android:title="#string/drawer_menu_item_my_publications" />
<item
android:icon="#drawable/ic_drawer_edit_profil_24dp"
android:id="#+id/drawer_item_edit_profil"
android:title="#string/drawer_menu_item_edit_profil" />
<item
android:icon="#drawable/ic_drawer_delete_account_24dp"
android:id="#+id/drawer_item_delete_account"
android:title="#string/drawer_menu_item_delete_account" />
<item
android:icon="#drawable/ic_drawer_logout_24dp"
android:id="#+id/drawer_item_logout"
android:title="#string/drawer_menu_item_logout" />
</group>
</menu>
</item>
</group>
And my method to update my NavigationView
private void setUpNavigationDrawer()
{
boolean isLoggedIn = sessionManager.isLoggedIn();
navigationView.getMenu().findItem(R.id.drawer_item_account).getSubMenu().findItem(R.id.drawer_item_login).setVisible(!isLoggedIn);
navigationView.getMenu().findItem(R.id.drawer_item_account).getSubMenu().setGroupVisible(R.id.group_actions_user, isLoggedIn);
}
After some operations I called setUpNavigationDrawer() but the menu was not updated !
Instead of referencing group and then finding a item from that group and setting it's visibility try to reference the item directly like this ...
navView.getMenu().findItem(R.id.drawer_item_login).setVisible(!isLoggedin);
navView.getMenu().findItem(R.id.drawer_item_account).getSubMenu().setGroupVisible(R.id.group_actions_user, !isLoggedin);
It works for me. I hope it helps you.
Related
I have two sensor connected with my android app. Both apps are connecting over BLE and I get two types of data from these sensors.
Sensor Data
Power Value
To show the power status, I followed a tutorial to create the progressbar inside actionbar menu as follows.
theme.xml
<!-- Power Progress Theme -->
<style name="PowerProgressBar">
<item name="android:indeterminateOnly">false</item>
<item name="android:progressDrawable">#drawable/ic_action_power_progress</item>
</style>
layout_power_progress.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
style="#android:style/Widget.ActionButton">
<ProgressBar
android:id="#+id/powerProgress"
style="#style/PowerProgressBar"
android:layout_width="24dp"
android:layout_height="24dp"
android:visibility="visible"
android:layout_gravity="center" />
</FrameLayout>
menu/main.xml
<item
android:id="#+id/action_power_sensor_1"
android:title="#string/action_power_sensor_1"
app:actionLayout="#layout/layout_power_progress"
app:showAsAction="always" />
<item
android:id="#+id/action_power_sensor_2"
android:title="#string/action_power_sensor_2"
app:actionLayout="#layout/layout_power_progress"
app:showAsAction="always" />
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
/*---------- Sensor 1 ---------------*/
sensor1PowerProgressView = menu?.findItem(R.id.action_power_sensor_1)?.actionView?.findViewById(R.id.powerProgress)
sensor1PowerProgressView ?.max = 5
sensor1PowerProgressView ?.progress = sensor1Power
/*---------- Sensor 2 ---------------*/
sensor2PowerProgressView = menu?.findItem(R.id.action_power_sensor_2)?.actionView?.findViewById(R.id.powerProgress)
sensor2PowerProgressView ?.max = 100
sensor2PowerProgressView ?.progress = sensor2Power
return super.onPrepareOptionsMenu(menu)
}
/*--- Code where the power is getting updated ----*/
sensorViewModel.getSensor1Power().observe(this) {
sensor1Power = it
if (sensor1PowerPrev!=sensor1Power) {
sensor1PowerPrev = sensor1Power
invalidateOptionsMenu()
}
}
sensorViewMode2.getSensor2Power().observe(this) {
sensor1Power = it
if (sensor2PowerPrev!=sensor2Power) {
sensor2PowerPrev = sensor2Power
invalidateOptionsMenu()
}
}
I am updating these power values from sensorViewModel. I see the values inside the sensorViewModel getting updated properly upon sensor connect and disconnect. I am logging both values (sensor1Power & sensor2Power ) inside the onPrepareOptionsMenu and I see the values getting logged there properly.
Now after spending whole 2 weeks on this issue I can't figure out why sensor1PowerProgressView and sensor2PowerProgressView are not getting updated on disconnect. They retain the last value.
Anyone, can point out what am I doing incorrectly. if you need any more details, I can share upon request.
EDIT: Problem solved after upgrading Build Tools Version from 23 to 27.
I have the following code snippet:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.findItem(R.id.shareMenuItem).getActionView().setOnClickListener(onShareMenuItemClickedListener);
}
Recently I have got some errors on Crashlytics with line menu.findItem(...):
Fatal Exception: java.lang.NullPointerException: Attempt to invoke interface method 'android.view.View android.view.MenuItem.getActionView()' on a null object reference
at pl.application.ProductViewFragment.onCreateOptionsMenu(SourceFile:434)
at android.support.v4.app.Fragment.performCreateOptionsMenu(SourceFile:2186)
at android.support.v4.app.FragmentManagerImpl.dispatchCreateOptionsMenu(SourceFile:2250)
at android.support.v4.app.FragmentController.dispatchCreateOptionsMenu(SourceFile:328)
at android.support.v4.app.FragmentActivity.onCreatePanelMenu(SourceFile:363)
The problem is not deterministic and shows only on Android Oreo (by Fabric - 100% of crashes were on Android 8.0, different devices). I have never had problems with this line before.
Were there any important changes in Android 8.0 able to cause NPE there? I've tried reproduce it on my Xiaomi Mi A1, but with no effects. Or maybe there is a workaround?
Thanks!
// Edit: added xml menu file
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:res="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/breadcrumbsMenuItem"
android:icon="#drawable/ic_breadcrumbs"
android:title="#string/breadcrumbs"
res:showAsAction="always" />
<item
android:id="#+id/shareMenuItem"
android:icon="#drawable/ic_menu_share"
android:title="#string/share"
res:actionLayout="#layout/layout_share_button"
res:showAsAction="always" />
</menu>
Just try to add something like this, to see if it will be still null or not
Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
public void run()
{
menu.findItem(R.id.shareMenuItem).getActionView().setOnClickListener(onShareMenuItemClickedListener);
}
}, 2000);
If this fixes the problem, then the reason for him to be null is that is still hasn't been created and you area all rdy trying to access to it
I did have a problem when I was trying to change the color of an icon of my Menu acording to some info that it get's when the program starts, and that "work arround" fix the problem to me
I'm not sure where you get res:... but i think it should be app:...
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:res="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/breadcrumbsMenuItem"
android:icon="#drawable/ic_breadcrumbs"
android:title="#string/breadcrumbs"
app:showAsAction="always" />
<item
android:id="#+id/shareMenuItem"
android:icon="#drawable/ic_menu_share"
android:title="#string/share"
app:actionLayout="#layout/layout_share_button"
app:showAsAction="always" />
</menu>
I am using custom ActionBar library in my Android App. there i want to show a searchView but can not find any solution, i m working in library that is
https://github.com/johannilsson/android-actionbar
This is a class
private class ExampleAction extends AbstractAction {
public ExampleAction() {
super(R.drawable.ic_title_export_default);
}
#Override
public void performAction(View view) {
Toast.makeText(OtherActivity.this, "Example action",
Toast.LENGTH_SHORT).show();
}
}
//use for signle action how to use for multiactions
ActionBar actionBar = (ActionBar) findViewById(R.id.actionbar);
actionBar.addAction(new ExampleAction());
actually i found code for searchbar but it is in .cs format how to use this searchview
https://github.com/zleao/MonoDroid.ActionBar
Thanks bro & sis
Take a look at this answer.
According to this answer SearchView is available support library.
add dependency to build.gradle
compile 'com.android.support:appcompat-v7:22.0.0'
and make imports
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
According to this answer it worked on API 8 on emulator. For more details, check the link with the question and answer itself.
Hope it helps.
UPDATE
By adding this code
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:hmkcode="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_search"
android:orderInCategory="100"
hmkcode:showAsAction="always"
android:icon="#drawable/ic_action_search"
android:title="Search"/>
<item
android:id="#+id/action_copy"
android:orderInCategory="100"
hmkcode:showAsAction="always"
android:icon="#drawable/ic_content_copy"
android:title="Copy"/>
<item
android:id="#+id/action_share"
android:orderInCategory="100"
hmkcode:showAsAction="always"
android:icon="#drawable/ic_social_share"
android:title="Share"/>
you can achieve this:
You can customize items in the way you want. For more details see this example.
I want to have an Menu item in the ActionBar that visualizes a boolean value. If this boolean value is true, the icon should start animating a series of 2 images in a loop. I did the following:
I added an item in the menu.xml file:
<item
android:id='#+id/myAnimation'
android:icon='#drawable/pic1'
android:showAsAction='ifRoom'>
</item>
I created an animation-list:
<?xml version='1.0' encoding='utf-8'?>
<animation-list xmlns:android='http://schemas.android.com/apk/res/android'
android:oneshot='false' >
<item
android:drawable='drawable/pic1'
android:duration='100' />
<item
android:drawable='drawable/pic2'
android:duration='100' />
</animation-list>
In the method onCreateOptionsMenu I assign this menu item to a variable
myMenuItem = menu.findItem(R.id.myAnimation);
Now, I was hoping to add an animation which would get executed whenever I tell the menu item to animate. But I wasn't able to come even close.
is this even possible?
How can I do that?
Thanks! Any help is appreciated!
Edit:
The App should support API from 8
I did ((AnimationDrawable) item.getIcon()).start(); in onCreateOptionsMenu(Menu menu)
This did not work. Then I thought, maybe it should be done on the UI thread, and then this worked:
someView.postDelayed(new Runnable() {
#Override
public void run() {
((AnimationDrawable) item.getIcon()).start();
}
}, 1000);
I was looking for the same thing and just found your question unanswered, so here is the solution, from the Android dev website:
((AnimationDrawable)myMenuItem).start();
I want to add a submenu to an existing submenu with this xml:
<item android:id="#+id/chooseCountry" android:title="Choose Country">
<menu>
<item android:id="#+id/india" android:title="India" >
<menu>
<item android:id="#+id/blor" android:title="Bangalore" />
<item android:id="#+id/delhi" android:title="Delhi" />
<item android:id="#+id/hyd" android:title="Hyderabad" />
</menu>
</item>
<item android:id="#+id/pak" android:title="Pakistan" />
<item android:id="#+id/africa" android:title="South Africa" />
</menu>
</item>
I am getting but this exception:
08-15 12:57:50.942: ERROR/AndroidRuntime(312): java.lang.UnsupportedOperationException: Attempt to add a sub-menu to a sub-menu.
I do not understand what I am doing wrong - can anybody give me some advice?
This appears to be natively supported from Android API level 15. On earlier versions, a workaround is to redirect menu calls. Using your xml example, change it so that the sub-sub-menu is a regular hidden menu item, and add a redirect place holder item instead:
<item android:id="#+id/india" android:title="India" android:visible="false">
<menu>
<item android:id="#+id/blor" android:title="Bangalore" />
<item android:id="#+id/delhi" android:title="Delhi" />
<item android:id="#+id/hyd" android:title="Hyderabad" />
</menu>
</item>
<item android:id="#+id/chooseCountry" android:title="Choose Country">
<menu>
<item android:id="#+id/india_redirect" android:title="India" />
<item android:id="#+id/pak" android:title="Pakistan" />
<item android:id="#+id/africa" android:title="South Africa" />
</menu>
Hang on to the inflated Menu mOptionsMenu created in onCreateOptionsMenu( Menu menu ) and open the sub-menu from your redirect like this:
#Override
public boolean onMenuItemSelected( int id, MenuItem item)
{
switch ( item.getItemId() )
{
case R.id.india_redirect:
mSomeView.post( new Runnable()
{
public void run()
{
mOptionsMenu.performIdentifierAction( R.id.india, 0 );
}
} );
return true;
}
return super.onMenuItemSelected( id, item );
}
Note the call to performIdentifierAction is posted from a View to the UI message queue. On old versions of Android it can be called immediately, but on newer versions it needs to be a separate message to work.
Well, apparently this is not supported. You'll have to redesign your menu.