Android ListView条目长按如何在应用顶部覆盖Toolbar显示上下文菜单
要实现长按ListView条目后顶部显示覆盖Toolbar的操作菜单,用Android官方提供的ActionMode上下文操作栏方案即可,具体实现步骤如下:
1. 配置主题支持覆盖Toolbar
在你的app主题(res/values/styles.xml)中添加如下配置,保证ActionMode会覆盖在Toolbar上方,不会把Toolbar挤到下方:
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar"> <!-- 其他主题配置 --> <item name="windowActionModeOverlay">true</item> <item name="actionModeStyle">@style/MyActionModeStyle</item> </style> <!-- 可选:自定义ActionMode样式 --> <style name="MyActionModeStyle" parent="Widget.MaterialComponents.ActionMode.Primary"> <item name="android:background">?attr/colorPrimary</item> </style>
2. 新建菜单资源文件
在res/menu目录下新建file_item_menu.xml,定义你需要的操作选项:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/action_delete" android:title="删除" android:icon="@drawable/ic_delete"/> <item android:id="@+id/action_share" android:title="分享" android:icon="@drawable/ic_share"/> <item android:id="@+id/action_rename" android:title="重命名" android:icon="@drawable/ic_edit"/> </menu>
3. 修改FileActivity代码
完整修改后的代码如下:
public class FileActivity extends ListActivity { ArrayList<String> al; ArrayAdapter<String> adapter; ListView lv; private ActionMode mActionMode; private int mSelectedPosition = -1; // ActionMode回调 private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { // 加载上下文菜单 mode.getMenuInflater().inflate(R.menu.file_item_menu, menu); mode.setTitle("选择操作"); return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { // 处理菜单点击事件 switch (item.getItemId()) { case R.id.action_delete: // 处理删除逻辑 String selectedFile = adapter.getItem(mSelectedPosition); // TODO 执行删除操作 adapter.remove(selectedFile); mode.finish(); return true; case R.id.action_share: // 处理分享逻辑 mode.finish(); return true; case R.id.action_rename: // 处理重命名逻辑 mode.finish(); return true; default: return false; } } @Override public void onDestroyActionMode(ActionMode mode) { mActionMode = null; mSelectedPosition = -1; // 可选:取消条目的选中状态 lv.clearChoices(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.file_view); // 安卓6.0以上需要动态申请存储权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 100); return; } } ArrayList<String> arr1 = GetFiles(Environment.getExternalStorageDirectory().getPath()); adapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_expandable_list_item_1, arr1); lv = getListView(); lv.setAdapter(adapter); lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE); // 给ListView设置长按监听器 lv.setOnItemLongClickListener((parent, view, position, id) -> { if (mActionMode != null) { return false; } mSelectedPosition = position; // 启动ActionMode mActionMode = startActionMode(mActionModeCallback); view.setSelected(true); return true; }); } private ArrayList<String> GetFiles(String path) { ArrayList<String> arr2 = new ArrayList<>(); File file = new File(path); File[] allfiles = file.listFiles(); if (allfiles == null || allfiles.length == 0) { return arr2; } for (File f : allfiles) { arr2.add(f.getName()); } return arr2; } @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); // 如果ActionMode已启动,点击条目切换选中 if (mActionMode != null) { mSelectedPosition = position; v.setSelected(true); return; } // 原有点击逻辑处理 } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 100) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限申请通过,重新加载文件列表 ArrayList<String> arr1 = GetFiles(Environment.getExternalStorageDirectory().getPath()); adapter.clear(); adapter.addAll(arr1); } } } }
注意事项
- 你需要自行添加菜单对应的图标资源,或者去掉icon属性只显示文字
- 如果需要支持多选条目,只需要把ListView的
choiceMode改成CHOICE_MODE_MULTIPLE,然后在ActionMode回调中记录所有选中的位置即可 - 处理文件操作时注意添加对应的存储读写权限,安卓10以上还要适配分区存储规则
内容的提问来源于stack exchange,提问作者S. Najeeb
相关产品推荐
相关产品推荐

