最近开发遇到了需要获取EditText光标的位置,以及获取光标的位置,查找网络找到这些代码,给自己做个笔记,也给广大开发这一个小小的提醒;
不多说,直接上代码,获取光标所在的位置,需要用到反射:
/** * @return the coordinate of cursor. x=float[0]; y=float[1]; */ private float[] getCursorCoordinate (){ /* *以下通过反射获取光标cursor的坐标。 * 首先观察到TextView的invalidateCursorPath()方法,它是光标闪动时重绘的方法。 * 方法的最后有个invalidate(bounds.left + horizontalPadding, bounds.top + verticalPadding, bounds.right + horizontalPadding, bounds.bottom + verticalPadding); *即光标重绘的区域,由此可得到光标的坐标 * 具体的坐标在TextView.mEditor.mCursorDrawable里,获得Drawable之后用getBounds()得到Rect。 * 之后还要获得偏移量修正,通过以下三个方法获得: * getVerticalOffset(),getCompoundPaddingLeft(),getExtendedPaddingTop()。 * */ int xOffset = 0; int yOffset = 0; Class<?> clazz = EditText.class; clazz = clazz.getSuperclass(); try { Field editor = clazz.getDeclaredField("mEditor"); editor.setAccessible(true); Object mEditor = editor.get(mEditText); Class<?> editorClazz = Class.forName("android.widget.Editor"); Field drawables = editorClazz.getDeclaredField("mCursorDrawable"); drawables.setAccessible(true); Drawable[] drawable= (Drawable[]) drawables.get(mEditor); Method getVerticalOffset = clazz.getDeclaredMethod("getVerticalOffset",boolean.class); Method getCompoundPaddingLeft = clazz.getDeclaredMethod("getCompoundPaddingLeft"); Method getExtendedPaddingTop = clazz.getDeclaredMethod("getExtendedPaddingTop"); getVerticalOffset.setAccessible(true); getCompoundPaddingLeft.setAccessible(true); getExtendedPaddingTop.setAccessible(true); if (drawable != null){ Rect bounds = drawable[0].getBounds(); Log.d(TAG,bounds.toString()); xOffset = (int) getCompoundPaddingLeft.invoke(mEditText) + bounds.left; yOffset = (int) getExtendedPaddingTop.invoke(mEditText) + (int)getVerticalOffset.invoke(mEditText, false)+bounds.bottom; } } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } float x = mEditText.getX() + xOffset; float y = mEditText.getY() + yOffset; return new float[]{ x , y}; }而获取所在的行号,比较简单,只需要如下即可:
private int getCurrentCursorLine(EditText editText) { int selectionStart = Selection.getSelectionStart(editText.getText()); Layout layout = editText.getLayout(); if (selectionStart != -1) { return layout.getLineForOffset(selectionStart) + 1; } return -1; }