如何在屏幕方向改变时保留所选的下拉框/下拉列表项的状态?

17

我的代码中使用了一个下拉式旋转器,其中有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) {
    }
任何想法?
谢谢!
2个回答

26

你可以像这样做...

@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
    }
}

希望这能帮到你


1
我的Spinner在onCreateOptionsMenu中定义。我该如何解决这个问题? - IntoTheDeep
2
这个解决方案可能会导致Spinner调用OnItemSelected()多次。 - Sam Ramezanli
@SamRamezanli 一份解释为什么该方法可以被多次调用会很有帮助。 - Ely
1
我的下拉菜单在片段中..我该如何使用它? - Ajay Mistry

0

如果设备的配置(由Resources.Configuration类定义)发生更改,则任何显示用户界面的内容都需要更新以匹配该配置,因此您的Activity除非您另有指定,否则配置更改(例如屏幕方向、语言、输入设备等)将导致当前活动被销毁,并按适当的方式进行正常的Activity生命周期过程,即onPause(),onStop()和onDestroy()

如果活动曾经在前台或对用户可见,那么一旦在该实例中调用onDestroy(),则将创建一个新的活动实例,其中包含先前实例从onSaveInstanceState(Bundle)生成的任何savedInstanceState

这是因为任何应用程序资源,包括布局文件,都可以根据任何配置值进行更改。在一些特殊情况下(就像你的情况一样,如果我理解正确的话,如果你当前的 UI 只有下拉列表/下拉框,并且你不需要完整的 Activity 生命周期),你可能想要绕过基于一个或多个类型的配置更改重新启动您的 Activity。这可以通过其清单中的 android:configChanges 属性来实现,也可以使用 onSaveInstanceState(Bundle),当 Activity 从头开始销毁并重新创建时调用。

你只需有两种方法来解决这个问题_

1_

    1. 在 Manifest 文件中的 Activity 标签中添加 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、重写onConfigurationChanged方法,当设备配置在您的活动运行时发生更改时,系统会调用该方法。
 @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");
    }
}

这肯定会解决你的问题,并且在屏幕方向改变时不会刷新你的旋转器。我希望这能帮到你和大家!:)


1
旋转器的状态保存在哪里? - user2386226

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接