Show / hide an item in the Action Bar Android (3.0+)

I use the built-in action bar. I want to display an animated bootloader on the action bar when retrieving data and display a refresh icon if not. The simple way I found is to use two menu items and show one / hide the other, and then vice versa. So here is my menu:

<item android:id="@+id/menuItemRefresh" android:title="Refresh" android:showAsAction="always" android:icon="@drawable/ic_menu_refresh" android:visible="false" /> <item android:id="@+id/menuItemProgress" android:actionLayout="@layout/progress" android:showAsAction="always" android:visible="true" /> 

I use actionLayout (as you can see) because I did not understand how to create an undefined progressbar change in my Menu. Here is the corresponding Layout action:

 <?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" android:orientation="vertical" android:id="@+id/layoutProgress" > <ProgressBar android:id="@+id/menuItemRefresh" android:layout_width="30dp" android:layout_height="30dp" android:layout_marginLeft="13dp" android:layout_marginRight="13dp" /> </LinearLayout> 

My activity:

 public class MainActivity extends Activity implements OnItemClickListener { Handler handler; MenuItem menuItemProgress; MenuItem menuItemRefresh; int currentPage; List<CloudAppItem> items; boolean currentlyLoading = false; ListView listView; FilesAdapter filesAdapter; LinearLayout emptyView; @Override public void onCreate(Bundle savedInstanceState) { Log.i("MainActivity", "Started"); super.onCreate(savedInstanceState); setContentView(R.layout.main); setHandler(); setListing(); loadItems(); } @Override protected void onResume() { super.onResume(); if (isFirstRun() && haveCredentialsChanged()) { setFirstRun(false); } if (isFirstRun()) { firstRun(); } else if (haveCredentialsChanged()) { setCredentialsChanged(false); loadFiles(true, 0); } else { loadFiles(false, 0); } } @Override public Object onRetainNonConfigurationInstance() { return items; } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu, menu); this.menuItemProgress = menu.findItem(R.id.menuItemProgress); this.menuItemRefresh = menu.findItem(R.id.menuItemRefresh); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menuItemPreferences: startActivity(new Intent(MainActivity.this, PreferencesActivity.class)); break; case R.id.menuItemRefresh: loadFiles(true, 0); break; } return false; } private boolean isFirstRun() { return Prefs.getPreferences(this).getBoolean(Prefs.FIRST_RUN, true); } private void firstRun() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("First run"); builder.setCancelable(false); builder.setPositiveButton("ok", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startActivity(new Intent(MainActivity.this, PreferencesActivity.class)); } }); AlertDialog alert = builder.create(); alert.show(); } private void setFirstRun(boolean b) { Prefs.getPreferences(this).edit().putBoolean(Prefs.FIRST_RUN, b).commit(); } private boolean haveCredentialsChanged() { return Prefs.getPreferences(this).getBoolean(Prefs.CREDENTIALS_CHANGED, false); } private void setCredentialsChanged(boolean b) { Prefs.getPreferences(this).edit().putBoolean(Prefs.CREDENTIALS_CHANGED, b).commit(); } private void setListing() { listView = (ListView) findViewById(R.id.listView); emptyView = (LinearLayout) findViewById(R.id.emptyView); listView.setOnItemClickListener(this); listView.setEmptyView(emptyView); } @SuppressWarnings("unchecked") private void loadItems() { Object obj = getLastNonConfigurationInstance(); if (obj != null) { items = (List<CloudAppItem>) obj; MainActivity.this.handler.sendEmptyMessage(0); } else { if (!isFirstRun()) loadFiles(true, 0); } } private void showProgressIcon(boolean show) { if(this.menuItemProgress != null && this.menuItemRefresh != null) { if(show) { this.menuItemProgress.setVisible(true); this.menuItemRefresh.setVisible(false); } else { this.menuItemRefresh.setVisible(true); // PROBLEM : LINE TRIGGERING ERROR this.menuItemProgress.setVisible(false); } } } @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { if(this.items.get(arg2).isFake()) { filesAdapter.lastItemLoading = true; filesAdapter.notifyDataSetChanged(); int page = (int)(this.items.size()/Integer.valueOf(Prefs.getPreferences(this).getString(Prefs.FILES_PER_REQUEST, "20")))+1; loadFiles(false, page); } else { startActivity(new Intent(this, FileInfosActivity.class)); } } /** * @param reload : clean the list before loading new items * @param page : if 0, items are prepended, else, items are appended */ private void loadFiles(final boolean reload, final int page) { if (!currentlyLoading) { currentlyLoading = true; showProgressIcon(true); new Thread(new Runnable() { @Override public void run() { // REQUESTING WEB SERVICE HERE MainActivity.this.handler.sendEmptyMessage(0); } }).start(); } } private void setHandler() { this.handler = new Handler() { @Override public void handleMessage(Message msg) { currentlyLoading = false; if (filesAdapter == null) { filesAdapter = new FilesAdapter(MainActivity.this, MainActivity.this.items); listView.setAdapter(filesAdapter); } else { filesAdapter.refill(MainActivity.this.items); } // PROBLEM : LINE TRIGGERING ERROR showProgressIcon(false); } }; } } 

Everything works fine and works when the application starts. The problem occurs when you turn the phone.

Stack:

 FATAL EXCEPTION: main java.lang.RuntimeException: Unable to start activity ComponentInfo{com.quanturium.androcloud/com.quanturium.androcloud.MainActivity}: java.lang.ClassCastException: android.view.AbsSavedState$1 cannot be cast to android.widget.ProgressBar$SavedState at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1955) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3347) at android.app.ActivityThread.access$700(ActivityThread.java:122) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1150) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4340) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.ClassCastException: android.view.AbsSavedState$1 cannot be cast to android.widget.ProgressBar$SavedState at android.widget.ProgressBar.onRestoreInstanceState(ProgressBar.java:1093) at android.view.View.dispatchRestoreInstanceState(View.java:9876) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2330) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2330) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2330) at android.view.View.restoreHierarchyState(View.java:9854) at com.android.internal.policy.impl.PhoneWindow.restoreHierarchyState(PhoneWindow.java:1625) at android.app.Activity.onRestoreInstanceState(Activity.java:906) at android.app.Activity.performRestoreInstanceState(Activity.java:878) at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1100) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1933) ... 12 more 

The Layout action (@ + id / menuItemProgress) seems to be causing the problem. Everything is fine with the update item (@ + id / menuItemRefresh). I wrote as a comment where the problem is. When I comment out the line β€œPROBLEM”: rotation works well.

+4
source share
2 answers

Android does not seem to be able to restore the state of the saved state.

This is because you have two views with the same identifier. Since they do not belong to the same class, the process is reset and crashes.

 <item android:id="@+id/menuItemRefresh" 

and

 <ProgressBar android:id="@+id/menuItemRefresh" 

It's your problem.

+3
source

I had the same issue and decided to add it by adding the following to my activity declaration in AndroidManifest.xml :

 android:configChanges="orientation|screenSize|keyboardHidden" 

This page led me to a solution. Hope this helps.

0
source

Source: https://habr.com/ru/post/1392879/


All Articles