2012-01-25 16 views
4

私は組み込みのアクションバーを使用しています。 私はデータを取得中にアニメーションローダーをアクションバーに表示し、そうでないときは「更新」アイコンを表示したいと思います。私が見つけた簡単な方法は、2つのメニュー項目を使用し、1つを表示するか、もう一方を非表示にしてから反対に表示することです。だからここに私のメニューです:アクションバーのアイテムを表示/非表示にする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を持つ2つのビューがあるために発生します。彼らは同じクラスではないので、キャストは失敗し、クラッシュします。

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

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

これはあなたの問題です。

0

私は同じ問題を抱えていたとAndroidManifest.xmlでの私の活動の宣言に以下を追加して、それを解決:

android:configChanges="orientation|screenSize|keyboardHidden" 

This pageは、ソリューションに私を導きました。お役に立てれば。

関連する問題