私は伝統的なモンゴルの垂直EditText
を作っています。回転したEditText
の内部にわずかに変更したViewGroup
を埋め込むことで、実装に成功しました。システムの1つは垂直テキストをサポートしておらず、ViewGroup
が回転しても回転しないため、完全にカスタムコンテキストメニューを作成する必要があります。したがって、システムコンテキストメニューを完全に無効にします。
これは、コピー/貼り付けなどを無効にしようとしているこれらの質問とは異なることに注意してください。
シミュレーターにはコンテキストメニューが表示されませんが、Android 5.0.2 Xiaomi電話に表示されます。
私が試してみました:
setCustomSelectionActionModeCallback
"ソリューション"setLongClickable(false);
"ソリューション"onTouchEvent
"ソリューション"私はハッキングに対してオープンですが、デバイス間で一貫して動作するためにそれが必要です。マークマーフィー(Commons Guy) wrote 似たようなことをしようとしている別のユーザーへの返信でしばらく前:
あなたが答えを思いついたとしても、それはデバイス間で機能しないと思います。デバイスメーカーは、EditText用に独自の「コンテキストメニュー」を展開する傾向があり、開発者がそのコンテキストメニューにアイテムを追加しようとする試みを無効にしました。私の推測では、そのコンテキストメニューをブロックしようとすると、同様の結果になります。
私は運が悪いですか?
今考えられる唯一のことは、TextView
とEditText
を完全にゼロから書き換えることです(まあ、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を実行)は、カーソルハンドルをクリックしても表示されます(ただし、ロングクリックやダブルクリックでは表示されません)。これが画像です:
Android 5.0を実行しているXiaomi MIUI電話では、すべての状況でコンテキストメニューが表示されます(カーソルハンドルクリック、ロングクリック、ダブルクリック)。
Aritra Royのソリューションは、シミュレーター、彼がテストした他のいくつかのデバイス、および私のデバイスで動作しています。私の元の問題を解決するので、私は彼の答えを受け入れました。唯一のマイナスの副作用は、テキスト選択も無効になることです。
あなたがする必要がある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) {
}
}
}
_
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();
}
解決策は非常に簡単です
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) {
}
});
}
}
これは難しい問題です。私は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
mEditText.setLongClickable(false);
編集テキストを無効にする最も簡単な方法。
これは、コピーペーストメニューがどのような形、形、形であっても表示されないようにする方法です。このバグは本当に私を夢中にさせました。Samsungのバグと同様に、コード内でそのバグを知っていますが、すぐに修正されないこともわかっています。とにかく、不思議な壁があります...
Android.Build.Model.toLowerCase()。startsWith( 'sm-g930')かどうかを確認します。文字列全体と一致しないでください。最後の文字はマイナーバージョン識別子です。このブール値は、後で表示されるshouldBlockCopyPaste変数に格納しました。
一致する場合は、コピーペーストメニューの表示をブロックします。これが実際のやり方です!
これら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);
}
}