4

我正在使用内置的操作栏。我想在获取数据时在操作栏中显示一个动画加载器,并在不显示时显示一个“刷新”图标。我发现的简单方法是使用 2 个菜单项并显示一个/隐藏另一个,然后反之。所以这是我的菜单:

<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 )一切正常。我写了问题所在的评论。当我注释掉“问题:”行时,旋转效果很好。

4

2 回答 2

3

Android 似乎无法恢复视图的保存状态。

发生这种情况是因为您有两个具有相同 ID 的视图。由于它们不属于同一类,因此演员表失败并崩溃。

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

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

这是你的问题。

于 2012-01-25T11:22:51.230 回答
0

我遇到了同样的问题,并通过在我的活动声明中添加以下内容来解决它AndroidManifest.xml

android:configChanges="orientation|screenSize|keyboardHidden"

这个页面让我找到了解决方案。希望这可以帮助。

于 2012-01-27T04:56:26.263 回答