Показать / скрыть элемент в панели действий Android (3.0+) - PullRequest
4 голосов
/ 25 января 2012

Я использую встроенную панель действий. Я хочу отобразить на панели действий анимированный загрузчик во время извлечения данных и отображать значок «обновить», если нет.Простой способ, который я нашел, состоит в том, чтобы использовать 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 ).Я написал в качестве комментария, где проблема.Когда я комментирую строку «ПРОБЛЕМА:», вращение работает хорошо.

Ответы [ 2 ]

3 голосов
/ 25 января 2012

Похоже, Android не может восстановить сохраненное состояние просмотра.

Это происходит потому, что у вас есть два представления с одинаковым идентификатором. Поскольку они не принадлежат к одному классу, произойдет сбой и сбой приведения.

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

и

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

Это ваша проблема.

0 голосов
/ 27 января 2012

У меня возникла та же проблема, и я решил ее, добавив в объявление своей деятельности в AndroidManifest.xml следующее:

android:configChanges="orientation|screenSize|keyboardHidden"

Эта страница привела меня к решению.Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...