Как сохранить состояние выбранного элемента spinner/dropdown при изменении ориентации?

Я использую раскрывающийся список spinner в моем коде, в котором у меня есть от 4 до 5 динамически заполненных значений, скажем, если у меня есть "яблоки", установленные по умолчанию, и я выбираю "апельсины" из раскрывающегося списка и поворачиваю свой экран на пейзаж из портрет, он возвращается к умолчанию "яблоки" вместе с представлением, связанным с ним. Как я могу сохранить состояние таким образом, что, когда я выбираю "апельсины" и поворачиваюсь в альбомный, он заполняет выбранное значение/остается в том же выбранном состоянии и сохраняет представление intact/заполняет представление, которое было выбрано в портретном режиме, соответствующем выбранному значению. Здесь код адаптера, который я использую для него:

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) {
    }

Любые идеи?

Спасибо!

Ответ 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
    }
}

Надеюсь, что это поможет

Ответ 2

Если конфигурация устройства (как определено Resource.Configuration), то все, что отображает пользовательский интерфейс, должно будет обновление, чтобы соответствовать этой конфигурации и для этого Activity Если вы не укажете иное, изменение конфигурации (например, изменение ориентации экрана, языка, устройств ввода и т.д.) приведет к уничтожению текущей активности, проходящей через обычный Activity lifecycle process onPause(), onStop() и onDestroy(), если это необходимо.

Если действие было на переднем плане или видимо для пользователя, как только onDestroy() вызывается в этом экземпляре, тогда будет создан новый экземпляр действия с любым сохраненнымInstanceState, который был создан предыдущим экземпляром из onSaveInstanceState(Bundle).

Это делается потому, что любой ресурс приложения, включая файлы макета, может изменяться на основе любого значения конфигурации. В некоторых особых случаях (как и у вас, если я получаю право, если у вас есть только spinner/dropdown на текущем пользовательском интерфейсе, и вам не нужно проходить полный жизненный цикл активности), вы можете обойти перезапуск своей деятельности на основе одного или больше типов изменений конфигурации. Это делается с атрибутом android: configChanges в его манифесте и/или вы также можете использовать onSaveInstanceState (Bundle), который является вызывающим, когда активность уничтожается и воссоздается от зачатия.

У вас есть только два способа решить эту проблему:

1_

    • Добавить 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");
    }
}

Это, безусловно, решит вашу проблему, и при изменении ориентации экрана он не будет обновлять ваш счетчик. Надеюсь, это поможет вам и всем!:)