2012-01-25 25 views
4

我正在使用內置的操作欄。 我想在操作欄中顯示一個動畫加載器,同時讀取數據,並在不存在時顯示「刷新」圖標。我發現的簡單方法是使用2個菜單項並顯示/隱藏另一個菜單項,然後顯示相反的菜單項。因此,這裏是我的菜單:在Action Bar中顯示/隱藏項Android(3.0+)

<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" /> 

我使用的是actionLayout(因爲你可以看到),因爲我也沒弄清楚如何創建我的菜單中的不確定進度轉動。以下是相應的actionLayout:

<?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> 

我的活動:

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); 
      } 
     }; 
    } 
} 

一切都很好,工作,當我運行應用程序。 旋轉手機時出現問題。

堆棧跟蹤:

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 

的actionLayout(+ @ ID/menuItemProgress)似乎會導致問題。刷新項目一切正常(@ + id/menuItemRefresh)。我在問題出在哪裏寫了評論。當我對「問題:」這一行發表評論時,輪換效果很好。

+0

請僅在下次發佈必要的代碼。 – CSchulz

+0

這是一個不錯的小方法,您可以在此處理相同菜單項上的進度/刷新。謝謝! – brk3

+0

請注意,在Android 2.2上,當你隱藏進度條時,下一次讓它可見時,它不會生成動畫 –

回答

3

Android似乎無法恢復您的視圖的保存狀態。

發生這種情況是因爲您有兩個具有相同ID的視圖。由於他們不屬於同一個班級,因此演員陣容失敗並崩潰。

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

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

這是你的問題。

0

我有同樣的問題,並通過增加解決它下面到我的活動宣言AndroidManifest.xml

android:configChanges="orientation|screenSize|keyboardHidden" 

This page導致我的解決方案。希望這可以幫助。