【问题标题】:How do I preserve the state of a selected spinner/dropdown item on orientation change?如何在方向更改时保留选定微调器/下拉项的状态?
【发布时间】:2013-11-26 05:12:32
【问题描述】:

我在我的代码中使用微调器下拉菜单,其中我有 4 到 5 个动态填充的值,假设我将“苹果”设置为默认值,然后从下拉列表中选择“橙子”并将屏幕旋转为横向纵向,它会与与之关联的视图一起返回默认的“苹果”。如何保存状态,以便当我选择“橙色”并旋转到横向时,它会填充选定的值/保持在相同的选定状态和保持视图完整/填充在与所选值相对应的纵向模式中选择的视图。这是我使用的适配器代码:

public class MarketsSpinnerAdapter extends CustomRowAdapter<AdapterRow> {


    private List<AdapterRow> mRenderList;

    public MarketsSpinnerAdapter(final Context context, final List<AdapterRow> renderList) {
        super(context);


        mRenderList = new ArrayList<AdapterRow>();
        mRenderList.addAll(renderList);
    }

    @Override
    protected void setEntries(final List<AdapterRow> renderList) {
        mRenderList = renderList;
    }

    @Override
    protected List<AdapterRow> getEntries() {
        return mRenderList;
    }

    @Override
    public View getDropDownView(final int position, final View convertView, final ViewGroup parent) {
        return getEntries().get(position).getDropDownView(mContext, convertView);
    }

}

各自片段中的对应用法:

 private void populateCategoryRows(final Cursor cursor) {
            mCategories.clear();
            mAllCategories.clear();
            cursor.moveToPosition(-1);
            Map<String, String> categoryParentNames = new HashMap<String, String>();

            int selectedPosition = 0;
            String previousHeader = "";
            String previousAllHeader = "";

            while (cursor.moveToNext()) {
                final int categoryLevel = cursor.getInt(cursor.getColumnIndex(MarketsCategory.Columns.LEVEL));
                final String categoryName = cursor.getString(cursor.getColumnIndex(MarketsCategory.Columns.NAME));
                final String categoryDisplayName = cursor.getString(cursor.getColumnIndex(MarketsCategory.Columns.DISPLAY_NAME));

                if (categoryLevel == 1) {
                    categoryParentNames.put(categoryName, categoryDisplayName);
                }
            }

            cursor.moveToPosition(-1);
            while (cursor.moveToNext()) {
                final int categoryLevel = cursor.getInt(cursor.getColumnIndex(MarketsCategory.Columns.LEVEL));
                final boolean categoryIsDefault = cursor.getInt(cursor.getColumnIndex(MarketsCategory.Columns.IS_DEFAULT)) == 1;
                final boolean categoryIsSelected = cursor.getInt(cursor.getColumnIndex(MarketsCategory.Columns.IS_SELECTED)) == 1;
                final String categoryParent = cursor.getString(cursor.getColumnIndex(MarketsCategory.Columns.PARENT));
                final String categoryName = cursor.getString(cursor.getColumnIndex(MarketsCategory.Columns.NAME));
                final String categoryDisplayName = cursor.getString(cursor.getColumnIndex(MarketsCategory.Columns.DISPLAY_NAME));


                if (categoryLevel == 2 ) {
                    String categoryParentDisplayName = categoryParentNames.get(categoryParent);
                        if (!categoryParent.equals(previousHeader)) {
                            if (categoryIsSelected) {

                                mCategories.add(new CategoryHeader(categoryParentDisplayName));
                                previousHeader = categoryParent;
                            }
                        }

                        if (!categoryParent.equals(previousAllHeader)) {
                            mAllCategories.add(new CategoryHeader(categoryParentDisplayName));
                            previousAllHeader = categoryParent;
                        }

                        if (categoryIsSelected) {
                            mCategories.add(new SpinnerMarketCategoryRow(categoryName, categoryDisplayName, categoryParent));
                        }
                        mAllCategories.add(new MarketsCategoryCheckableRow(categoryName, categoryDisplayName, categoryIsSelected, categoryIsDefault));

                        if(categoryIsDefault){
                            selectedPosition = mCategories.size()-1;
                        }
                }
            }

            mSpinnerAdapter = new MarketsSpinnerAdapter(Application.getAppContext(), mCategories);
            headerView.setSpinnerAdapter(mSpinnerAdapter);
            headerView.setSpinnerSelectedItemPosition(selectedPosition);
        }
        if (selectedItem instanceof SpinnerMarketCategoryRow) {
            selectedCategory = (SpinnerMarketCategoryRow) mSpinnerAdapter.getItem(position);
        } else {
            if (mSpinnerAdapter.getCount() - 1 >= position + 1) {
                selectedCategory = (SpinnerMarketCategoryRow) mSpinnerAdapter.getItem(position + 1);
            } else {
                selectedCategory = (SpinnerMarketCategoryRow) mSpinnerAdapter.getItem(position - 1);
            }
        }

        final MarketsFragment parentFragment = (MarketsFragment) getParentFragment();
        parentFragment.onCategorySelected(selectedCategory.getCategoryName(), selectedCategory.getCategoryParentName());
    }
