android - fragment 中的上下文操作模式未显示

标签 android android-fragments android-listview contextual-action-bar android-actionmode

我想做一个这样的应用

batch contextual actions in an AbsListView

我关注了Google's guide to enable batch contextual actions in an AbsListView .在我的例子中,我在 Fragment 中实现了 AbsListView,因为我希望用户能够更改布局,我为 Activity (一个 ListView、一个 GridView 和另一个 AbsListView 子类)。我还在单独的类中实现了 AbsListView.MultiChoiceModeListener,因为我想在多个 Fragment 和 Activity 中重用它。

我的问题是:当我长按列表项时,上下文操作栏不显示。但是它响应了一次点击(表明选择器正在工作)。

我已经一遍又一遍地检查和试错我的代码,以确保我正确地遵循了指南中的所有内容,浏览了许多关于这个主题的故障排除,但我仍然无法弄清楚为什么上下文操作栏没有出现。

这是其中一个 fragment :

public class List extends Bookshelf {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_list, container, false);
        ListView list = (ListView) rootView.findViewById(R.id.book_list);
        list.setAdapter(new BookListAdapter(getActivity()));

        list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
        list.setMultiChoiceModeListener(new MultiChoiceCallback(list));

        return rootView;
    }

    private static class BookListAdapter extends BaseAdapter {
        private LayoutInflater mInflater;

        public BookListAdapter(Context context) {
            mInflater = LayoutInflater.from(context);
        }

        public int getCount() {
            return 100;
        }

        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;

            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.view_item_book_1text, null);
                holder = new ViewHolder();
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            return convertView;
        }

        static class ViewHolder {
            TextView title;
            ImageView cover;
        }
    }
}

这里是 MultiChoiceModeListener (MultiChoiceCallback.java):

public class MultiChoiceCallback implements MultiChoiceModeListener {
    AbsListView usingView;

    public MultiChoiceCallback(AbsListView view) {
        usingView = view;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        switch (item.getItemId()) {
        case R.id.bookDetails:
            break;
        case R.id.category:
            break;
        case R.id.delete:
            break;
        }
        return false;
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        mode.getMenuInflater().inflate(R.menu.select_book, menu);
        return false;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
    }

    @Override
    public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
        final int checkedCount = usingView.getCheckedItemCount();
        switch (checkedCount) {
            case 0:
                mode.setTitle(null);
                break;
            case 1:
                mode.setTitle("1 item selected");
                break;
            default:
                mode.setTitle("" + checkedCount + " items selected");
                break;
        }
    }
}

fragment 的布局(layout/fragment_list.xml):

<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/book_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</ListView>

膨胀的 View 列表项(layout/view_item_book_1text.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="51dp"
    android:background="@color/blue_when_clicked"
    android:clickable="true"
    android:focusable="true"
    android:layout_marginLeft="3dp"
    android:layout_marginRight="3dp"
    android:gravity="center_vertical"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/cover"
        android:contentDescription="@string/cover"
        android:layout_width="75dp"
        android:layout_height="45dp"
        android:layout_marginTop="3dp"
        android:layout_marginBottom="3dp"
        android:scaleType="fitCenter"
        android:src="@drawable/cover_02" />

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="3dp"
        android:text="A Book Title"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</LinearLayout>

每个列表项的颜色选择器(color/blue_when_clicked.xml):

<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:drawable="@drawable/color_light_blue" android:state_pressed="true"/>  <!-- pressed -->
    <item android:drawable="@drawable/color_light_gray" android:state_focused="true"/>  <!-- focused -->
    <item android:drawable="@drawable/color_light_gray" android:state_activated="true"/> <!-- selected -->
</selector>

如有任何帮助,我们将不胜感激!

最佳答案

我还没有测试过,但乍一看我认为你的问题出在你的 onCreateActionMode (ActionMode mode, Menu menu) 方法中。

根据documentation - 您应该返回 true 以创建 ActionMode

true if the action mode should be created, false if entering this mode should be aborted.


该机制与 Activity 中的 onCreateOptionsMenu(菜单菜单) 方法相同。 documentation在这里用更清楚的方式说:

You must return true for the menu to be displayed; if you return false it will not be shown.


编辑:

您是否尝试过只启动您提到的 tutoril 中的代码? 我在 ListView 上完成了 ActionMode 的最小实现。甚至没有菜单资源膨胀,只要在那里返回true,长按后就会出现ActionMode。

final ListView listView = new ListView(getActivity());
listView.setAdapter(new BookListAdapter(getActivity()));
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
    @Override
    public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        return false;
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        // not even need to inflate anything in order to ActionMode to appear
        return true;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
    }
});

来自适配器的代码(修改了您的适配器):

private static class BookListAdapter extends BaseAdapter {
    private LayoutInflater mInflater;

    public BookListAdapter(Context context) {
        mInflater = LayoutInflater.from(context);
    }

    public int getCount() {
        return 100;
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = mInflater.inflate(android.R.layout.simple_list_item_1, null);
        }

        ((TextView)convertView).setText("TEST");
        return convertView;
    }
}


结果的屏幕截图 - 如您所见,存在 ActionMode

enter image description here

关于android - fragment 中的上下文操作模式未显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24865949/

相关文章:

android - ListView 中的 "Separator"

java - 在fragment中使用google map 支持fragment

java - 在java和android中使用final变量的替代方案?

android - 元素集没有必需的属性 layout_height

java - 使用 Firebase 数据库获取每个子项的最后一个子项

Android: Activity 意外破坏,null savedInstanceState

java - AppCompatActivity 的接口(interface)

java - 在 ListView 的 ListItem 中删除和取消删除

android - Xamarin Forms 项目中使用 AD 和 Google 进行的 Azure 身份验证在授权后不会重定向回应用程序

android - 将 inputStream 转换为 FileInputStream?