Cheok Yan Cheng
Cheok Yan Cheng

Reputation: 42690

How to make android:lineSpacingMultiplier behaves same for both EditText and TextView

I tend to create TextView and EditText, which looks visually pixel identical.

I overlay an EditText with TextView, so that I can compare their identical. I make TextView having red color text.

This is how they looks like so far.

EditText and TextView looks identical without android:lineSpacingMultiplier

enter image description here

This is the XML being used

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/body_text_view"
        android:gravity="top"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:layout_marginBottom="12dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:textSize="24sp"
        android:singleLine="false"
        android:textColor="#ff0000" />
    <EditText
        android:id="@+id/body_edit_text"
        android:gravity="top"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:layout_marginBottom="12dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:scrollbars="vertical"
        android:textSize="24sp"
        android:singleLine="false"
        android:inputType="textMultiLine|textCapSentences" />
</FrameLayout>

However, when comes with android:lineSpacingMultiplier, both behaves differently.

EditText and TextView looks different with android:lineSpacingMultiplier

enter image description here

This is the XML being used

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/body_text_view"
        android:gravity="top"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:layout_marginBottom="12dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:textSize="24sp"
        android:singleLine="false"
        android:textColor="#ff0000"
        android:lineSpacingMultiplier="2.4" />
    <EditText
        android:id="@+id/body_edit_text"
        android:gravity="top"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:layout_marginBottom="12dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:scrollbars="vertical"
        android:textSize="24sp"
        android:singleLine="false"
        android:inputType="textMultiLine|textCapSentences"
        android:lineSpacingMultiplier="2.4" />
</FrameLayout>

May I know, how to make android:lineSpacingMultiplier behaves same for both EditText and TextView, so that EditText and TextView can look visually identical?

p/s

Please don't suggest using EditText as replacement for TextView. They are not the same! You can have all sort of workaround trying to make EditText behave like TextView. (Stackoverflow has tone of suggestions on workaround. None of them will work perfectly) At the end of the day, it doesn't work!

Upvotes: 0

Views: 921

Answers (5)

Cheok Yan Cheng
Cheok Yan Cheng

Reputation: 42690

Apply the following 2 in TextView solves my problem

android:breakStrategy="simple"
android:textIsSelectable="true"

Upvotes: 0

Niraj Niroula
Niraj Niroula

Reputation: 2424

EditText is an extension (subclass) of TextView, yet the two are behaving differently here and that certainly is because of their unsimilar properties (either set from xml or those unsimilar by default). So the only way to align them perfectly is to look for those unsimilar properties that might be causing the issue and make them behave alike.
Considering "May I know, how to make android:lineSpacingMultiplier behaves same for both EditText and TextView, so that EditText and TextView can look visually identical?" as your main concern, I was able to align them perfectly by altering the following attributes of TextView.

As stated in this document (TextView class).

android:editable

If set, specifies that this TextView has an input method. It will be a textual one unless it has otherwise been specified. For TextView, this is false by default. For EditText, it is true by default.

This attribute has been deprecated but it can be replaced by

android:inputType

The type of data being placed in a text field, used to help an input method decide how to let the user enter text. The constants here correspond to those defined by InputType. Generally you can select a single value, though some can be combined together as indicated. Setting this attribute to anything besides none also implies that the text is editable.

To make it work efficiently use textMultiLine because your EditText has the same property.

android:breakStrategy

Sets the break strategy for breaking paragraphs into lines. The default value for TextView is Layout.BREAK_STRATEGY_HIGH_QUALITY, and the default value for EditText is Layout.BREAK_STRATEGY_SIMPLE, the latter to avoid the text "dancing" when being edited.

In a nutshell, adding

android:inputType="textMultiLine"
android:breakStrategy="simple"

to the TextView will place them exactly at the same position.

Upvotes: 2

Philippe Banwarth
Philippe Banwarth

Reputation: 17725

Oddly enough, adding

android:inputType="textMultiLine"

or

android:editable="true"

to the TextView seems to solve the problem

