2

我在尝试在我的应用程序中恢复 Android Spinner 的状态时遇到问题。目前,我的 Activity 的 ListView 标头中有多个 Spinner,它们相互依赖,因为选择一个 Spinner 会为后续 Spinner 加载数据。

我遇到的问题是,当我在 Spinners 上手动设置选择时,恢复状态似乎不起作用。我已经尝试过 onRestoreInstanceState 和 onResume。在查看 LogCat 输出时,似乎设置选择是异步的。当我必须等待一个被选中然后另一个可以填充然后设置时,如何可靠地恢复这些 Spinner 的状态?

编辑:添加代码

Activity 的 onCreate():

mSecondSpinner = mMyListHeader.findViewById(R.id.second_spinner);
mSecondSpinnerArrayAdapter = new SecondArrayAdapter(MyActivity.this, R.layout.second_spinner_item, new ArrayList<MySecondDto>());
mSecondSpinner.setAdapter(mSecondSpinnerArrayAdapter);
mSecondSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

   @Override
   public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

      MySecondDto selectedMySecondDto = (MySecondDto) parent.getItemAtPosition(position);
      List<MyThirdDto> myThirdDtos = selectedMySecondDto.getMyThirdDtos();

      // Load third spinner with dtos....
   }

   @Override
   public void onNothingSelected(AdapterView<?> parent) {}}
);

mFirstSpinner = mMyListHeader.findViewById(R.id.first_spinner);
mFirstSpinnerAdapter= new FirstArrayAdapter(MyActivity.this, R.layout.first_spinner, mResponse.getAllDtos());
mFirstSpinner.setAdapter(mFirstSpinnerArrayAdapter);
mFirstSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

   @Override
   public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

      mSecondSpinner.setAdapter(null);

      MyFirstDto selectedMyFirstDto = (MyFirstDto ) parent.getItemAtPosition(position);
      List<MySecondDto> mySecondDtos = selectedMyFirstDto .getMySecondDtos();

      mSecondSpinnerArrayAdapter.clearAndReplaceAll(mySecondDtos);
      mSecondSpinner.setAdapter(mSecondSpinnerArrayAdapter);

      // If there is only one second dto, disable the spinner
      if (mySecondDtos== null || mySecondDtos.size() <= 1)
      {
          disableSpinner(mSecondSpinner);
      }
      else
      {
          // Enable second spinner, select the hint element
          enableSpinner(mSecondSpinner);
          mSecondSpinner.setSelection(mSecondSpinnerArrayAdapter .getHintIndex());
      }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {}
});

Activity的onRestoreInstanceState():

 mFirstSpinner.setSelection(mFirstAdapterPosition);
 mFirstSpinnerArrayAdapter.notifyDataSetChanged();

 mSecondSpinner.setSelection(mSecondAdapterPosition);
 mSecondSpinnerArrayAdapter.notifyDataSetChanged();
4

2 回答 2

0

这可能对你有用。某处可能有错误,所以要小心。我和你有类似的情况,但我有 3 个微调器,它们的填充取决于前一个的选择。

这个想法是将微调器的索引/位置存储在 IndexVariables 中。这些变量的默认值为 -1。

将当前值存储在 onSaveInstanceState 中,

恢复 onActivityCreated 中的值。

在 onItemSelected 检查选中的 Item = null,检查是否设置了 IndexVariable(即!-= -1)

如果是这样,请使用它来设置 Spinner,然后将 IndexVariable 设置回 -1;

这是课程

(我使用了How to make an Android Spinner 中的 NothingSelectedSpinnerAdapter 并带有初始文本 "Select One"。不是很重要,但只是向我获得该代码的人大喊大叫。)

public class SpinnerTestFragment  extends Fragment {

private MainActivity activity;

private static final String SELECTED_THEME_IDX_STORAGE_KEY = "mSelectedTheme_IDX_StorageKey";
private static final String SELECTED_AIM_IDX_STORAGE_KEY = "mSelectedAim_IDX_StorageKey";
private static final String SELECTED_GOAL_IDX_STORAGE_KEY = "mSelectedGoal_IDX_StorageKey";

private static String TAG = "SpinnerTestFragment";

private Spinner spnrThemes;
private Spinner spnrAims;
private Spinner spnrGoals;

private String mSelectedTheme;
private String mSelectedAim;
private String mSelectedGoal;

private int mSelectedAimIdx = -1;
private int mSelectedThemeIdx = -1;
private int mSelectedGoalIdx = -1;


//----------------------------------------------------------------------------------------//


public SpinnerTestFragment() {
}//ctor

//----------------------------------------------------------------------------------------//

@Override
public View onCreateView(LayoutInflater inflater,
                         ViewGroup container,
                         Bundle savedInstanceState) {
    Log.d(TAG, "onCreateView");

    activity = (MainActivity) getActivity();


    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_photo, container, false);