@Override
    public void showResults(final Uri uri) {
        LayoutUtils.showResults(getView(), headerView.getSpinnerId());
        headerView.setVisibility(View.VISIBLE);
    }

    @Override
    public void showNoResults(final Uri uri) {
        final MarketsFragment parentFragment = (MarketsFragment) getParentFragment();
        parentFragment.hideSpinner();
        //LayoutUtils.showNoResult(getView(), headerView.getSpinnerId());
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        headerView.setSelected(false);
    }
    @Override
    public void onNothingSelected(IcsAdapterView<?> parent) {
    }

有什么想法吗?

谢谢!

【问题讨论】:

    标签: android android-layout android-fragments android-spinner android-orientation


    【解决方案1】:

    你可以这样做......

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("yourSpinner", yourSpinner.getSelectedItemPosition());
        // do this for each or your Spinner
        // You might consider using Bundle.putStringArray() instead
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // initialize all your visual fields        
        if (savedInstanceState != null) {
            yourSpinner.setSelection(savedInstanceState.getInt("yourSpinner", 0));
            // do this for each of your text views
        }
    }
    

    希望对你有帮助

    【讨论】:

    • 我的微调器是在 onCreateOptionsMenu 中定义的。我该如何解决?
    • 此解决方案可能会使微调器多次调用 OnItemSelected()。
    • @SamRamezanli 解释为什么可以多次调用该方法会很有帮助。
    • 我的微调器在片段中..我该如何使用它?
    【解决方案2】:

    如果设备的配置(由Resources.Configuration 类定义)发生更改,则显示用户界面的任何内容都需要更新以匹配该配置,因此您的Activity 除非您另有指定,否则配置更改(例如屏幕方向、语言、输入设备等的变化)将导致您当前的活动被破坏,通过 onPause()、onStop() 和 onDestroy() 的正常 Activity lifecycle process 视情况而定。

    如果活动在前台或对用户可见,则在该实例中调用 onDestroy() 后,将创建活动的新实例,无论 savedInstanceState 之前的实例是从 onSaveInstanceState(Bundle) 生成的。

    这样做是因为任何应用程序资源(包括布局文件)都可以根据任何配置值进行更改。在某些特殊情况下(就像您的一样,如果我做对了,如果您在当前 UI 上只有微调器/下拉菜单并且您不需要经历完整的 Activity 生命周期),您可能希望绕过基于一个重新启动您的 Activity或更多类型的配置更改。这是通过其清单中的 android:configChanges 属性完成的,并且/或者您也可以使用 onSaveInstanceState(Bundle),它是活动被销毁并从开始重新创建时的调用者。

    你有两种方法可以解决这个问题_

    1_

      1. 在您的 Activity 标签的 Manifest 文件中添加 android:configChanges="orientation"
     <?xml version="1.0" encoding="utf-8"?>
     <manifest ...
     >
     <application ...
       >      
        <activity
            android:name="SpinnerActivity"
            android:configChanges="orientation" >
             <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
     </application>
    
     </manifest>
    
    • 2、OverrideonConfigurationChanged,当你的Activity运行时设备配置发生变化时系统会调用它。
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        int orientation = newConfig.orientation;
    
        switch (orientation) {
        case Configuration.ORIENTATION_LANDSCAPE:
            // do what you want when user is in LANDSCAPE
            break;
    
        case Configuration.ORIENTATION_PORTRAIT:
            // do what you want when user is in PORTRAIT
            break;
        }
    
    }
    

    2_

    使用 put 方法将值存储在 onSaveInstanceState() 中:

    protected void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        //Put your spinner values to restore later...
        savedInstanceState.putLong("yourSpinnerValKey", yourSpinner.getSelectedItemPosition());
    }
    

    并恢复 onCreate() 中的值:

    public void onCreate(Bundle savedInstanceState) {
        if (savedInstanceState!= null) {
         //get your values to restore...
            value = savedInstanceState.getLong("param");
        }
    }
    

    这肯定会解决您的问题,并且在屏幕方向更改时不会刷新您的微调器。我希望这对你和所有人都有帮助! :)

    【讨论】:

    • 微调器的状态保存在哪里?
    猜你喜欢
    • 2019-04-21
    • 1970-01-01
    • 2013-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多