日本免费精品_最新日韩一区_亚洲视频一区在线_a在线视频观看_天天射夜夜骑_粉嫩av一区二区三区_欧美中日韩免费视频_综合图区欧美_国内精品美女在线观看_午夜精品久久久久久久男人的天堂

首頁 > 系統(tǒng) > Android > 正文

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

2019-10-21 21:19:27
字體:
供稿:網(wǎng)友

常見的EditText長按菜單如下

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

oppo

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

小米

需求是隱藏掉其中的分享/搜索功能,禁止將內(nèi)容分享到其他應(yīng)用。

最終解決方案

這里先說下最終解決方案

像華為/oppo等手機(jī),該菜單實(shí)際是谷歌系統(tǒng)的即沒有改過源代碼,像小米的菜單則是自定義,該部分的源代碼改動(dòng)過。
兩方面修改:

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

代碼如下

 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 //只保留需要的菜單項(xiàng)  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.小米等手機(jī)自定義菜單無法進(jìn)行隱藏,可以是分享、搜索等功能失效,即在BaseActivity的startActivityForResult中進(jìn)行跳轉(zhuǎn)攔截,如果是調(diào)用系統(tǒng)的分享/搜索功能,則不允許跳轉(zhuǎn)

 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//跳轉(zhuǎn)到瀏覽器 && action != Intent.ACTION_SEARCH//搜索 } ?: false }

如果以上不滿足要求,只能通過自定義長按菜單來實(shí)現(xiàn)自定義的菜單欄。

解決思路(RTFSC)

分析源碼菜單的創(chuàng)建和點(diǎn)擊事件

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

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

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

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

從上面代碼分析

1.長按時(shí)會(huì)先選中內(nèi)容 Selection.setSelection((Spannable) mTextView.getText(), offset)

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

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

看著很像了

看下第二步中展示的內(nèi)容

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; }

實(shí)際是InsertionHandleView 執(zhí)行了show方法。  查看其父類HandlerView的構(gòu)造方法

 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實(shí)際上是PopWindow的View。 即選中的圖標(biāo)實(shí)際上是popwidow
看源碼可看出HandleView有兩個(gè)實(shí)現(xiàn)類 InsertionHandleView  和SelectionHandleView 由名字可看出一個(gè)是插入的,一個(gè)選擇的 看下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); ··· } ··· } }

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

getPositionListener()返回的實(shí)際上是ViewTreeObserver.OnPreDrawListener的實(shí)現(xiàn)類PositionListener
重繪會(huì)調(diào)用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; }

調(diào)用了positionListener.updatePosition方法, positionListener這個(gè)實(shí)現(xiàn)類對應(yīng)的是HandlerView

重點(diǎn)在HandleView的updatePosition方法,該方法進(jìn)行popWindow的顯示和更新位置

看一下該方法的實(shí)現(xiàn)

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]); } }  ··· } }

到此我們知道選中的圖標(biāo)即下面紅框內(nèi)的實(shí)際上popWindow展示

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

點(diǎn)擊選中的圖標(biāo)可以展示菜單,看下HandleView的onTouchEvent方法

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

updateFloatingToolbarVisibility(ev)真相在這里,該方法進(jìn)行懸浮菜單欄的展示
經(jīng)過進(jìn)一步查找,可以看到會(huì)調(diào)用下面SelectionActionModeHelper的這個(gè)方法

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

會(huì)啟動(dòng)一個(gè)叫TextClassificationAsyncTask的異步任務(wù),該異步任務(wù)最后會(huì)執(zhí)行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. 根據(jù)給的類型,開啟一個(gè)動(dòng)作模式,該模式是一個(gè)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)中,生成完菜單會(huì)執(zhí)行自定義的回調(diào)getCustomCallback() , 看下該回調(diào)如何賦值。

在TextView中

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

因此我們可以在自定義回調(diào)的onCreateActionMode方法中,刪除不需要的菜單項(xiàng)。

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

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網(wǎng)的支持。


