如何识别ActionMode中是不是点击了Done按钮

Posted

技术标签:

【中文标题】如何识别ActionMode中是不是点击了Done按钮【英文标题】:How to recognize whether the Done button is clicked in ActionMode如何识别ActionMode中是否点击了Done按钮 【发布时间】:2012-07-23 11:31:21 【问题描述】:

我使用ActionMode 来选择网格中的项目。问题是我无法识别是否准确地点击了 Done 按钮。我唯一能知道的就是ActionMode 已经完成了。但是按 Back 也会完成ActionMode。 期望的行为是在 Done 点击时接受选择,并在 Back 按下时退出 ActionMode

我尝试使用ActionMode.setCustomView(),但它不影响完成按钮。启动 ActionMode 时不会调用 Activity.onBackPressed()

我发现的一种解决方案是使用 ActionBarSherlock 并手动获取 完成 按钮:

View closeButton = findViewById(R.id.abs__action_mode_close_button); 

但它仅适用于 android 2.x-3.x,因为在 4.x 上使用了本机操作栏。

【问题讨论】:

【参考方案1】:

请不要这样做,因为它是特定于实现且极其不标准的。

您可以使用onDestroyActionMode 回调来解除操作模式。

【讨论】:

我明白了,但我正在实现一个支持多选的选择器,我认为“完成”按钮是接受选择的最佳方式......无论如何,谢谢你的回答!看来我必须添加一个菜单项来接受所选项目。 但是我们如何区分完成按钮和返回按钮呢?我需要为这些人实施不同的行动...... 你也许可以拦截onBackPressed。否则,你不能。 @JakeWharton 如何区分由于屏幕旋转或完成按钮造成的 ActionMode 破坏。实际上我有一个要添加到 fav 数据库表的 id 列表,所以如果设备方向更改我应该保留这个数组,如果用户单击完成按钮我应该清除它,请帮助 @JakeWharton 但是这种情况如何:我有一个片段,其中包含一个列表视图,而该片段位于 ViewPager 中。点击并按住启动 CAB,按完成取消 CAB。假设我正在多选事物中(所以 CAB 处于打开状态)。当我在 ViewPager 中滑动到另一个片段时,我自然想删除 CAB,为此,我在第一个片段的 onPause 方法上完成了动作模式,当用户滑回该片段时,我再次启动 CAB。我认为我应该能够通过滑动和完成来区分解雇 CAB,以便我可以在暂停时重新启动 CAB【参考方案2】:

解决办法如下:

ActionMode mMode = MyActivityClass.this.startActionMode(some implementation);
int doneButtonId = Resources.getSystem().getIdentifier("action_mode_close_button", "id", "android");
View doneButton = MyActivityClass.this.findViewById(doneButtonId);
doneButton.setOnClickListener(new View.OnClickListener() 

    @Override
    public void onClick(View v) 
        // do whatever you want 
        // in android source code it's calling mMode.finish();
    
);

【讨论】:

只是一个旁注:注意你调用findViewById是从你启动动作模式的Activity而不是从其他视图,否则你会得到一个null pointer exception 这不适用于 Gingerbread 等前 ICS 设备上的 ABS。 此代码仅适用于 API LEVEL >= 11 您需要添加 API LEVEL 条件:View doneButton; if (android.os.Build.VERSION.SDK_INT >= 11) doneButton = Resources.getSystem().getIdentifier("action_mode_close_button", "id", "android"); else doneButton = findViewById(R.id.abs__action_mode_close_button); 警告:这是一个不灵活的解决方案,它本质上是访问私有 API。如果 Google 更改了 action_mode_close_button 的名称,这将停止工作。 此解决方案完美运行,除非方向更改按钮失去其点击监听器。我不会破坏方向改变的活动。【参考方案3】:

这是我的实现,它是一个适当的 hack,但它有效,当单击 ActionMode DONE 时,我真的找不到替代方法来执行特定的操作。我觉得你不能更优雅地捕捉这个事件真的很奇怪。

任何使这个稍微不那么难看的建议将不胜感激......

在我的活动中..

boolean mActionModeIsActive = false;
boolean mBackWasPressedInActionMode = false;

@Override
public boolean dispatchKeyEvent(KeyEvent event)

    mBackWasPressedInActionMode = mActionModeIsActive && event.getKeyCode() == KeyEvent.KEYCODE_BACK;
    return super.dispatchKeyEvent(event);


@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu)

    mActionModeIsActive = true;
    return true;


@Override
public void onDestroyActionMode(ActionMode mode)

    mActionModeIsActive = false;

    if (!mBackWasPressedInActionMode)
        onActionModeDoneClick();

    mBackWasPressedInActionMode = false;


public void onActionModeDoneClick();

    // Do something here.

如果您在 Activity 中使用 Fragments,那么其中一些代码可能需要在 Fragment 中,而其他位在 Activity 中。

@JakeWharton(和其他 ActionBarSherlock 用户)如果您在旅途中看到这个。我很想知道以上内容是否与 ABS 兼容,因为我尚未将 ABS 与我当前的项目集成。

【讨论】:

这确实有效,但我在项目的几个地方使用了动作模式。所以我决定将 MenuItems 添加到操作模式中,并将它们用作实际的“确认”项目。主要我将图标转换为解雇。这使得代码不那么骇人听闻。 看起来这也会检测到点击普通菜单项的时间,而不仅仅是按下完成按钮的时间。 @JDJ 是什么让你这么想? 至于答案,看起来不错,但它在没有 mActionModeIsActive 的情况下也可以工作:相反,只需确保在 onCreateActionMode 中设置mBackWasPressedInActionMode = false,然后在dispatchKeyEvent 中删除&&,所以它只是第二个测试。

以上是关于如何识别ActionMode中是不是点击了Done按钮的主要内容,如果未能解决你的问题,请参考以下文章

如何在ActionMode中禁用操作栏后退按钮

android webview:防止文本选择actionMode actionBar

需要为EditText长触摸而不是ActionMode自定义弹出窗口

TextView - setCustomSelectionActionModeCallback如何在为多个TextView选择文本时创建ActionMode.Callback

如何检查是不是在单元测试中调用了 sync.WaitGroup.Done()

自定义ActionMode Menu