web-dev-qa-db-ja.com

EditTextコンテキストメニューを無効にする

私は伝統的なモンゴルの垂直EditTextを作っています。回転したEditTextの内部にわずかに変更したViewGroupを埋め込むことで、実装に成功しました。システムの1つは垂直テキストをサポートしておらず、ViewGroupが回転しても回転しないため、完全にカスタムコンテキストメニューを作成する必要があります。したがって、システムコンテキストメニューを完全に無効にします。

これは、コピー/貼り付けなどを無効にしようとしているこれらの質問とは異なることに注意してください。

シミュレーターにはコンテキストメニューが表示されませんが、Android 5.0.2 Xiaomi電話に表示されます。

私が試してみました:

私はハッキングに対してオープンですが、デバイス間で一貫して動作するためにそれが必要です。マークマーフィー(Commons Guy) wrote 似たようなことをしようとしている別のユーザーへの返信でしばらく前:

あなたが答えを思いついたとしても、それはデバイス間で機能しないと思います。デバイスメーカーは、EditText用に独自の「コンテキストメニュー」を展開する傾向があり、開発者がそのコンテキストメニューにアイテムを追加しようとする試みを無効にしました。私の推測では、そのコンテキストメニューをブロックしようとすると、同様の結果になります。

私は運が悪いですか?

今考えられる唯一のことは、TextViewEditTextを完全にゼロから書き換えることです(まあ、Androidソース)を変更することによって。誰が同じようなことをしましたが、彼のコードはオープンソースではありません。

更新:過去2日間TextViewソースコードを変更しようとしており、6か月のプロジェクトのように見えます。相互に関連するクラスの集まりです。別の解決策が必要ですが、アイデアがありません。

[〜#〜] mvce [〜#〜]

これは、問題を再現するために考えられる最も簡単な方法です。カスタムEditTextには何も必要ありません。レイアウトには、デフォルトのプロジェクトHello WorldのEditTextを置き換えることによって作成された単一のTextViewがあります。非推奨メソッドの処理を避けるために、最小APIを11に変更しました。

public class MainActivity extends AppCompatActivity {

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

        EditText editText = (EditText) findViewById(R.id.edit_text);
        editText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
            @Override
            public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { return false; }
            @Override
            public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { return false; }
            @Override
            public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { return false; }
            @Override
            public void onDestroyActionMode(ActionMode actionMode) { }
        });
    }
}

シミュレータのコンテキストメニュー(API 24を実行)は、カーソルハンドルをクリックしても表示されます(ただし、ロングクリックやダブルクリックでは表示されません)。これが画像です:

enter image description here

Android 5.0を実行しているXiaomi MIUI電話では、すべての状況でコンテキストメニューが表示されます(カーソルハンドルクリック、ロングクリック、ダブルクリック)。

更新

Aritra Royのソリューションは、シミュレーター、彼がテストした他のいくつかのデバイス、および私のデバイスで動作しています。私の元の問題を解決するので、私は彼の答えを受け入れました。唯一のマイナスの副作用は、テキスト選択も無効になることです。

31
Suragch

あなたがする必要がある3つのことがあります。

ステップ1

これらのメソッドからfalseを返すことにより、コンテキストメニューの表示を無効にできます。

_mEditEext.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;
            }
        });
_

ステップ2

EditTextでのロングクリックも無効にする必要があります。

_mEditText.setLongClickable(false);
_

または、XMLの_Android:longClickable="false"_を実行します。

ステップ

次に、ハンドルをクリックしたときにメニューが表示されないようにする必要があります。解決策は簡単です、

1)EditTextクラスを拡張し、

2)isSuggestionsEnabled()をオーバーライドし、falseを返します。

3)canPaste()メソッドを作成し、falseを返します。これはメソッドの非表示です。

クイックソリューション

これらすべてを手動で行いたくない場合。これは、これをすばやく実行するために使用できるカスタムEditTextクラスです。しかし、私はまだあなたが物事がどのように機能するかを理解するために一度ステップを踏むことを勧めます。

_public class MenuHidingEditText extends EditText {
    private final Context mContext;

    public MenuHidingEditText(Context context) {
        super(context);
        this.mContext = context;

        blockContextMenu();
    }

    public MenuHidingEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;

        blockContextMenu();
    }

    public MenuHidingEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.mContext = context;

        blockContextMenu();
    }

    private void blockContextMenu() {
        this.setCustomSelectionActionModeCallback(new BlockedActionModeCallback());
        this.setLongClickable(false);
        this.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                MenuHidingEditText.this.clearFocus();
                return false;
            }
        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            // setInsertionDisabled when user touches the view
            this.setInsertionDisabled();
        }
        return super.onTouchEvent(event);
    }

    private void setInsertionDisabled() {
        try {
            Field editorField = TextView.class.getDeclaredField("mEditor");
            editorField.setAccessible(true);
            Object editorObject = editorField.get(this);

            Class editorClass = Class.forName("Android.widget.Editor");
            Field mInsertionControllerEnabledField = editorClass.getDeclaredField("mInsertionControllerEnabled");
            mInsertionControllerEnabledField.setAccessible(true);
            mInsertionControllerEnabledField.set(editorObject, false);
        }
        catch (Exception ignored) {
            // ignore exception here
        }
    }

    @Override
    public boolean isSuggestionsEnabled() {
        return false;
    }

    private class BlockedActionModeCallback implements ActionMode.Callback {

        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) {
        }
    }
}
_
25
Aritra Roy

