在屏幕旋转时切换ListView ChoiceMode时出现问题

时间:2011-08-25 11:00:36

标签: android

我正在尝试基于Android文档末尾提供的有关Fragments的example code构建拆分窗格,基本上是一个包含两个片段的LinearLayout(所有细节都可以在上面的链接中找到):< / p>

  • TitlesFragment显示标题列表
  • DetailsFragment显示当前所选标题的详细信息

我的问题是发生以下意外行为:

  1. 我以横向方向启动应用程序:标题列表显示在左侧,当前所选标题的详细信息(开头的第一个)显示在右侧。
  2. 我从标题列表中选择项目X :标题会突出显示,因为ListView设置为CHOICE_MODE_SINGLE,其项目实现Checkable界面。
  3. 我切换到纵向方向(通过旋转设备或模拟器):正如预期的那样,只显示标题列表,并且在此配置中未选择任何项目,因为ListView被重新创建,并且默认情况下,它设置为CHOICE_MODE_NONE
  4. 我从标题列表中选择项目Y :正如预期的那样,系统会显示仅显示与所做选择对应的DetailsFragment的活动。
  5. 我切换回横向方向(此处发生意外行为):右侧的DetailsFragment正确显示项目Y 的详细信息(其中是以纵向方式选择的,但TitlesFragment仍显示项目X 为选中状态(即在第一次屏幕旋转之前选择的那个)。
  6. 当然,我希望在纵向方向上进行的最后一次选择也在TitlesFragment内正确显示,否则我最终会出现一个不一致的突出显示,在显示项目Y的详细信息时显示项目X 。

    我发布了更改ListView模式的相关代码(在'onActivityCreated'中)并且设置了所选项目(在'showDetails'方法中):

    public static class TitlesFragment extends ListFragment {
    boolean mDualPane;
    int mCurCheckPosition = 0;
    
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    
        // Populate list with our static array of titles.
        setListAdapter(new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_activated_1, Shakespeare.TITLES));
    
        // Check to see if we have a frame in which to embed the details
        // fragment directly in the containing UI.
        View detailsFrame = getActivity().findViewById(R.id.details);
        mDualPane = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE;
    
        if (savedInstanceState != null) {
            // Restore last state for checked position.
            mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
        }
    
        if (mDualPane) {
            // In dual-pane mode, the list view highlights the selected item.
            getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            // Make sure our UI is in the correct state.
            showDetails(mCurCheckPosition);
        }
    }
    
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("curChoice", mCurCheckPosition);
    }
    
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        showDetails(position);
    }
    
    /**
     * Helper function to show the details of a selected item, either by
     * displaying a fragment in-place in the current UI, or starting a
     * whole new activity in which it is displayed.
     */
    void showDetails(int index) {
        mCurCheckPosition = index;
    
        if (mDualPane) {
            // We can display everything in-place with fragments, so update
            // the list to highlight the selected item and show the data.
            getListView().setItemChecked(index, true);
    
            // Check what fragment is currently shown, replace if needed.
            DetailsFragment details = (DetailsFragment)
                    getFragmentManager().findFragmentById(R.id.details);
            if (details == null || details.getShownIndex() != index) {
                // Make new fragment to show this selection.
                details = DetailsFragment.newInstance(index);
    
                // Execute a transaction, replacing any existing fragment
                // with this one inside the frame.
                FragmentTransaction ft = getFragmentManager().beginTransaction();
                ft.replace(R.id.details, details);
                ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                ft.commit();
            }
    
        } else {
            // Otherwise we need to launch a new activity to display
            // the dialog fragment with selected text.
            Intent intent = new Intent();
            intent.setClass(getActivity(), DetailsActivity.class);
            intent.putExtra("index", index);
            startActivity(intent);
        }
    }
    

    有没有人知道如何解决这个问题? 提前谢谢。

4 个答案:

答案 0 :(得分:2)

两年后,我在这里使用Android v4支持库中的Fragment Layout示例,我遇到了同样的问题!

这是我提出的唯一一个不需要一直使用CHOICE_MODE_SINGLE的修补程序:

只需在TitlesFragment的getListView().setItemChecked(mCurCheckPosition, true);方法中添加对onResume()的调用即可。而且......就是这样!

答案 1 :(得分:0)

也许你应该设置你调用super.onSaveInstanceState的outState BEFORE 的值?

@Override
public void onSaveInstanceState(Bundle outState) {
    outState.putInt("curChoice", mCurCheckPosition);
    super.onSaveInstanceState(outState);
}

答案 2 :(得分:0)

我在该代码上遇到了同样的问题,并且我在setItemChecked方法上调用了onStart作为解决方法:

@Override
public void onStart() {
    super.onStart();
    if (mDualPane) {
        getListView().setItemChecked(mCurCheckPosition, true);
    }
}

或者正如LearningNerd所说,在onResume()

中这样做

答案 3 :(得分:-2)

如果您在清单文件中的活动代码中放置android:configChanges="orientation",您的应用会忽略轮播,但仍会呈现相关的布局。