Jacob
Jacob

Reputation: 3801

Keep text in TextView with drawableLeft centered

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)?

Upvotes: 65

Views: 76973

Answers (23)

All Іѕ Vаиітy
All Іѕ Vаиітy

Reputation: 26442

Add this to your textview instead of wrapping with another layout

android:gravity="center|start"

Upvotes: 0

abhi
abhi

Reputation: 1136

Wrap your TextView inside a LinearLayout. Then set android:gravity="center_horizontal" to your LinearLayout..

<LinearLayout
        android:layout_width="0dp"
        android:gravity="center_horizontal"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableStart="@drawable/your_drawable"
            android:drawablePadding="5dp"
            android:ellipsize="end"
            android:maxLines="1"
            android:textAlignment="center"
            android:textColor="@color/ic_text_color"
            android:textSize="15sp"
            tools:text="Your Text.." />

    </LinearLayout>

Upvotes: 1

mixer
mixer

Reputation: 1829

no test too much, another way

    class CenterDrawableToggleButton @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
    ) : AppCompatToggleButton(context, attrs, defStyleAttr) {

        private val centerMatrix = Matrix()

        override fun onDraw(canvas: Canvas?) {
            canvas?.save()?:return
            centerMatrix.reset()
            centerMatrix.postTranslate(width / 2F - (getDrawWidth() / 2), 0F)
            canvas.concat(centerMatrix)
            super.onDraw(canvas)
            canvas.restore()
        }

        private fun getDrawWidth(): Float {
            return paint.measureText(text.toString()) + compoundPaddingRight + compoundPaddingLeft
        }
    }

Upvotes: 1

yifei chen
yifei chen

Reputation: 111

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);
    }
}

Upvotes: 4

Ajay Chauhan
Ajay Chauhan

Reputation: 1551

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>

Upvotes: 1

sumang_87
sumang_87

Reputation: 19

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"
    />

Upvotes: -1

Suresh Maidaragi
Suresh Maidaragi

Reputation: 2308

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>

Upvotes: 1

EpicPandaForce
EpicPandaForce

Reputation: 81549

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>

Upvotes: -2

vikas singh
vikas singh

Reputation: 61

> 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>

Upvotes: 2

Harshil
Harshil

Reputation: 1010

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" />

Upvotes: 5

Furedal
Furedal

Reputation: 533

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"/>

Upvotes: 1

Harshil
Harshil

Reputation: 1010

<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" />

Upvotes: 0

amukhachov
amukhachov

Reputation: 5900

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"
    />

Upvotes: 6

Rohan Taneja
Rohan Taneja

Reputation: 10707

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.

Upvotes: 15

Quentin Colle
Quentin Colle

Reputation: 246

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" />

Upvotes: 5

abcfrom0
abcfrom0

Reputation: 31

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.

Upvotes: 1

Hafiz Waleed Hussain
Hafiz Waleed Hussain

Reputation: 1072

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>

Upvotes: 4

Mr.Lights
Mr.Lights

Reputation: 29

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" />

Upvotes: -1

Deepak Ganachari
Deepak Ganachari

Reputation: 406

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"
    />

Upvotes: 1

blahdiblah
blahdiblah

Reputation: 34011

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.

Upvotes: 32

Stefano Ortisi
Stefano Ortisi

Reputation: 5326

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

Upvotes: -18

Khan
Khan

Reputation: 7605

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

Upvotes: 3

Aamirkhan
Aamirkhan

Reputation: 5784

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

Upvotes: 0

Related Questions