【问题标题】:maintain Item selection on orientation change在方向改变时保持项目选择
【发布时间】:2014-06-18 20:58:56
【问题描述】:

我正在尝试在方向更改时恢复动作模式的状态。但它不能正常工作。按照以下步骤顺序,在 #3 和 #4 中,选择被破坏:

  1. 长按一个项目 - 项目突出显示,上下文操作栏显示标题显示“1 个已选择”。看起来不错。
  2. 将手机转到横向 - 没有变化。看起来不错。
  3. 将手机转回纵向 - 项目未突出显示,上下文操作栏消失
  4. 长按项目 - 项目突出显示,上下文操作栏显示标题显示“0 已选择”

myListView.getCheckedItemCount() in onSaveInstanceState() 在 #3 上返回 0。这就是问题的开始。

我在片段中做错了什么(使用支持库)?

@Override
public void onSaveInstanceState(Bundle outState) {
    //check if any items are selected
    if (myListView.getCheckedItemCount() > 0) {
        //get the list of selected items and convert it to an int Array
        //because SparseBooleanArray cannot be stored in a bundle
        SparseBooleanArray selectedItems = myListView.getCheckedItemPositions();
        int[] selectedItems_intArray = new int[myListView.getCheckedItemCount()];
        for (int i = 0; i < selectedItems.size(); i++) {
            if (selectedItems.valueAt(i) == false)
                continue;
            selectedItems_intArray[i] = selectedItems.keyAt(i);
        }
        outState.putIntArray(KEY_CHECKED_ITEMS, selectedItems_intArray);
    }
}

@Override
public void onViewStateRestored(Bundle savedInstanceState) {
    super.onViewStateRestored(savedInstanceState);
    if (savedInstanceState != null) {
        int[] checkedItems = savedInstanceState.getIntArray(KEY_CHECKED_ITEMS);
        if (checkedItems != null) {
            actionMode = ((ActionBarActivity) getActivity()).startSupportActionMode(new ContextualActionBarActionModeCallBack());

            for (int i = 0; i < checkedItems.length; i++) {
                myListView.setItemChecked(checkedItems[i], true);
            }

            actionMode.setTitle(myListView.getCheckedItemCount() + " selected");
        }
    }
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    myListView = (ListView) getActivity().findViewById(R.id.myListView);
    adpt = new myCustomCursorAdapter(getActivity());
    myListView.setAdapter(adpt);
    //Choice mode is allowed only after a long click
    //disabling it on first time load
    myListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
        myListView.setOnItemLongClickListener(new OnItemLongClickListener(){
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id){
            if(actionMode == null){
                //Start the action mode
                actionMode = ((ActionBarActivity)getActivity()).startSupportActionMode(new ContextualActionBarActionModeCallBack());

                myLisVIew.setItemChecked(position, true);                           
                actionMode.setTitle(myListView.getCheckedItemCount() + " selected");
                return true;
                }
            else return false;
        }
    });
}

@Override
public void onResume(){
    super.onResume();
    getLoaderManager().initLoader(0,null,this);
}

private class ContextualActionBarActionModeCallBack implements ActionMode.Callback{
    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.mycontextmenu, menu);   
        myListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    }
    ...
    ...
}

ListView 布局元素:

<ListView
        android:id="@+id/myListView"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:layout_alignParentTop="true"
        android:listSelector="@android:color/transparent"
        android:stackFromBottom="true"
        android:layout_above="@id/layout_input"
        android:divider="#00000000"
        />

【问题讨论】:

    标签: android android-fragments android-support-library


    【解决方案1】:

    问题在于,每次在方向更改时创建列表视图时,列表视图的选择模式都会重置为默认值CHOICE_MODE_NONE,因为在列表视图布局文件中没有明确定义选择模式。发生这种情况的 Android 源 - http://androidxref.com/4.4.2_r2/xref/frameworks/base/core/java/android/widget/AbsListView.java#815

    解决方案是添加:

    android:choiceMode="multipleChoice"
    

    到列表视图布局。

    这也意味着无需手动将列表视图选择存储在onSaveInstanceState() 中并在onViewStateRestored() 中检索它。它由片段自动完成。所以删除这两个功能。只需在onResume 中启动动作模式即可:

    @Override
        public void onResume() {
            super.onResume();
                getLoaderManager().initLoader(0,null,this);
                if (myListView.getCheckedItemCount() > 0 && actionMode == null) {
                actionMode = ((ActionBarActivity) getActivity()).startSupportActionMode(new ContextualActionBarActionModeCallBack());
                actionMode.setTitle(myListView.getCheckedItemCount() + " selected");
            }
        }
    

    注意:如果你已经实现了LoaderManager.LoaderCallBacks接口并且你需要在方向改变之后访问适配器项,在适配器加载数据源之后在onLoadFinished()进行.在onResume() 中执行此操作会导致NPE

    【讨论】:

    • 我的活动和片段没有在方向改变时重新创建,因为我正在使用 android:configChanges="orientation|screenSize" 所以 listview 也不应该重新创建。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-29
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-01
    相关资源
    最近更新 更多