【问题标题】:EditText how to activate copy/paste popup without any actionbar?EditText 如何在没有任何操作栏的情况下激活复制/粘贴弹出窗口?
【发布时间】:2023-03-25 21:59:01
【问题描述】:

我在 delphi 下,我使用 android 框架来创建编辑。当我将主题设置为 Theme.DeviceDefault.Light.NoActionBar 时,我可以在我的 EditText 中选择一些文本,然后我会弹出一个带有“全选/剪切/复制/粘贴/等”的弹出窗口,就像你可以见下图。

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

他们有什么方法可以在 Theme_Material_Light_NoActionBar 上有这个复制/粘贴弹出窗口吗?

Theme.DeviceDefault.Light.NoActionBar

Theme_Material_Light_NoActionBar

Theme.Holo.Light.NoActionBar

注意 1:

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

注意 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 ,这禁止显示操作栏和文本选择句柄。现在如果我在我的编辑文本中做这样的事情:

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

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

【问题讨论】:

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


【解决方案1】:

在您的活动中添加关注

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 上的每个动作事件上编写你自己的点击动作。

~赏金猎人 More details here

【讨论】:

  • @Loki,这有帮助吗?
  • 感谢 Loki,这是关于这个问题最好的部分,我的 5 人办公室团队在这个主题中进行了讨论,我搜索了很多,最后我找到了这个。
  • 如果你喜欢赏金,我会开始另一个类似的东西:stackoverflow.com/questions/39561133/… :)
【解决方案2】:

对于 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 将阻止启动操作模式(全选、剪切、复制和粘贴操作)。

解决方案:覆盖 isSuggestionsEnabled 并可以在 EditText 中粘贴。

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

有关坚韧不拔的细节,请继续阅读。

解决方案在于防止 PASTE/REPLACE 菜单出现在(未记录的)android.widget.Editor 类的 show() 方法中。在菜单出现之前,检查 if (!canPaste && !canSuggest) return;。作为设置这些变量的基础的两个方法都在 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) {}
    }
} 

【讨论】:

  • 谢谢!!您的建议有效,但是我不想删除对面的剪切/复制/过去/我想展示它!但我明白为什么它没有显示,这是因为 startactionmodeforChild 返回 null !现在我用 ActionMode = MyActivity.startActionMode(callback) 覆盖 startActionMode(ActionMode.Callback callback);它的工作(部分)。它的部分工作是因为显示了操作栏但没有绘制:(我不明白为什么
  • 让我知道我是否得到了赏金。哈哈哈
  • 我不明白你说的 lemme 是什么意思?
  • 它的英国口音“lemme”=“让我”
  • W4R10CK 您的回答非常好,但不幸的是,这与我想要实现的目标完全相反(我想显示操作栏,您向我解释如何隐藏它)
【解决方案3】:

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

【讨论】:

  • 当我尝试使用 Theme.AppCompat.Light.NoActionBar 时,我收到:*找不到与给定名称匹配的资源(在“主题”处,值为“@android:style/Theme.AppCompat.Light” .NoActionBar')。
  • 如果可能,请在此处提供帮助 https://stackoverflow.com/questions/58858810/clipboard-shows-a-different-label-special-on-samsung-android-phone
猜你喜欢
  • 2014-06-02
  • 2018-12-21
  • 2020-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多