EditText如何在没有任何操作栏的情况下激活复制/粘贴弹出窗口?

时间:2016-09-08 17:07:01

标签: android android-edittext textview android-theme android-styles

我在delphi下,我使用android框架创建一个编辑。当我将主题设置为 Theme.DeviceDefault.Light.NoActionBar 时,我可以在我的EditText中选择一些文本,我有一个弹出窗口,其中包括“select all / cut / copy / paste / etc”,就像你可以见下图。

但是,当我选择 Theme.Material.Light.NoActionBar Theme.Holo.Light.NoActionBar 时,我无法选择我的EditText中的任何文本(我没有右边或左边的文本选择句柄),当然我没有任何复制/粘贴弹出窗口

他们是否可以在Theme_Material_Light_NoActionBar上进行此复制/粘贴弹出?

enter image description here Theme.DeviceDefault.Light.NoActionBar

enter image description here Theme_Material_Light_NoActionBar

enter image description here Theme.Holo.Light.NoActionBar

注1:

当我将屏幕移动到水平,然后编辑文本占用所有可用空间,然后我可以看到我的左右文本选择句柄,如下图所示,但我认为这是因为主题交换到主题.DeviceDefault.Light.NoActionBar 当我将屏幕移动到水平但我不确定时:

enter image description here

注意2

在我的editText上,当我执行 setCustomSelectionActionModeCallback (new Callback(){})时,永远不会调用Callback :(这是不正常的我认为?editText中的哪些内容可以禁止回调?

注意2

我可以选择所有主题中的文字(但我不能将其复制出去),但除了在Theme.DeviceDefault.Light.NoActionBar中,我看不到左右文字选择句柄。

注3

Theme.DeviceDefault.Light.NoActionBar仅在三星Galaxy等手机上显示左右文字选择句柄。在其他方面,它没有用。

注4

我发现问题的根源部分!这是因为我通过WindowManager.addView(view,layout_params)创建我的视图,这样startactionmodeforChild返回null,这禁止动作栏和文本选择句柄显示。现在如果我在我的edittext中做了类似的事情:

@Override
public ActionMode startActionMode(ActionMode.Callback callback) {
    Activity host = (Activity) this.getContext();    
    return host.getWindow().getDecorView().startActionMode(callback); 
} 

然后我可以看到左右文本动作句柄(但不是棉花糖,它只在棒棒糖上工作,我不知道为什么)。我现在的问题是显示了操作栏,但它显示为空:(内部没有任何内容(但我可以看到剪切/复制/过去控件位于转储视图中的内部)。所以现在我不寻找方法通过弹出菜单替换此操作栏(如图片Theme.DeviceDefault.Light.NoActionBar)。任何想法?

3 个答案:

答案 0 :(得分:5)

在您的活动中添加以下内容

ActionMode mActionMode;

你必须创建一个ActionMondeCallback接口

class ActionBarCallback implements ActionMode.Callback
    {

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

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

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

            int id = item.getItemId();
            if(id == R.id.item_delete)
            {
                tv.setText("");
                Toast.makeText(MainActivity.this,"option deleted",Toast.LENGTH_LONG);
            }
            return false;
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {

        }
    }

其中contextual_menu.xml如下所示,带有必需的图标

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context="com.example.letschat"
    >
    <item
        android:id="@+id/item_search"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="ifRoom|withText"
        android:title="Delete"
        android:titleCondensed="Delete">
    </item>
    <item
        android:id="@+id/item_delete"
        android:icon="@android:drawable/ic_menu_delete"
        app:showAsAction="ifRoom|withText"
        android:title="Delete"
        android:titleCondensed="Delete">
    </item>
    <item
        android:id="@+id/item_share"
        android:icon="@android:drawable/ic_menu_share"
        app:showAsAction="ifRoom|withText"
        android:title="Delete"
        android:titleCondensed="Delete">
    </item>
</menu>

现在启用您的Contextual ActionBar(CAB)如下所示,例如,这里是长时间点击textview启用

yourtextView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                mActionMode = MainActivity.this.startActionMode(new ActionBarCallback());
                return true;
            }
        });

然后你必须在点击CAB上的每个动作事件时编写自己的动作。

Bounty Hunter More details here

答案 1 :(得分:4)

对于API级别11或更高版本,您可以停止复制,粘贴,剪切和自定义上下文菜单。

edittext.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

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

        public void onDestroyActionMode(ActionMode mode) {                  
        }

        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            return false;
        }

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

从onCreateActionMode(ActionMode,Menu)返回false将阻止启动操作模式(选择全部,剪切,复制和粘贴操作)。

解决方案:在EditText中覆盖isSuggestionsEnabled和canPaste。

对于快速解决方案,请复制下面的类 - 此类会覆盖EditText类,并相应地阻止所有事件。

对于细节,请继续阅读。

解决方案在于防止PASTE / REPLACE菜单出现在(未记录的)android.widget.Editor类的show()方法中。在菜单出现之前,检查是否(!canPaste&amp;&amp;!canSuggest)返回;。用作设置这些变量的基础的两个方法都在EditText类中:

isSuggestionsEnabled()是公开的,因此可能会被覆盖。 canPaste()不是,因此必须通过在派生类中引入相同名称的函数来隐藏它。 因此,将这些更新合并到一个也具有setCustomSelectionActionModeCallback的类中,并禁用长按,这里是完整的类,以防止所有编辑(但仍然显示文本选择处理程序)来控制游标:

package com.cjbs.widgets;

import android.content.Context;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;


/**
 *  This is a thin veneer over EditText, with copy/paste/spell-check removed.
 */
public class NoMenuEditText extends EditText

{
    private final Context context;

    /** This is a replacement method for the base TextView class' method of the same name. This 
     * method is used in hidden class android.widget.Editor to determine whether the PASTE/REPLACE popup
     * appears when triggered from the text insertion handle. Returning false forces this window
     * to never appear.
     * @return false
     */
    boolean canPaste()
    {
       return false;
    }

    /** This is a replacement method for the base TextView class' method of the same name. This method
     * is used in hidden class android.widget.Editor to determine whether the PASTE/REPLACE popup
     * appears when triggered from the text insertion handle. Returning false forces this window
     * to never appear.
     * @return false
     */
    @Override
    public boolean isSuggestionsEnabled()
    {
        return false;
    }

    public NoMenuEditText(Context context)
    {
        super(context);
        this.context = context;
        init();
    }

    public NoMenuEditText(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        this.context = context;
        init();
    }

    public NoMenuEditText(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        this.context = context;
        init();
    }

    private void init()
    {
        this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());
        this.setLongClickable(false);
    }


    /**
     * Prevents the action bar (top horizontal bar with cut, copy, paste, etc.) from appearing
     * by intercepting the callback that would cause it to be created, and returning false.
     */
    private class ActionModeCallbackInterceptor implements ActionMode.Callback
    {
        private final String TAG = NoMenuEditText.class.getSimpleName();

        public boolean onCreateActionMode(ActionMode mode, Menu menu) { return false; }
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; }
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; }
        public void onDestroyActionMode(ActionMode mode) {}
    }
} 

答案 2 :(得分:2)

尝试使用主题 Theme.AppCompat.Light.NoActionBar
还要在xml文件中的EditText上设置android:textIsSelectable="true"