このGoogleのガイド と このチュートリアル を使用して、独自のコンテキストアクションバーを作成しました。
_private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
// Called when the action mode is created; startActionMode() was called
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.annotation_menu, menu);
return true;
}
// Called each time the action mode is shown.
// Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false; // Return false if nothing is done
}
// Called when the user selects a contextual menu item
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.custom_button:
// do some stuff
break;
case R.id.custom_button2:
// do some other stuff
break;
default:
// This essentially acts as a catch statement
// If none of the other cases are true, return false
// because the action was not handled
return false;
}
finish(); // An action was handled, so close the CAB
return true;
}
// Called when the user exits the action mode
@Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
};
_
このメニューは、ユーザーがテキストを選択したときに表示されるように設計されているため、ネイティブのコピー/貼り付けメニューをオーバーライドします。今私は私の問題に行きます。
テキスト選択用の関数をオーバーライドしているので、LongClickListener
をWebView
に追加し、onLongClick(View v)
メソッドを実装して、ユーザーがいつ選択したかを検出できるようにしました。
_ myWebView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (mActionMode != null) {
return false;
}
mActionMode = startActionMode(mActionModeCallback);
v.setSelected(true);
return true;
}
});
_
長い間クリックすると、カスタムメニューが表示されますが、テキストが強調表示されていません。
テキスト選択機能が必要です。それがなければ、私のメニューは無意味です。
onLongClick(View v)
をオーバーライドしながら、Androidが提供するテキスト選択を維持するにはどうすればよいですか?
それが不可能な場合は、どこかでstartActionMode(mActionModeCallback)
を呼び出して、テキストが通常どおり選択されるようにできますが、カスタムメニューも表示されますか?
これらのどちらも可能でない場合...助けてください。
そこにIS簡単な方法!以下の更新を参照してください:D
私は この答え に従って提案に従いましたが、オーバーライドされたコードにさらに一致するように少し調整しました。
public class MyWebView extends WebView {
private ActionMode mActionMode;
private mActionMode.Callback mActionModeCallback;
@Override
public ActionMode startActionMode(Callback callback) {
ViewParent parent = getParent();
if (parent == null) {
return null;
}
mActionModeCallback = new CustomActionModeCallback();
return parent.startActionModeForChild(this, mActionModeCallback);
}
}
基本的に、これにより、カスタマイズされたCABがAndroid CABの代わりに表示されます。ここで、コールバックを変更して、テキストの強調表示がCABと共に消えるようにする必要があります。
public class MyWebView extends WebView {
...
private class CustomActionModeCallback implements ActionMode.Callback {
...
// Everything up to this point is the same as in the question
// Called when the user exits the action mode
@Override
public void onDestroyActionMode(ActionMode mode) {
clearFocus(); // This is the new code to remove the text highlight
mActionMode = null;
}
}
}
これですべてです。オーバーライドされたMyWebView
でstartActionMode
を使用している限り、ネイティブCAB(WebViewの場合はコピー/貼り付けメニュー)を取得する方法がないことに注意してください。そのような動作を実装することは可能かもしれませんが、それはこのコードが機能する方法ではありません。
このソリューションではActionMode
に対する制御が少なくなりますが、上記のソリューションよりはるかに少ないコードで済みます。
public class MyActivity extends Activity {
private ActionMode mActionMode = null;
@Override
public void onActionModeStarted(ActionMode mode) {
if (mActionMode == null) {
mActionMode = mode;
Menu menu = mode.getMenu();
// Remove the default menu items (select all, copy, paste, search)
menu.clear();
// If you want to keep any of the defaults,
// remove the items you don't want individually:
// menu.removeItem(Android.R.id.[id_of_item_to_remove])
// Inflate your own menu items
mode.getMenuInflater().inflate(R.menu.my_custom_menu, menu);
}
super.onActionModeStarted(mode);
}
// This method is what you should set as your item's onClick
// <item Android:onClick="onContextualMenuItemClicked" />
public void onContextualMenuItemClicked(MenuItem item) {
switch (item.getItemId()) {
case R.id.example_item_1:
// do some stuff
break;
case R.id.example_item_2:
// do some different stuff
break;
default:
// ...
break;
}
// This will likely always be true, but check it anyway, just in case
if (mActionMode != null) {
mActionMode.finish();
}
}
@Override
public void onActionModeFinished(ActionMode mode) {
mActionMode = null;
super.onActionModeFinished(mode);
}
}
ここにあなたが始めるためのメニューの例があります:
<!-- my_custom_menu.xml -->
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item
Android:id="@+id/example_item_1"
Android:icon="@drawable/ic_menu_example_1"
Android:showAsAction="always"
Android:onClick="onContextualMenuItemClicked"
Android:title="@string/example_1">
</item>
<item
Android:id="@+id/example_item_2"
Android:icon="@drawable/ic_menu_example_2"
Android:showAsAction="ifRoom"
Android:onClick="onContextualMenuItemClicked"
Android:title="@string/example_2">
</item>
</menu>
それでおしまい!完了です!これでカスタムメニューが表示され、選択を気にする必要がなくなり、ActionMode
ライフサイクルを気にする必要がほとんどなくなります。
これは、親全体WebView
を占有するActivity
とほぼ完璧に機能します。 View
内に一度に複数のActivity
が存在する場合、どれだけうまく機能するかわかりません。その場合、おそらく多少の調整が必要になります。
私が同様のことをした方法は、onTouchListenerをオーバーライドするだけで、GestureDetectorを呼び出してWebViewが長押しされたことを検出し、そこから私がやりたいことを実行することでした。以下は、WebViewでテキスト選択を犠牲にすることなく長押しイベントをキャッチできるサンプルコードです。うまくいけば、これが役立ちます。
@Override
protected void onCreate(Bundle savedInstanceState) {
WebView mWebView = (WebView) findViewById(R.id.myWebView);
GestureDetector mGestureDetector = new GestureDetector(this, new CustomGestureListener());
mWebView.setOnTouchListener(new OnTouchListener(){
@Override
public boolean onTouch(View view, MotionEvent arg1) {
//Suggestion #1 - this just lets the touch to be handled by the system but allows you to detect long presses
mGestureDetector.onTouchEvent(arg1);
return false;
//Suggestion #2 - this code will only let the touch be handled by the system if you don't detect a long press
return mGestureDetector.onTouchEvent(arg1);
}
});
}
private class CustomGestureListener extends SimpleOnGestureListener {
@Override
public void onLongPress(MotionEvent e) {
//do stuff
}
}