首页 > 解决方案 > 如何在 TextView 中选择文本时覆盖“复制”、“共享”和“全选”选项

问题描述

我有TextView一个用户可以选择文本的地方。默认情况下会出现以下选项:“复制”、“共享”和“全选”。我需要用自定义选项覆盖它们。但我找不到如何做到这一点。我浏览了文档和这篇不错的文章,但也不乏。这篇文章解释了当用户按下三点按钮时如何扩展菜单,这不是我需要的。

问题:如何覆盖文本部分菜单中的默认“复制”、“共享”和“全选”选项?

这是我的视图的样子:

<TextView
    android:id="@+id/transcript"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scrollbars="vertical" />

在java代码中我有:

transcript.setTextIsSelectable(true);
transcript.setFocusable(true);
transcript.setFocusableInTouchMode(true);

标签: androidandroid-layouttextviewandroid-menu

解决方案


您可以使用它TextView.setCustomSelectionActionModeCallback()来执行此操作。

文档:https://developer.android.com/reference/android/widget/TextView.html#setCustomSelectionActionModeCallback(android.view.ActionMode.Callback)

我整理了一个非常简单的应用程序来演示如何使用此功能。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView text = (TextView) findViewById(R.id.text);

        CustomActionModeCallback callback = new CustomActionModeCallback(this);
        text.setCustomSelectionActionModeCallback(callback);
    }
}

activity_main.xml

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="16dp"
        android:text="@string/lorem_ipsum"
        android:textIsSelectable="true"/>

</FrameLayout>

CustomActionModeCallback.java

public class CustomActionModeCallback implements ActionMode.Callback {

    private final Context context;

    public CustomActionModeCallback(Context context) {
        this.context = context;
    }

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

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

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        if (item.getItemId() == R.id.custom_one) {
            Toast.makeText(context, "One!", Toast.LENGTH_SHORT).show();
            mode.finish();
            return true;
        }
        else if (item.getItemId() == R.id.custom_two) {
            Toast.makeText(context, "Two!", Toast.LENGTH_SHORT).show();
            mode.finish();
            return true;
        }
        else if (item.getItemId() == R.id.custom_three) {
            Toast.makeText(context, "Three!", Toast.LENGTH_SHORT).show();
            mode.finish();
            return true;
        }

        return false;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {

    }
}

menu_custom.xml

<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/custom_one"
        android:title="One"
        app:showAsAction="never"/>

    <item
        android:id="@+id/custom_two"
        android:title="Two"
        app:showAsAction="never"/>

    <item
        android:id="@+id/custom_three"
        android:title="Three"
        app:showAsAction="never"/>

</menu>

MainActivity在xml 文件中没有什么可评论的。所有的魔法都发生在CustomActionModeCallback.

两者onCreateActionMode()onPrepareActionMode()可以用于将您的自定义菜单项添加到菜单中。如果使用onCreateActionMode(),系统会在溢出菜单中添加一些额外的选项,如下所示:

在此处输入图像描述 在此处输入图像描述

如果您使用onPrepareActionMode(),则不会添加额外的项目。

在此处输入图像描述

请注意,无论如何都必须return truefrom (返回 false 会导致菜单不显示),但只有在实际修改了菜单时才需要from 。onCreateActionMode()return trueonPrepareActionMode()

您可以处理用户对您的自定义项目内部的点击onActionItemClicked()。在我的示例中,我只是显示 aToast然后关闭上下文菜单(使用ActionMode.finish())。在这种方法中,您应该return true只在您自己处理的菜单项上;返回 false 允许发生系统默认操作(例如,如果您想为用户提供选择所有文本的选项)。

最后,onDestroyActionMode()在菜单关闭时调用。也许你对此有一些用处;我没有。


推荐阅读