注:相關(guān)教程知識閱讀請移步到Android開發(fā)頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
国产传媒久久久| 粉嫩粉嫩芽的虎白女18在线视频| 亚洲一卡二卡在线观看| 午夜av一区二区| 日韩在线视频精品| 日韩福利视频导航| 欧美日韩视频免费看| 欧美片网站免费| 欧美三级日韩在线| 欧美日韩国产一二| 中文字幕亚洲在| 久久精品不卡| 日韩不卡一二区| 一级片免费在线| 国产欧美高清在线| 国产一级一片免费播放| 欧美日韩一二三| 国产乱国产乱300精品| aaa大片在线观看| 国产123在线| 国产乱码午夜在线视频| 日韩中文字幕久久| 日韩欧美三级视频| 欧美日韩在线视频一区| 欧美日韩视频免费播放| 日韩精品福利视频| 国产乱国产乱老熟300| 国产午夜精品全部视频播放| 日韩av一区二| 亚洲乱码中文字幕综合| 国产视频一二区| 99精品免费观看| 在线一区av| 91精品国产色综合久久久蜜香臀| 日韩中文在线视频| 国产区在线看| 国产在线精品国自产拍免费| 午夜影院在线观看欧美| 91精品在线免费| 婷婷久久综合网| 国产99精品| 国产高清视频一区二区| 日韩av一区二区在线| 国产黄色精品| 樱花草www在线观看| 亚洲欧美韩国综合色| 韩日中文字幕第一页| 视频一区二区不卡| 国产在线看一区| 亚洲日本精品视频| 日韩免费电影网站| 国产成人中文字幕| av丝袜在线| 日韩av一区二区在线观看| 日韩精品欧美| 亚洲国产www| 日韩国产一区| 欧美日韩亚洲一区| 欧美一级搡bbbb搡bbbb| 亚洲高清中文字幕| 久久99精品久久久久久青青日本| 国产黄色在线播放| 精品视频www| 欧美日韩综合在线观看| 香蕉精品久久| 亚洲国产综合久久| 精品熟女一区二区三区| 日韩国产欧美三级| 精品一二线国产| 日韩视频在线一区二区| 91精品国产自产| 国产视频一区三区| 午夜一区二区三区| 亚洲第一中文字幕| 天堂在线中文| 国产欧美综合在线| 正在播放日韩精品| 日韩在线中文字幕| 精品一性一色一乱农村| 久草亚洲一区| 一区二区三区在线|网站| 国产黄在线观看免费观看不卡| 色综合婷婷久久| 日韩精品在线网站| 日韩欧美在线不卡| 日韩欧美视频一区二区三区四区| 亚洲 欧美 中文字幕| 欧美中文字幕视频| 国产天堂素人系列在线视频| 国产欧美日韩精品在线观看| 日韩中文字幕精品视频| 日韩免费高清一区二区| 久草视频观看| 欧美日韩久久久| 亚洲综合欧美在线| 欧美日韩性视频一区二区三区| 亚洲女同中文字幕| 日韩一级免费视频| 欧美99久久| 一区二区三区高清在线| 中文在线а√在线8| 精品国产乱码久久久久久牛牛| 欧美日韩国产专区| 精品国产乱码久久久久久蜜臀| 91精品久久久久久久91蜜桃| 欧美中文字幕在线视频| 日韩精品中文字幕第1页| 日韩不卡av| 樱花草www在线观看| 亚洲日本欧美日韩高观看| 日韩中文字幕国产| 亚洲精品中文字幕乱码三区不卡| 一区二区精品区| 国产福利不卡| 中文字幕久久精品| 亚洲高清在线免费| 91精品国产入口| 精品区一区二区| 欧美国产一级片| 午夜伊人狠狠久久| 国产福利第一页| 国产日韩中文字幕在线| 一区二区精品| 九一久久久久久| 天堂在线www天堂中文在线 | 中文字幕国产视频| 欧美日韩国产综合视频在线观看中文| av手机天堂| 国产一级免费在线观看| 色欧美日韩亚洲| 日韩三级视频中文字幕| 国产最新在线| 欧美日韩中文在线| 欧美中文字幕视频在线观看| 欧美日韩国产一区中文午夜| 中文字幕日韩欧美| 91精品国产全国免费观看| 久久精品在线免费观看| 精品国产99| 顶级网黄在线播放| 最近中文字幕日韩精品| 亚洲v中文字幕| 日韩欧美在线第一页| 欧美日韩三级在线| 日韩中文字幕网| 久久中文免费视频| 蜜桃精品在线| 中文字幕在线观看视频www| 欧美日韩精品综合| 久精品在线观看| 国产成人中文字幕| 极品久久久久久| 国产小视频在线| 一本大道一区二区三区| 国产欧美日产一区| 久久夜色精品国产噜噜亚洲av| 国产一级视频| 1区2区3区在线视频| 亚洲欧美中文在线视频| 精品日韩视频在线观看| 国产三级视频在线播放线观看| 精品久久蜜桃| 美女免费视频一区| 日本精品二区| 国产123在线| 人妻一区二区三区免费| 精品一区二区三区中文字幕| 国产黄在线看| 中文精品在线观看| 精品调教chinesegay| 欧美日韩一级视频| 一级片免费网站| 亚洲第一精品在线| 精品国产99久久久久久| 精品久久人人做人人爽| 日韩欧美成人一区二区三区| 国产一区免费视频| 一区二区在线看| 九九在线精品| 亚洲午夜91| 999精品网| 久久精品国产2020观看福利| 日韩精品欧美| 99pao成人国产永久免费视频| 国产嫩草影院久久久久| 国产视频一区三区| 日韩高清不卡一区二区| 久久久久久久久综合| 亚洲福利视频专区| 不卡专区在线| 国产乱国产乱300精品| 日韩一级精品| 国产欧美综合视频| 中文字幕第一页在线播放| 久久久久久久久99精品| 日韩av一区二区在线| 在线精品视频免费播放| 亚洲视频中文字幕| 久久精品网站免费观看| 尤物在线精品| 精品网站999www| 综合激情国产一区| a视频免费在线观看| 国产日韩精品在线观看| 欧美日韩在线中文字幕| 国产在线一在线二| 色综合影院在线| 精品999视频| 免费高清在线一区| 久久99精品国产| 欧美日韩国产专区| 在线视频不卡国产V| 999精品网| 国产三级做爰在线观看| 国产69精品久久app免费版| 日本亚洲视频在线| 最近免费中文字幕在线第一页| 久精品在线观看| 久久91精品久久久久久秒播| 一区二区高清视频| a视频免费看| 精品日韩av一区二区| 欧美日韩国产中字 | 亚洲午夜91| www高清在线视频日韩欧美| 久久久精品福利| 国产视频一二区| 中文字幕 欧美 日韩| 精品视频在线导航| 免费看黄资源大全高清| 欧美不卡123| 日韩亚洲欧美中文字幕| 国产一区在线精品| 一区免费视频| 欧美国产一级片| 亚洲视频中文字幕| 天天摸日日摸狠狠添| 亚洲影视资源网| 亚洲一区资源| www.三级.com| 亚洲第一福利视频在线| 日韩a一区二区| 国产羞羞视频在线播放| 狠狠色噜噜狠狠狠狠97| 日韩精品a在线观看91| 国产亚洲视频中文字幕视频| 蜜桃久久av一区| 日韩午夜高潮| 国产亚洲污的网站| 欧美色视频一区二区三区在线观看| 日韩中文字幕视频在线观看| 激情婷婷亚洲| 中文精品电影| 亚洲日本精品视频| 亚洲第一中文字幕在线观看| 成人a在线观看| 日韩视频1区| 日韩在线高清| 99精品999| 一区二区三区精品久久久| 国产黄色在线网站| 日韩中文字幕精品视频| 日韩欧美国产综合| 亚洲欧美中文在线视频| 亚洲 欧美 日韩系列| 久久精品欧美日韩精品| 欧美三级中文字幕在线观看| 欧美一级手机免费观看片| 国产日韩中文字幕在线| www.三级.com| 在线观看中文字幕一区| 日韩在线视频中文字幕| 伊人伊成久久人综合网小说| 在线视频1区2区| 91久久久精品| 中文网丁香综合网| 999精品视频在线观看播放| 精品视频www| 国产 日韩 欧美 综合 一区| 欧美日韩91| 日韩中文首页| 欧美国产91| 欧美日韩中文| 欧美日韩三级视频| 日韩中文字幕视频网| 日韩精品视频中文字幕| 亚洲成年人影院在线| 日本黄色一区二区| 91精品视频国产| 91精品国产自产在线丝袜啪| 日韩欧美不卡| 国产蜜臀在线| 高清日韩中文字幕| 国产一区精品在线| 1区2区3区在线视频| 国产丝袜一区二区| av一卡二卡| 黄色国产在线| 久久精品不卡| 你懂的亚洲视频| 中文精品电影| 欧美日韩一二| 中文字幕在线高清| 日本xxxwww免费视频| 国产亚洲人成a一在线v站| 国产日韩三级| 精品成a人在线观看| 中文字幕在线高清| 亚洲一级特黄| 欧美日韩在线视频免费观看| 国产视频中文字幕在线观看| 国产真实乱子伦精品视频| 91精品久久久久久久91蜜桃| 精品中文字幕视频| 91精品日本| 亚洲欧洲综合另类| 欧美日韩性视频| 久久永久免费视频| www..com日韩| 国产一卡二卡3卡4卡四卡在线 | 欧美中文字幕在线观看视频| 91精品国产自产91精品| 亚洲一级特黄| 亚洲天堂国产视频| 综合激情国产一区| 国产一二三区精品视频| 中文字幕日韩视频| 国产一级在线免费观看| 国产在线欧美| 亚洲免费精品| 91精品视频国产| 国产在线拍偷自揄拍精品| 日韩欧美专区在线| 日韩欧美在线视频日韩欧美在线视频| 国产视频三级在线观看播放| 亚洲最新永久观看在线| 欧美日韩国产不卡| 欧美日韩在线视频首页| 天堂在线中文| 精品久久九九| 日韩精品在线第一页| 不卡av免费在线| 色www精品视频在线观看| 欧美一级在线免费| 国产欧美自拍一区| 国产成人精品免费久久久久| 日韩精品在线免费观看视频| 欧美亚洲天堂网| 最新中文字幕在线| 视频一区二区精品的福利| 一区二区三区视频网站| 中文字幕亚洲一区在线观看| 久久精品电影| 日韩欧美一二三四区| 欧美日韩成人综合| 精品久久蜜桃| 亚洲第一精品在线| 综合激情国产一区| 欧美变态tickling挠脚心| 最近中文字幕日韩精品| 国产拍揄自揄精品视频麻豆| 国产蜜臀在线| 日本国产一区| www中文字幕| www..com日韩| 色综合婷婷久久| 国产三级做爰在线观看| 久久91精品久久久久久秒播| 在线观看免费国产小视频| 日韩中文字幕综合| 日韩不卡一二区| 欧美日韩国产高清一区| 国产成人综合精品| 二区视频在线观看| 亚洲a一级视频| 国产一区三区三区| 日韩久久精品视频| 欧美激情一区二区在线| 日韩不卡一区二区| 亚洲乱码视频| 欧美日韩视频免费| 欧美日韩尤物久久| 99精品人妻国产毛片| 福利在线国产| 中文字幕在线视频第一页| 欧美日韩精品是欧美日韩精品| 国产高清精品在线观看| 欧美日韩亚洲不卡| 日韩在线视频观看正片免费网站| 黄色资源在线观看| 日韩不卡在线播放| 91精选在线| 国产成人精品综合网站| 欧美一级日韩一级| 香蕉人人精品| www.91香蕉视频| 中文字幕一区不卡| 国产亚洲欧美中文| 久艹在线视频| 国产欧美中文字幕|