This does not make the textview really editable, and in fact it doesn't make sense, but it changes the effect of the lineSpacingMultiplier attribute.

Upvotes: 1

Zafar Hussain
Zafar Hussain

Reputation: 268

    lineSpacingExtra with 2dp worked fine for me but I was wondering what the Multiplier does instead?`<?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
        android:layout_height="match_parent">
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <TextView
                android:lineSpacingMultiplier="1.5"
                android:text="An editable text view that shows completion suggestions ... When you define an edit text widget, you must specify the R.styleable. .... android:lineSpacingMultiplier"
                android:id="@+id/body_text_view"
                android:gravity="top"
                android:paddingLeft="16dp"
                android:paddingRight="16dp"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/transparent"
                android:textSize="24sp"
                android:singleLine="false"
                android:textColor="#ff0000" />

            <EditText
                android:lineSpacingMultiplier="1.5"
                android:text="An editable text view that shows completion suggestions ... When you define an edit text widget, you must specify the R.styleable. .... android:lineSpacingMultiplier"
                android:gravity="top"
                android:paddingLeft="16dp"
                android:paddingRight="16dp"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/transparent"
                android:textSize="24sp"
                android:singleLine="false"
                android:textColor="#000000" />


        </FrameLayout>
    </android.support.constraint.ConstraintLayout>`



2nd way Not  android:lineSpacingMultiplier=" " use LineSpacingExtra insteed   LineSpacingMultiplier

 android:lineSpacingExtra="1.5dp"



  <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:lineSpacingExtra="1.5dp"
            android:text="An editable text view that shows completion suggestions ... When you define an edit text widget, you must specify the R.styleable. .... android:lineSpacingMultiplier DD"
            android:id="@+id/body_text_view"
            android:gravity="top"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/transparent"
            android:textSize="24sp"
            android:singleLine="false"
            android:textColor="#ff0000" />

        <EditText
            android:lineSpacingExtra="1.5dp"
            android:text="An editable text view that shows completion suggestions ... When you define an edit text widget, you must specify the R.styleable. .... android:lineSpacingMultiplier D"
            android:gravity="top"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/transparent"
            android:textSize="24sp"
            android:singleLine="false"
            android:textColor="#000000" />


    </FrameLayout>
</android.support.constraint.ConstraintLayout>

Upvotes: 0

Daniel B.
Daniel B.

Reputation: 2601

Instead of using lineSpacingMultiplier, use lineSpacingExtra and simply calculate with the multiplier you want to apply in the code.

I was able to replicate your problem on my machine, and indeed lineSpacingMultiplierproduces the same problem you were facing with, and couldn't find any solution/reason to why this would happen (not even on the Android Docs).

However, when I changed it to the same lineSpacingExtra, for example: lineSpacingExtra = 20dp, they were perfectly aligned.

So basically , you can calculate the spacing you want for your EditText and TextView, and apply that value through code like this:

float calculatedValue = 50.0f;
editText.setLineSpacing(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, calculatedValue,  getResources().getDisplayMetrics()), 1.0f);
textView.setLineSpacing(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, calculatedValue,  getResources().getDisplayMetrics()), 1.0f);

This approach worked for me, even when I played around with the calculatedValue,the text of both elements always aligns perfectly.

This is the xml I ended up using:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:layout_width="match_parent"

    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView
        android:id="@+id/body_text_view"
        android:gravity="top"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:layout_marginBottom="12dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:textSize="24sp"
        android:singleLine="false"
        android:textColor="#ff0000"
        android:lineSpacingExtra="0dp"/>
    <EditText
        android:id="@+id/body_edit_text"
        android:gravity="top"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:layout_marginBottom="12dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:scrollbars="vertical"
        android:textSize="24sp"
        android:singleLine="false"
        android:inputType="textMultiLine|textCapSentences"
        android:lineSpacingExtra="0dp"/>

</FrameLayout>

Image with line spacing set to 50 on both EditText And TextView:

Image with line spacing set to 50 on both <code>EditText</code> And <code>TextView</code>:

Upvotes: 0

Related Questions