Reputation: 5295
i am trying to make an Edittext
with a good amount of line spacing. It is working but the cursor is not in the correct position. Look at the image below. As you can see the cursor is halfway in between the lines.
Here is the Edittext Code :-
<EditText
android:id="@+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:fadingEdge="vertical"
android:gravity="left|center_vertical"
android:lineSpacingExtra="10dp"
android:lineSpacingMultiplier="2"
android:padding="18dp"
android:scrollbars="vertical"
android:textSize="22sp" >
<requestFocus />
</EditText>
Upvotes: 3
Views: 4450
Reputation: 11695
There is another problem if you're using textCursorDrawble
with lineSpacingExtra
: when your app is running above Lollipop, because the line height won't be changed for the last line, if you defines a negative bottom padding in your custom textCursorDrawable
, the cursor will be shrank in last line like this:
To achieve more dramatic effect, I set the lineSpacingExtra
to 8dp
, and a part of my custom textCursorDrawable
is <padding android:bottom="-8dp"/>
. As a result, you can see the small cursor appearing in last line.
Of course we don't like this. I searched this in Internet for hours and days, but no page helps. But don't worry for this if you saw this answer since I've solved it in my way, which is a little hacky but works well as far as I know.
The root cause of our problem is that we've set a bottom padding to the textCursorDrawable
, made it shorter for all lines. Let's say the text size is 12dp, then the original line height is also 12dp(just make things easier). After we define a lineSpacingExtra="8dp"
, the line height will increase to 20dp. If we don't do anything to textCursorDrawable
, the cursor height will also be 20dp now, which is longer than text size apparently, so we shorten it, cut the bottom 8dp by defining <padding android:bottom="-8dp"/>
in custom textCursorDrawable
shape xml file. However, above Lollipop, lineSpacingExtra
is ignored for the last line, so the line height of that remains at 12dp. So does the cursor of last line if we don't use custom one. And then we cut 8dp of that and now we see a 4dp cursor, which is wrong, while the correct operation is stopping setting the -8dp bottom padding in custom textCursorDrawable
.
So the solution is: use different textCursorDrawable
for normal lines and last line, showing enough respect to special one.
Then, when should we change the textCursorDrawable
? My answer is: when user clicks last line of your EditText
. This is reasonable because the cursor can only appear after this operation(maybe not the last operation if user clicks "enter" after this, but that doesn't influence our solution).
Next step is listening for user's clicking on last line. My solution is crude:
mEditText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
EditText et = (EditText) v;
// lineSpacingExtra's unit is px.
int lastLineHeight = (int) (et.getLineHeight() - et.getLineSpacingExtra());
if (et.getHeight() - event.getY() <= lastLineHeight) {
setTextCursorDrawable(et, lastLineCursorRes);
} else {
setTextCursorDrawable(et, normalCursorRes);
}
return true;
}
return false;
}
});
And This is the not elegant(but we have to) implementation for setTextCursorDrawable
:
public void setTextCursorDrawable(EditText et, @DrawableRes int res) {
try {
Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
f.setAccessible(true);
f.set(et, res);
} catch (Exception ignored) {}
}
Finally, the special part of lastLineCursorRes
:
<padding android:bottom="0dp"/>
OK, there you go. Please be noticed that I wrote this answer just after I tried on this solution and found it worked, which means I didn't check it very carefully. If you meet any problems with this solution, please comment.
REFERENCES
To know why lineSpacingExtra/Multiplier
is ignored in last line of TextView
and its subclasses, check: How LineSpace Affects StaticLayout Height in One Line Text, Android TextView 行间距解析(in Chinese) and StaticLayout源码解析(in Chinese).
Upvotes: 1
Reputation: 19
The answer that you have to use android:textCursorDrawable="@drawable/name_of_your_drawable" and set your own drawable of cursor and in padding you should set value of android:bottom="-20sp"(or your size of text) .Like in example.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.androisxxxsxsxd.com/apk/res/android"
android:shape="rectangle" >
<size
android:width="2dip" />
<solid
android:color="@color/red" />
<padding
android:top="2sp"
android:bottom="-20sp" />
</shape>
myxml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<EditText
android:id="@+id/edittext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:paddingTop="18dp"
android:gravity="left|center_vertical"
android:lineSpacingExtra="20dp"
android:textCursorDrawable="@drawable/d"
android:text="test"
/>
Upvotes: 1