    spnrThemes = view.findViewById(R.id.spnrThemes);
    spnrAims = view.findViewById(R.id.spnrAims);
    spnrGoals = view.findViewById(R.id.spnrGoals);


    setSpinner(spnrThemes, "Select Theme", ThemesAimsGoals.getThemes());

    spnrThemes.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            Object selectedItem = parent.getItemAtPosition(position);

            if (selectedItem != null) {
                mSelectedTheme = selectedItem.toString();
                setSpinner(spnrAims, "Select Aim", ThemesAimsGoals.getAims(mSelectedTheme));

            } else if(mSelectedThemeIdx != -1){
                selectedItem = parent.getItemAtPosition(mSelectedThemeIdx);
                mSelectedTheme = selectedItem.toString();
                setSpinner(spnrAims, "Select Aim", ThemesAimsGoals.getAims(mSelectedTheme));
                parent.setSelection(mSelectedThemeIdx);
                mSelectedThemeIdx = -1;
            }//Else
        }//onItemSelected

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });


    spnrAims.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            Object selectedItem = parent.getItemAtPosition(position);

            if (selectedItem != null) {
                mSelectedAim = selectedItem.toString();
                setSpinner(spnrGoals, "Select Goal", ThemesAimsGoals.getGoals(mSelectedTheme, mSelectedAim));

            } else if(mSelectedAimIdx != -1){
                selectedItem = parent.getItemAtPosition(mSelectedAimIdx);
                mSelectedAim = selectedItem.toString();
                setSpinner(spnrGoals, "Select Goal", ThemesAimsGoals.getGoals(mSelectedTheme, mSelectedAim));
                parent.setSelection(mSelectedAimIdx);
                mSelectedAimIdx = -1;
            }//Else
        }//onItemSelected

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });

    spnrGoals.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            Object selectedItem = parent.getItemAtPosition(position);
            if (selectedItem != null) {
                mSelectedGoal = selectedItem.toString();

            }else if(mSelectedGoalIdx != -1){
                selectedItem = parent.getItemAtPosition(mSelectedGoalIdx);
                mSelectedGoal = selectedItem.toString();
                parent.setSelection(mSelectedGoalIdx);
                mSelectedGoalIdx = -1;
            }//Else
        }//onItemSelected

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });

    return view;
}//onCreateView

//----------------------------------------------------------------------------------------//

/**
 * Populate Spinner
 * @param spnr Spinner to populate
 * @param prompt What to show at the start
 * @param array Items in the spinner
 */
private void setSpinner(Spinner spnr, String prompt, String[] array) {
    spnr.setPrompt(prompt);
    ArrayAdapter<CharSequence> adapter = new ArrayAdapter(activity, android.R.layout.simple_spinner_item, array);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spnr.setAdapter(
            new NothingSelectedSpinnerAdapter(
                    adapter,
                    R.layout.contact_spinner_row_nothing_selected,
                    activity,
                    prompt));
}//setSpinner

//----------------------------------------------------------------------------------------//

/**
 * Some lifecycle callbacks so that the image can survive orientation chang
 *
 * @param outState current state of fragment
 */
@Override
public void onSaveInstanceState(Bundle outState) {
    Log.d(TAG, "onSaveInstanceState");
    super.onSaveInstanceState(outState);

    outState.putInt(SELECTED_THEME_IDX_STORAGE_KEY, spnrThemes.getSelectedItemPosition());
    outState.putInt(SELECTED_AIM_IDX_STORAGE_KEY, spnrAims.getSelectedItemPosition());
    outState.putInt(SELECTED_GOAL_IDX_STORAGE_KEY, spnrGoals.getSelectedItemPosition());

}//onSaveInstanceState

//----------------------------------------------------------------------------------------//

/**
 * Rebuilds the Activity/Fragment in the image of the last one.
 *
 * @param savedInstanceState Info from last session or rotation
 */
@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    Log.d(TAG, "onActivityCreated");

    if (savedInstanceState == null)
        return;

    mSelectedThemeIdx = savedInstanceState.getInt(SELECTED_THEME_IDX_STORAGE_KEY);
    mSelectedAimIdx = savedInstanceState.getInt(SELECTED_AIM_IDX_STORAGE_KEY);
    mSelectedGoalIdx = savedInstanceState.getInt(SELECTED_GOAL_IDX_STORAGE_KEY);


}//onActivityCreated

}//Cls
于 2018-01-19T15:43:12.287 回答
0

你试过这个吗

mySpinner.post(new Runnable() { @Override public void run() { mySpinner.setSelection(position); } });
于 2017-12-28T20:14:43.603 回答