亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android EditText長按菜單中分享功能的隱藏方法

2019-10-21 21:19:27
字體:
來源:轉載
供稿:網友

常見的EditText長按菜單如下

Android,EditText,長按菜單,分享功能,隱藏

oppo

Android,EditText,長按菜單,分享功能,隱藏

小米

需求是隱藏掉其中的分享/搜索功能,禁止將內容分享到其他應用。

最終解決方案

這里先說下最終解決方案

像華為/oppo等手機,該菜單實際是谷歌系統的即沒有改過源代碼,像小米的菜單則是自定義,該部分的源代碼改動過。
兩方面修改:

1.谷歌系統自帶的 通過 EditText.setCustomSelectionActionModeCallback()方法設置自定義的選中后動作模式接口,只保留需要的菜單項

代碼如下

 editText.customSelectionActionModeCallback = object : ActionMode.Callback { override fun onCreateActionMode( mode: ActionMode?, menu: Menu? ): Boolean { menu?.let { val size = menu.size() for (i in size - 1 downTo 0) { val item = menu.getItem(i) val itemId = item.itemId //只保留需要的菜單項  if (itemId != android.R.id.cut && itemId != android.R.id.copy && itemId != android.R.id.selectAll && itemId != android.R.id.paste ) { menu.removeItem(itemId) } } } return true } override fun onActionItemClicked( mode: ActionMode?, item: MenuItem? ): Boolean { return false } override fun onPrepareActionMode( mode: ActionMode?, menu: Menu? ): Boolean { return false } override fun onDestroyActionMode(mode: ActionMode?) { } }

2.小米等手機自定義菜單無法進行隱藏,可以是分享、搜索等功能失效,即在BaseActivity的startActivityForResult中進行跳轉攔截,如果是調用系統的分享/搜索功能,則不允許跳轉

 override fun startActivityForResult( intent: Intent?, requestCode: Int ) { if (!canStart(intent)) return super.startActivityForResult(intent, requestCode) } @SuppressLint("RestrictedApi") @RequiresApi(Build.VERSION_CODES.JELLY_BEAN) override fun startActivityForResult( intent: Intent?, requestCode: Int, options: Bundle? ) { if (!canStart(intent)) return super.startActivityForResult(intent, requestCode, options) } private fun canStart(intent: Intent?): Boolean { return intent?.let { val action = it.action action != Intent.ACTION_CHOOSER//分享 && action != Intent.ACTION_VIEW//跳轉到瀏覽器 && action != Intent.ACTION_SEARCH//搜索 } ?: false }

如果以上不滿足要求,只能通過自定義長按菜單來實現自定義的菜單欄。

解決思路(RTFSC)

分析源碼菜單的創建和點擊事件

既然是長按松手后彈出的,應該在onTouchEvent中的ACTION_UP事件或者在performLongClick中,從兩方面著手
先看perfomLongEvent EditText沒有實現 去它的父類TextView中查找

TextView.java public boolean performLongClick() { ···省略部分代碼 if (mEditor != null) { handled |= mEditor.performLongClick(handled); mEditor.mIsBeingLongClicked = false; } ···省略部分代碼 return handled; }

可看到調用了 mEditor.performLongClick(handled)方法

Editor.java public boolean performLongClick(boolean handled) { if (!handled && !isPositionOnText(mLastDownPositionX, mLastDownPositionY) && mInsertionControllerEnabled) { final int offset = mTextView.getOffsetForPosition(mLastDownPositionX, mLastDownPositionY);//獲取當前松手時的偏移量 Selection.setSelection((Spannable) mTextView.getText(), offset);//設置選中的內容 getInsertionController().show();//插入控制器展示 mIsInsertionActionModeStartPending = true; handled = true; ··· } if (!handled && mTextActionMode != null) { if (touchPositionIsInSelection()) { startDragAndDrop();//開始拖動 ··· } else { stopTextActionMode(); selectCurrentWordAndStartDrag();//選中當前單詞并且開始拖動 ··· } handled = true; } if (!handled) { handled = selectCurrentWordAndStartDrag();//選中當前單詞并且開始拖動 ··· } } return handled; }

從上面代碼分析

1.長按時會先選中內容 Selection.setSelection((Spannable) mTextView.getText(), offset)

2.顯示插入控制器  getInsertionController().show()

3.開始拖動/選中單詞后拖動 startDragAndDrop()/ selectCurrentWordAndStartDrag()

看著很像了

看下第二步中展示的內容

Editor.java -> InsertionPointCursorController public void show() { getHandle().show(); if (mSelectionModifierCursorController != null) { mSelectionModifierCursorController.hide(); } } ··· private InsertionHandleView getHandle() { if (mSelectHandleCenter == null) { mSelectHandleCenter = mTextView.getContext().getDrawable( mTextView.mTextSelectHandleRes); } if (mHandle == null) { mHandle = new InsertionHandleView(mSelectHandleCenter); } return mHandle; }

實際是InsertionHandleView 執行了show方法。  查看其父類HandlerView的構造方法

 private HandleView(Drawable drawableLtr, Drawable drawableRtl, final int id) { super(mTextView.getContext()); ··· mContainer = new PopupWindow(mTextView.getContext(), null, com.android.internal.R.attr.textSelectHandleWindowStyle); ··· mContainer.setContentView(this); ··· }

由源碼可看出 HandlerView實際上是PopWindow的View。 即選中的圖標實際上是popwidow
看源碼可看出HandleView有兩個實現類 InsertionHandleView  和SelectionHandleView 由名字可看出一個是插入的,一個選擇的 看下HandleView的show方法

Editor.java ->HandleView public void show() { if (isShowing()) return; getPositionListener().addSubscriber(this, true ); // Make sure the offset is always considered new, even when focusing at same position mPreviousOffset = -1; positionAtCursorOffset(getCurrentCursorOffset(), false, false); }

看下positionAtCursorOffset方法

Editor.java ->HandleView  protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition, boolean fromTouchScreen) { ··· if (offsetChanged || forceUpdatePosition) { if (offsetChanged) { updateSelection(offset); ··· } ··· } }

里面有一個updateSelection更新選中的位置,該方法會導致EditText重繪,再看show方法的getPositionListener().addSubscriber(this, true )

getPositionListener()返回的實際上是ViewTreeObserver.OnPreDrawListener的實現類PositionListener
重繪會調用onPreDraw的方法

Editor.java-> PositionListener  @Override public boolean onPreDraw() { ··· for (int i = 0; i < MAXIMUM_NUMBER_OF_LISTENERS; i++) { ··· positionListener.updatePosition(mPositionX, mPositionY, mPositionHasChanged, mScrollHasChanged); ··· } ··· return true; }

調用了positionListener.updatePosition方法, positionListener這個實現類對應的是HandlerView

重點在HandleView的updatePosition方法,該方法進行popWindow的顯示和更新位置

看一下該方法的實現

Editor.java ->HandleView @Override public void updatePosition(int parentPositionX, int parentPositionY, boolean parentPositionChanged, boolean parentScrolled) { ··· if (isShowing()) { mContainer.update(pts[0], pts[1], -1, -1); } else { mContainer.showAtLocation(mTextView, Gravity.NO_GRAVITY, pts[0], pts[1]); } }  ··· } }

到此我們知道選中的圖標即下面紅框內的實際上popWindow展示

Android,EditText,長按菜單,分享功能,隱藏

點擊選中的圖標可以展示菜單,看下HandleView的onTouchEvent方法

Editor.java ->HandleView @Override public boolean onTouchEvent(MotionEvent ev) { updateFloatingToolbarVisibility(ev); ··· }

updateFloatingToolbarVisibility(ev)真相在這里,該方法進行懸浮菜單欄的展示
經過進一步查找,可以看到會調用下面SelectionActionModeHelper的這個方法

SelectionActionModeHelper.java public void invalidateActionModeAsync() { cancelAsyncTask(); if (skipTextClassification()) { invalidateActionMode(null); } else { resetTextClassificationHelper(); mTextClassificationAsyncTask = new TextClassificationAsyncTask(  mTextView,  mTextClassificationHelper.getTimeoutDuration(),  mTextClassificationHelper::classifyText,  this::invalidateActionMode)  .execute(); } }

會啟動一個叫TextClassificationAsyncTask的異步任務,該異步任務最后會執行mEditor.getTextActionMode().invalidate()

 private void invalidateActionMode(@Nullable SelectionResult result) { ··· final ActionMode actionMode = mEditor.getTextActionMode(); if (actionMode != null) { actionMode.invalidate(); } ··· }

最后看下mTextActionMode 如何在Editor中賦值

Editor.java void startInsertionActionMode() { ··· ActionMode.Callback actionModeCallback = new TextActionModeCallback(false /* hasSelection */); mTextActionMode = mTextView.startActionMode( actionModeCallback, ActionMode.TYPE_FLOATING); ··· }

看下mTextView.startActionMode的注釋,在View類中,Start an action mode with the given type. 根據給的類型,開啟一個動作模式,該模式是一個TYPE_FLOATING模式,菜單的生成就在TextActionModeCallback類中
在TextActionModeCallback的onCreateActionMode方法中

Editor.java ->TextActionModeCallback @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { mode.setTitle(null); mode.setSubtitle(null); mode.setTitleOptionalHint(true); //生成菜單 populateMenuWithItems(menu); Callback customCallback = getCustomCallback(); if (customCallback != null) { if (!customCallback.onCreateActionMode(mode, menu)) {  // The custom mode can choose to cancel the action mode, dismiss selection.  Selection.setSelection((Spannable) mTextView.getText(),  mTextView.getSelectionEnd());  return false; } } ··· }

生成的菜單的方法populateMenuWithItems(menu)中,生成完菜單會執行自定義的回調getCustomCallback() , 看下該回調如何賦值。

在TextView中

TextView.java public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) { createEditorIfNeeded(); mEditor.mCustomSelectionActionModeCallback = actionModeCallback; }

因此我們可以在自定義回調的onCreateActionMode方法中,刪除不需要的菜單項。

但該方法對小米手機無效,小米手機的菜單展示,不是通過startActionMode來展示的。不過可以對菜單中的分享等功能進行禁止跳轉,解決方法看最上面

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
激情成人在线视频| 欧美视频13p| 亚洲午夜女主播在线直播| 亚洲国产天堂久久综合| 久久不射热爱视频精品| 国产精品高潮呻吟久久av野狼| 日韩暖暖在线视频| 96国产粉嫩美女| 欧美日韩免费观看中文| 成人日韩av在线| 国产剧情久久久久久| 精品国产自在精品国产浪潮| 欧美性xxxx极品高清hd直播| 精品久久久久久| 国产在线观看91精品一区| 久久久免费在线观看| 久久艹在线视频| 国产男人精品视频| 欧美性jizz18性欧美| 欧美激情影音先锋| 欧美午夜www高清视频| 久久久久久久久电影| 国产欧美亚洲视频| 欧美在线视频a| 日韩精品亚洲精品| 亚洲护士老师的毛茸茸最新章节| 日韩视频一区在线| 国产日韩在线一区| 亚洲乱码国产乱码精品精| 国产精品视频中文字幕91| 97视频在线观看成人| 亚洲跨种族黑人xxx| 精品女同一区二区三区在线播放| 成人免费在线视频网址| 国产精品久久久久久久7电影| 国产精品久久久久久久久久| www高清在线视频日韩欧美| 亚洲精品久久久久久久久久久久久| 社区色欧美激情 | 久久视频免费在线播放| 欧美日韩亚洲精品一区二区三区| 亚洲一区二区三区四区在线播放| 国产精品jizz在线观看麻豆| 亚洲美女av在线播放| 国产欧美在线看| 麻豆乱码国产一区二区三区| 97婷婷涩涩精品一区| 久久99视频精品| 亚洲国产91精品在线观看| 国产精品久久久久久av福利软件| 久久99久久亚洲国产| 亚洲香蕉成人av网站在线观看| 午夜精品福利电影| 91精品啪aⅴ在线观看国产| 久久手机免费视频| 青青草原成人在线视频| 尤物九九久久国产精品的特点| 69**夜色精品国产69乱| 国产精品高潮呻吟视频| 97免费中文视频在线观看| www.久久色.com| 日韩高清av一区二区三区| 日本精品免费一区二区三区| 国产精品久久久久av免费| 91av视频在线| 国产亚洲成av人片在线观看桃| 亚洲直播在线一区| 91欧美精品午夜性色福利在线| 日韩在线精品一区| 性亚洲最疯狂xxxx高清| 精品亚洲va在线va天堂资源站| 亚洲综合自拍一区| 色悠悠久久久久| 中日韩美女免费视频网站在线观看| 日韩高清欧美高清| 欧美电影免费观看大全| 国产日韩欧美自拍| 精品福利在线看| 91系列在线播放| 久久精品视频网站| 国产精品自拍偷拍视频| 国产区精品视频| 亚洲深夜福利视频| 国产在线精品一区免费香蕉| 精品亚洲一区二区三区四区五区| 俺也去精品视频在线观看| 亚洲美女av在线| 岛国av在线不卡| 欧美刺激性大交免费视频| www.美女亚洲精品| 久久久电影免费观看完整版| 久久精品视频导航| 成人性生交大片免费看小说| 日韩精品极品毛片系列视频| 欧美性色19p| 欧美亚洲免费电影| 亚洲精品不卡在线| 中文字幕日韩欧美在线| 自拍偷拍亚洲区| 日韩欧亚中文在线| 亚洲小视频在线观看| 国产精品视频区| 这里只有精品在线观看| 日韩一级黄色av| 国产丝袜精品第一页| 亚洲缚视频在线观看| 欧美色播在线播放| 色综合伊人色综合网站| 国产一区二区三区在线| 日韩黄色在线免费观看| 91精品国产色综合久久不卡98口| 色老头一区二区三区在线观看| 亚洲成人免费在线视频| 九九九久久久久久| 欧美日韩国产麻豆| 久久伊人精品一区二区三区| 日产精品99久久久久久| 亚洲欧美另类自拍| 韩国三级日本三级少妇99| 8x拔播拔播x8国产精品| 亚洲欧美日韩区| 久久久最新网址| 色偷偷亚洲男人天堂| 亚洲新声在线观看| 久久6免费高清热精品| 日韩欧美在线播放| 92国产精品久久久久首页| 日韩在线观看免费高清完整版| 青草青草久热精品视频在线观看| 欧美特黄级在线| 国产suv精品一区二区三区88区| 亚洲专区国产精品| 色吧影院999| 欧美乱人伦中文字幕在线| 最近中文字幕日韩精品| 一区三区二区视频| 欧美影院成年免费版| 日韩免费中文字幕| 日韩av在线导航| 久久久亚洲福利精品午夜| 伊人久久久久久久久久| 日韩有码在线播放| 欧美黑人一级爽快片淫片高清| 国产精品黄页免费高清在线观看| 国产精品色视频| 自拍偷拍亚洲在线| 亚洲毛片在线观看.| 日韩影视在线观看| 91精品久久久久久久久久另类| 国产91精品久久久久久| 亚洲男女自偷自拍图片另类| 国产成人精品av| 国产日韩在线看| 米奇精品一区二区三区在线观看| 国产suv精品一区二区三区88区| 亚洲变态欧美另类捆绑| 国产精品入口免费视| 欧美精品在线播放| 亚洲第一页自拍| 国产va免费精品高清在线| 美女国内精品自产拍在线播放| 国产精品亚洲视频在线观看| 亚洲第一精品自拍| 午夜精品理论片|