EditText除了光標外還有選中時的左右下標以及點擊某個字符位置時的插入下標,分別爲SelectionHandleView 和 InsertionHandleView, 見Editor類。
Cursor
SelectionHandleView:
InsertionHandleView:
光標是如何顯示出來的
cursor對應的圖片可以通過style定製:
com.android.internal.R.styleable.TextView_textCursorDrawable
SelectionHandleView
SelectionHandleView有左右兩個,顯示流程如下
SelectionHandleView 繼承自HandleView, HandleView是一個PopupWindow.
1. 左右光標的圖標可以分別由以下兩個style來自定義:
com.android.internal.R.styleable.TextView_textSelectHandleLeft
com.android.internal.R.styleable.TextView_textSelectHandleRight
2. 其中View的寬度和高度取圖片本身的大小和com.android.internal.R.dimen.text_handle_min_size中小的那個值。
3. SelectionHandleView的顯示、隱藏及刷新是由SelectionModifierCursorController來控制
4. SelectionHandleView 是否顯示取決於以下方法中的兩個條件:
條件1:
ViewGroup.LayoutParams params = mTextView.getRootView().getLayoutParams(); if (params instanceof WindowManager.LayoutParams) { WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params; windowSupportsHandles = windowParams.type < WindowManager.LayoutParams.FIRST_SUB_WINDOW || windowParams.type > WindowManager.LayoutParams.LAST_SUB_WINDOW; }條件2:
boolean textCanBeSelected() { // prepareCursorController() relies on this method. // If you change this condition, make sure prepareCursorController is called anywhere // the value of this condition might be changed. if (mMovement == null || !mMovement.canSelectArbitrarily()) return false; return isTextEditable() || (isTextSelectable() && mText instanceof Spannable && isEnabled()); }其中isTextSelectable()是public方法,可以由setTextIsSelectable 或者
android.R.styleable#TextView_textIsSelectable 來設置
5. SelectionActionMode 是指長按選中TextView的文本時的行爲,實現類:TextActionModeCallback,繼承自ActionMode.CallBack2(實現了ActionMode.CallBack接口)。
TextView中長按選中TextView文本時的行爲默認是彈出的懸浮菜單,用戶可以通過下列方法自定義行爲:
/** * If provided, this ActionMode.Callback will be used to create the ActionMode when text * selection is initiated in this View. * * <p>The standard implementation populates the menu with a subset of Select All, Cut, Copy, * Paste, Replace and Share actions, depending on what this View supports. * * <p>A custom implementation can add new entries in the default menu in its * {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, android.view.Menu)} * method. The default actions can also be removed from the menu using * {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll}, * {@link android.R.id#cut}, {@link android.R.id#copy}, {@link android.R.id#paste}, * {@link android.R.id#replaceText} or {@link android.R.id#shareText} ids as parameters. * * <p>Returning false from * {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, android.view.Menu)} * will prevent the action mode from being started. * * <p>Action click events should be handled by the custom implementation of * {@link android.view.ActionMode.Callback#onActionItemClicked(ActionMode, * android.view.MenuItem)}. * * <p>Note that text selection mode is not started when a TextView receives focus and the * {@link android.R.attr#selectAllOnFocus} flag has been set. The content is highlighted in * that case, to allow for quick replacement. */ public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) { createEditorIfNeeded(); mEditor.mCustomSelectionActionModeCallback = actionModeCallback; }
且如果用戶自定義的callback中的onCreateActionMode返回爲false,那麼久不會有懸浮菜單欄出現,也會推出選中模式。@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; } }
............................
InsertionHandleView
InsertionHandleView同樣繼承自HandleView。它在一定時間後會自動消失。它同樣對應一個controller:
InsertionPointCursorController
1. InsertionHandleView 是否顯示上述條件1還取決於以下方法中的條件:
boolean isCursorVisible() { // The default value is true, even when there is no associated Editor return mCursorVisible && mTextView.isTextEditable(); }
由此可以看出,只要cursor顯示,就能顯示InsertionHandleView.反之,沒有辦法只顯示cursor而不顯示InsertionHandleView, 除非TextView所在的RootView的窗口類型事子窗口類型,也即:既不是應用程序窗口(如Activity)也不是者系統窗口。窗口類型的說明見:android 窗口類型分析。
2. 同樣用戶可以通過setCustomInsertionActionModeCallback 來自定義輸入狀態時的行爲。