android – Keep text in TextView with drawableLeft centered-ThrowExceptions

Exception or error:

In my app I have a header bar which consists of a single textview with fill_parent as width, which have a specific background color and some centered text. Now I want to add a drawable on the left side of the header bar, so I set the drawableLeft and sure enough the text and image is displayed. However the problem here is that the text is no longer properly centered, e.g., when the drawable is added the text is shifted a bit to the right as shown in the screenshots here:

without drawable
with drawable

Is there anyway I can center the text properly and have the drawable positioned as it is above without using an additional layout item (such as a LinearLayout)?

How to solve:

Though fragile, you can avoid the use of a wrapper Layout by setting a negative padding on the drawable:

<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerHorizontal="true"
    android:drawableLeft="@drawable/icon"
    android:drawablePadding="-20sp"
    android:text="blah blah blah" />

You’ll have to adjust the padding to the width of the drawable, but you’re left with just a single TextView instead of an extra LinearLayout or etc.

###

Try following:

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:padding="10dp"
    android:textAlignment="center" />

###

You can set the parent of the TextView as a RelativeLayout whose width is match_parent.

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<TextView
        android:id="@+id/edit_location_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/add_location_text_view"
        android:gravity="start|center_vertical"
        android:layout_centerHorizontal="true"
        android:drawableStart="@android:drawable/ic_menu_edit"
        android:text="Edit Location" />

</RelativeLayout>

This is what the result looks like.

###

I’ve faced a similar problem. Solved it by using single TextView with layout_width="wrap_content" and layout_gravity="center" parameters:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawableLeft="@drawable/some_drawable"
    android:text="some text"
    android:layout_gravity="center"
    android:gravity="center"
    />

###

I had same problem and I solved it with small changes in Textview,

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:drawableLeft="@drawable/search_red"
    android:text="your text goes here"
    />

###

use this way

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@color/White"
     >

  <RelativeLayout
       android:id="@+id/rlheader"
       android:layout_width="fill_parent"
       android:layout_height="50dp"
       android:layout_alignParentTop="true"
       android:background="@color/HeaderColor"

        >

        <TextView

           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_centerHorizontal="true"
           android:layout_centerVertical="true"
           android:text="Header_Title"
            />

        <ImageView
           android:id="@+id/ivSetting"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_alignParentLeft="true"
           android:layout_centerVertical="true"
           android:layout_marginLeft="10dp"
           android:src="@drawable/setting" />


    </RelativeLayout>

</RelativeLayout>

it look something like this snap of my demo project

Header Image

###

That work for me.

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="horizontal">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:drawableLeft="@drawable/trusted"
        android:gravity="center"
        android:text="@string/trusted"/>

</LinearLayout>

###

You can use android:gravity="center_vertical" to center the text vertically with the image. Or it can be centered inside the textView using android:gravity="center".

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:drawableLeft="@drawable/icon"
    android:text="Your text here" />

###

> This line is important ->> android:gravity="start|center_vertical


 <LinearLayout
            android:layout_width="match_parent"
            android:layout_margin="@dimen/marginplus2"
            android:layout_height="wrap_content">

            <TextView
                android:layout_width="0dp"
                android:layout_weight="1"
                android:text="@string/like"
                android:gravity="start|center_vertical"
                android:drawablePadding="@dimen/marginplus1"
                android:drawableLeft="@drawable/ic_like"
                android:layout_height="wrap_content" />

            <TextView
                android:layout_width="0dp"
                android:layout_weight="1.5"
                android:text="@string/comments"
                android:drawablePadding="@dimen/marginplus1"
                android:gravity="start|center_vertical"
                android:drawableLeft="@drawable/ic_comment"
                android:layout_height="wrap_content" />
            <TextView
                android:layout_width="0dp"
                android:layout_weight="1"
                android:text="@string/share"
                android:drawablePadding="@dimen/marginplus1"
                android:gravity="start|center_vertical"
                android:drawableLeft="@drawable/ic_share"
                android:layout_height="wrap_content" />

        </LinearLayout>

###

u can set your header like this

<RelativeLayout
             android:id="@+id/linearLayout1"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:background="@drawable/head" >

             <ImageView
                 android:id="@+id/cat"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"

                 android:layout_marginLeft="5dp"
                 android:onClick="onClick"
                 android:layout_marginTop="10dp"
                 android:src="@drawable/btn_back_" />


         <RelativeLayout
             android:id="@+id/linearLayout1"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:gravity="center" >

           <TextView
 android:id="@+id/TvTitle"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text=""
 android:layout_marginLeft="10dp"
 android:layout_marginRight="10dp"
 android:textColor="#000000" 

 android:textSize="20sp"/>
             </RelativeLayout>

         </RelativeLayout>

Just Give Hieght of Textview,image source as per your need

###

drawable is part of the TextView, so the textview’s height will be the drawable’s height if your text’s height is smaller than drawable’s height.

You can set TextView’s gravity attribute to center_vertical, so the text will be in the center.

###

<TextView
    android:id="@+id/distance"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:drawableLeft="@drawable/distance"
    android:drawablePadding="10dp"
    android:padding="10dp"
    android:textAlignment="center"
    android:textColor="#ffffff"
    android:textSize="20sp" />

