Android background + text + icon for a button

I would like to have an image set to background a text on it and an icon on the left side of the text.
Very easy in iPhone, but can’t figure out how to do it at Android, to be resizable that button and keep the icon + text position and distance properly.

iPhone:

  • The connection to adb is down, and a severe error has occurred
  • Android: How to/Tutorial for changing ActionBar to ActionBarCompat (Toolbar)?
  • Retrofit2 Android: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
  • Android and setting width and height programmatically in dp units
  • How to disable dates before today date in DatePickerDialog Android?
  • libgdx ClassNotFoundException when starting Desktop main - Mac, IntelliJ
  • iPhone

    Android I have this:

    Android

    The xml code is:

    <Button
        android:id="@+id/btSettings"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/tvWhatever"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="20dp"
        android:background="@drawable/bt_general"
        android:drawableTop="@drawable/settings_selected"
        android:text="@string/settings"
        android:textColor="#000000" />
    

    Took the code from here.

    If I use android:drawableLeft , than the icon will go to most left part.

    enter image description here

    If I start playing with semi hardcoded paddings, than I will have different look at diff devives: ( phone and table)

    If I add the android:gravity="left|center_vertical" than it will look like this:

    enter image description here

    The text is variable: it will change, when the user change the language.

    How to do it properly?

    I don’t want to downvote anybody’s answer, but please read the question and don’t suggest what I have tryed already. Also told the hardcoded fixes doesn’t work well.

    This is not a homework, but a commercial software part.

    Here is a suggested code from answers:

    <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/bt_general"
            android:padding="20dip" >
    
            <ImageView
                android:id="@+id/xIcon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_centerVertical="true"
                android:layout_marginLeft="10dip"
                android:src="@drawable/settings_selected" />
    
            <TextView
                android:id="@+id/xSettingsTxt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="@string/settings"
                android:textColor="#000000" />
        </RelativeLayout>
    

    What do you think how it will look like the android:layout_marginLeft="10dip" on Galaxy s4? Here is a preview:

    enter image description here

    This is not, what I have asked. “dip” or “dp” or “px” shouldn’t be used anywhere as distance from left, top, because phones has HPDI, smaller screen and Tablets has MDPI and wide resolutions. Simple doesn’t work on mdpi, and xxhdpi.

    Nizam answer is very close to a good solution:

    enter image description here

    Related posts:

    how to create a new AVD in eclipse?
    android.R.id.content as container for Fragment
    Java: Need some way to shorten this code
    Eclipse Android Emulator - Keyboard not working
    The import com.google cannot be resolved?
    Is there a way to connect to a Bluetooth Low Energy device under Android 5 exposing the public stati...
  • how to save images displayed in webview?
  • Android - Detect End of Long Press
  • Radial gradient in XML with parent size
  • What is the size, in pixels, of AdSize.BANNER?
  • FileObserver getting strange events
  • Android - Uploading new APK with updated permissions to a published app
  • 14 Solutions collect form web for “Android background + text + icon for a button”

    Maybe you should use RelativeLayout with rounded corners, than put TextView and ImageView inside of it.

    Try this:

        Button button = (Button) findViewById(R.id.button1);
        Spannable buttonLabel = new SpannableString(" Settings");
        buttonLabel.setSpan(new ImageSpan(getApplicationContext(), R.drawable.settings_selected,      
            ImageSpan.ALIGN_BOTTOM), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        button.setText(buttonLabel);
    

    Try this:
    Follow this : http://porcupineprogrammer.blogspot.in/2013/03/android-ui-struggles-making-button-with.html

    <FrameLayout
        style="?android:attr/buttonStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:drawableLeft="@android:drawable/ic_delete"
            android:gravity="center"
            android:text="Button Challenge" />
    </FrameLayout>
    

    Here is how i do things :

    LAYERS

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    
        <item android:drawable="@drawable/rounded_border"/>
        <item android:drawable="@drawable/selector_button"/>
    
    </layer-list>
    

    SELECTOR

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item android:drawable="@color/clr_grey_1" android:state_selected="true" android:state_window_focused="false"/>
        <item android:drawable="@color/clr_grey_1" android:state_selected="true"/>
        <item android:drawable="@color/clr_grey_1" android:state_pressed="true" android:state_selected="false"/>
        <item android:drawable="@color/clr_main_green" android:state_selected="false"/>
    
    </selector>
    

    ROUNDED CORNER

    <?xml version="1.0" encoding="UTF-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android" >
    
        <solid android:color="@color/clr_grey_2" />
    
        <stroke
            android:width="1dp"
            android:color="@android:color/white" />
    
        <corners
            android:bottomLeftRadius="8dp"
            android:bottomRightRadius="8dp"
            android:topLeftRadius="8dp"
            android:topRightRadius="8dp" />
    
        <padding
            android:bottom="0dp"
            android:left="4dp"
            android:right="0dp"
            android:top="4dp" />
    
    </shape>
    

    Use this on relative layout, with an imageview and button inside it

    Try below layout

    <?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="100dip"
    android:orientation="horizontal"
    android:background="@drawable/round_corners_drawable" >
    
    <ImageView 
        android:id="@+id/xIcon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="10dip"
        android:layout_centerVertical="true"
        android:src="@drawable/ic_launcher"/>
    
    <TextView
        android:id="@+id/xSettingsTxt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Settings"
        android:layout_centerInParent="true" />
    
    </RelativeLayout>
    

    and drawable/round_corner_drawable is as below:

    <?xml version="1.0" encoding="utf-8"?>
    
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
    
    <solid android:color="#310704"/>
    
    <corners
        android:bottomRightRadius="20sp"
        android:bottomLeftRadius="20sp"
        android:topLeftRadius="20sp"
        android:topRightRadius="20sp"/>
    
    <gradient
        android:startColor="#99310704"
        android:centerColor="#99310704"
        android:endColor="#99310704"
        android:angle="270" />
    
    </shape>
    

    Also, if you want to use your image as a background, give android:layout_height="wrap_content" and set it as a background for relative layout.

    p.s. If you put different color values for startColor, centerColor and endColor, you will get that gradient effect for your background drawable. So change the color values accordingly.

    EDIT:

    Try below layout, i edited it to fit in different screen sizes with rounded corner drawable.

    <?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="wrap_content"
    android:padding="20dip"
    android:background="@drawable/dialog_round_corners" >
    
    <ImageView 
        android:id="@+id/xIcon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@+id/xSettingsTxt"
        android:layout_centerVertical="true"
        android:src="@drawable/ic_launcher"/>
    
    <TextView
        android:id="@+id/xSettingsTxt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Settings"
        android:layout_centerInParent="true" />
    
    </RelativeLayout>
    
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button Text"
        android:background="@drawable/round_background"
        android:drawableLeft="@drawable/icon"/>
    

    save the xml code below as round_background.xml and put it on drawable folder. use this if you want, but you can also use image from the drawable folder.

    <?xml version="1.0" encoding="UTF-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android" >
    
        <solid android:color="#f5f5f5" />
    
        <corners android:radius="10px" />
    
        <padding
            android:bottom="0dp"
            android:left="0dp"
            android:right="0dp"
            android:top="0dp" />
    
        <stroke
            android:width="1dp"
            android:color="#ccc" />
    
    </shape>
    

    I had achieved that with following code. May be used as an easier alternative to above solutions.

    <Button android:id="@+id/btnUserProfile"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:drawableLeft="@drawable/ic_user_profile"
        android:background="#6C6C6C"
        android:drawablePadding="8dp"
        android:gravity="left|center_vertical"          
        android:text="@string/my_profile"
        android:textStyle="bold|italic" />   
    

    the button view is marked in red(this is not a list item but a button with above code):

    enter image description here

    Found a class called CenteredIconButton that extends Button at this link. Worked like magic. How to have Image and Text Center within a Button . Thanks to @atomicode

    If your button width: android:layout_width="wrap_content" then your code will be like this:

     <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableLeft="@drawable/img name"
            android:gravity="left|center"
            android:text="Button" />
    

    Else if your button width: android:layout_width="match_parent" then your code will be like this:

    <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:drawableLeft="@drawable/img name"
            android:gravity="left|center"
            android:text="Button"
            android:paddingLeft="100dp" 
            />
    

    By the way android:paddingLeft="100dp", change 100 with your suitable value.

    <Button
        android:id="@+id/btSettings"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/back_button"
        android:drawablePadding="5dp"
        android:drawableLeft="@drawable/ic_launcher"
        android:text="Settings"
        android:padding="20dp"
        android:textColor="#000000" />
    

    You can use paddingLeft and paddingRight to get button as the one in iphone

    Try to use TextView,

    <TextView
        android:id="@+id/txtSettings"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/tvWhatever"
        android:layout_centerHorizontal="true"
        android:text="@string/settings"
        android:textColor="#000000" />
    

    In Java

    txtView.setBackgroundResources(R.drawable.bt_general);
    txtView.setCompoundDrawablesWithIntrinsicBounds(Drawable left,Drawable top,Drawable right,Drawable bottom);
    

    where Drawable image is,

    Bitmap bitmap= BitmapFactory.decodeResource(context.getResources(), 
        R.drawable.settings_selected);
    BitmapDrawable drawable=new BitmapDrawable(getResources(), bitmap);
    

    I just implemented this kind of button (and it has been deployed in a large scale app), it is not really complicated :
    content of large_button.xml :

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/large_button_background"
        android:clickable="true"
        android:gravity="center_horizontal"
        android:orientation="horizontal" >
    
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="center_vertical"
            android:layout_marginRight="16dp"
            android:src="@drawable/some_icon" />
    
        <com.my.app.widget.RobotoTextView
            android:id="@+id/large_button_text"
            style="@style/AppName_RobotoBold"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:ellipsize="end"
            android:focusable="false"
            android:gravity="center_vertical"
            android:maxLines="1"
            android:singleLine="true"
            android:textColor="@color/text_main"
            />
    
    </LinearLayout>
    

    Then, to use it I just have to use the include tag :

    <include
        android:id="@+id/large_button"
        android:layout_width="match_parent"
        android:layout_height="@dimen/large_button_height"
        android:layout_marginBottom="@dimen/large_button_vertical_margin"
        android:layout_marginLeft="@dimen/large_button_horizontal_margin"
        android:layout_marginRight="@dimen/large_button_horizontal_margin"
        android:layout_marginTop="@dimen/large_button_vertical_margin"
        layout="@layout/large_button" />
    

    large_button_background is a selector that points to the different drawables to use for each button state

    I used a LinearLayout, it allows to simply center both text & icons in the button. It should also be doable with a GridLayout. If you want to center just on the text (I don’t think it looks great though but that’s your choice), use a RelativeLayout.

    You can use android:paddingLeft, android:paddingRight and layout_width at a fixed width to solve the issue.

    <Button
    android:id="@+id/btSettings"
    android:layout_width="148dp"
    android:layout_height="wrap_content"
    android:paddingLeft="32dp"
    android:paddingRight="32dp"
    android:background="@drawable/bt_general"
    android:drawableLeft="@drawable/settings_selected"
    android:text="@string/settings"
    android:textColor="#000000"/>  
    
    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.