EditTextに対してこのコードを作成しましたが、このような問題に対してはうまく機能しました。

try {
    edtName.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            edtName.setSelection(0);
        }
    });
    edtName.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            return true;
        }
    });
    edtName.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
        @Override
        public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { return false; }
        @Override
        public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { return false; }
        @Override
        public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { return false; }
        @Override
        public void onDestroyActionMode(ActionMode actionMode) { }
    });
} catch (Exception e) {
    e.printStackTrace();
}
4
Rjz Satvara

解決策は非常に簡単です

public class MainActivity extends AppCompatActivity {

EditText et_0;

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

    et_0 = findViewById(R.id.et_0);

    et_0.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            //to keep the text selection capability available ( selection cursor)
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            //to prevent the menu from appearing
            menu.clear();
            return false;
        }

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

        @Override
        public void onDestroyActionMode(ActionMode mode) {

        }
    });
   }
}

enter image description here

2
Muhammad Ali

これは難しい問題です。私はAndroid Studio 3.4.2で調査とテストに何時間も費やしました。

私は3つのステップを提案します:

a)元の質問では setCustomSelectionActionModeCallback "solution" しかし、選択ハンドルは引き続き表示されます(カーソルの下の赤いドロップ)赤いドロップをクリックすると、「クリップボード+すべて選択」ポップアップが表示されます。

b)選択ハンドル用に空の画像を作成します。 ic_empty.xmlの下にres/drawableというファイルを作成しました。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android">
</shape>

c)すべてのEditTextsに対してstyle.xmlのスタイルを作成しました。

メインテーマの下

 <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        ...
        <item name="Android:editTextStyle">@style/TStyle</item>
        ....
 </style>

したがって、空の画像をlef、middle、および右選択ハンドルに関連付けるスタイルを定義できます。

   <style name="TStyle" parent="@Android:style/Widget.EditText" >
        <item name="Android:textSelectHandle">@drawable/ic_empty</item>
        <item name="Android:textSelectHandleLeft">@drawable/ic_empty</item>
        <item name="Android:textSelectHandleRight">@drawable/ic_empty</item>
    </style>

ターゲットがAPI 23からのものである場合、setTextAppearance内のテキストにスタイルを付加するためにEditTextを使用できます。ただし、上記のソリューションは常に機能します

残っている唯一の問題は、ダブルクリック効果を取り除くことができるということです。テキスト内のピンク色の背景を持つWordを選択します。ただし、ユーザーの操作を必要としないため、比較的無害ですが厄介です。

実行できるトリックは、ハイライトの色を透明に設定することです。

EditT.setHighlightColor(Color.TRANSPARENT)  // EditT is a EditText
1
Paulo Buchsbaum
mEditText.setLongClickable(false);

編集テキストを無効にする最も簡単な方法。

1
udayatom

これは、コピーペーストメニューがどのような形、形、形であっても表示されないようにする方法です。このバグは本当に私を夢中にさせました。Samsungのバグと同様に、コード内でそのバグを知っていますが、すぐに修正されないこともわかっています。とにかく、不思議な壁があります...

  1. Android.Build.Model.toLowerCase()。startsWith( 'sm-g930')かど​​うかを確認します。文字列全体と一致しないでください。最後の文字はマイナーバージョン識別子です。このブール値は、後で表示されるshouldBlockCopyPaste変数に格納しました。

  2. 一致する場合は、コピーペーストメニューの表示をブロックします。これが実際のやり方です!

これら2つの関数をオーバーライドすると、shouldBlockCopyPasteブール値に気付くでしょう。これは、他のデバイスがブロックされないようにするためです。

   @Override
   public ActionMode StartActionMode (ActionMode.Callback callback){
      if (shouldBlockCopyPaste) {
        return null;
      } else {
        return super.StartActionMode(callback);
      }
    }

   @Override
   public ActionMode StartActionMode (ActionMode.Callback callback, int type){
      if (shouldBlockCopyPaste) {
        return null;
      } else {
        return super.StartActionMode(callback, type);
      }
    }
0
self.name