###

One simple solution is to use a transparent image with the same size on the opposite side of the textview.
In my example i copied my actual vector_image and changed the colors to be transparent.

<TextView
        android:id="@+id/name"
        style="@style/TextStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:drawableEnd="@drawable/ic_vector_caret_down_green"
        android:drawableStart="@drawable/ic_vector_space_18"
        android:gravity="center"
        android:padding="12dp"
        android:textColor="@color/green"/>

###

Remove the DrawableLeft and use a container FrameLayout.

<FrameLayout
     android:id="@+id/container"
     android:layout_width="match_parent"
     android:layout_height="wrap_content" >

     <ImageView
         android:id="@+id/image"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginLeft="5dp"
         android:layout_gravity="center_vertical"
         android:src="@drawable/image" />

     <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Text"
        android:layout_gravity="center" />
</FrameLayout>

###

If none of the above solutions did not work for you?. Then try below answer

Sample screen shot of the design.
enter image description here

For the above image please find the code below.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.CardView
        android:id="@+id/my_card"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:id="@+id/bb"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:divider="@color/gray"
            android:orientation="horizontal"
            android:weightSum="2">

            <TextView
                android:id="@+id/filter_tv"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="?attr/actionBarSize"
                android:layout_gravity="center_horizontal"
                android:layout_weight="1"
                android:drawableLeft="@drawable/ic_baseline_filter_list"
                android:gravity="center|fill_horizontal"
                android:paddingLeft="60dp"
                android:text="Filter"
                android:textAllCaps="false"
                android:textStyle="normal" />

            <View
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:layout_below="@+id/bb"
                android:background="@color/gray" />

            <TextView
                android:id="@+id/sort_tv"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="?attr/actionBarSize"
                android:layout_gravity="center|center_horizontal"
                android:layout_weight="1"
                android:drawableLeft="@drawable/ic_baseline_sort"
                android:drawablePadding="20dp"
                android:gravity="center|fill_horizontal"
                android:paddingLeft="40dp"
                android:text="Sort"
                android:textAllCaps="false" />

        </LinearLayout>
    </android.support.v7.widget.CardView>

    <View
        android:layout_width="match_parent"
        android:layout_height="0.9dp"
        android:layout_below="@+id/my_card"
        android:background="@color/gray" />
</RelativeLayout>

###

the best way is to use ConstraintLayout, to make the textview at the center of the layout and the width warp_content(don’t use 0dp now)
so that the drawable will follow the text.

<TextView
    android:id="@+id/tv_test"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="test"
    android:drawableLeft="@drawable/you_drawable"
    android:drawablePadding="5dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    />

###

The accepted answer is not working for me, it fails if TextView width is match parent I did it using FrameLayout.

 <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="10dp"
        android:background="#000">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:drawableStart="@drawable/ic_circle_check_white"
            android:drawablePadding="10dp"
            android:text="Header"
            android:textColor="#fff"
            android:textSize="14sp"/>

    </FrameLayout>

###

simple as this.. try it..

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center|left"
                android:drawableLeft="@drawable/icon"
                android:text="something something" />

###

Try flowing:

public class DrawableCenterTextView extends AppCompatTextView {

    public DrawableCenterTextView(Context context, AttributeSet attrs,
                                  int defStyle) {
        super(context, attrs, defStyle);
    }

    public DrawableCenterTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public DrawableCenterTextView(Context context) {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // We want the icon and/or text grouped together and centered as a group.
        // We need to accommodate any existing padding
        final float buttonContentWidth = getWidth() - getPaddingLeft() - getPaddingRight();

        float textWidth = 0f;
        final Layout layout = getLayout();
        if (layout != null) {
            for (int i = 0; i < layout.getLineCount(); i++) {
                textWidth = Math.max(textWidth, layout.getLineRight(i));
            }
        }

        // Compute left drawable width, if any
        Drawable[] drawables = getCompoundDrawables();
        Drawable drawableLeft = drawables[0];

        int drawableWidth = (drawableLeft != null) ? drawableLeft.getIntrinsicWidth() : 0;

        // We only count the drawable padding if there is both an icon and text
        int drawablePadding = ((textWidth > 0) && (drawableLeft != null)) ? getCompoundDrawablePadding() : 0;

        // Adjust contents to center
        float bodyWidth = textWidth + drawableWidth + drawablePadding;
        int translate = (int) ((buttonContentWidth - bodyWidth));
        if (translate != 0)
            setPadding(translate, 0, translate, 0);
        super.onDraw(canvas);
    }
}

###

The simplest way to obtain that is:

<RelativeLayout
         android:id="@+id/linearLayout1"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:background="@drawable/head" >

         <ImageView
             android:id="@+id/cat"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginLeft="5dp"
             android:onClick="onClick"
             android:layout_marginTop="10dp"
             android:layout_alignParentLeft="true"
             android:src="@drawable/btn_back_d" />

       <TextView
            android:id="@+id/TvTitle"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text=""
            android:layout_centerHorizontal="true" 
            android:textColor="#000000" 
            android:textSize="20sp"/>

Where

  • ImageView has the alignParentLeft setted true and
  • TextView has the centerHorizontal setted true

Leave a Reply

Your email address will not be published. Required fields are marked *