91

I have applied a shape for a button like:

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle" >
    <gradient android:startColor="#DD000000" android:endColor="#DD2d2d2d"  android:angle="90"></gradient>
    <corners android:radius="15dip"></corners>

</shape>

Now I want to use a selector like:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/active"
      android:state_pressed="true" />
<item android:drawable="@drawable/passive"/>

for this Button as well. Is it possible ...???

Angad Singh
  • 1,032
  • 1
  • 17
  • 36
Khawar Raza
  • 15,870
  • 24
  • 70
  • 127

9 Answers9

197

use this way:

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

   <item android:state_pressed="true" >
       <shape>.......</shape>
   </item>
   ..........
   ..........
</selector>
shobhan
  • 1,460
  • 2
  • 14
  • 28
Hanry
  • 5,481
  • 2
  • 40
  • 53
  • 8
    Yes, it worked by using: – Khawar Raza Sep 30 '11 at 09:02
  • 7
    @KhawarRaza In the future, please put information like that in your _question_, where it can be formatted and found more easily. Comments tend to vanish over time. – Tim Post Jun 30 '12 at 07:29
  • I tried adding a shape element inside the item element as you have suggested but it just errors out with a message that doesn't help much `09-13 15:25:02.868: ERROR/AndroidRuntime(9129): FATAL EXCEPTION: main android.view.InflateException: Binary XML file line #13: Error inflating class .` I am setting the selector as the `android:background` attribute of a `RoundedImageView` [ https://github.com/vinc3m1/RoundedImageView#usage]. Does anyone have any ideas of how to do this? – Etienne Lawlor Sep 13 '13 at 22:30
  • When attempting to use this technique, I kept getting an error message. AZ_'s answer worked better for me. – Alan Nelson Mar 25 '20 at 16:42
  • @Alan Nelson, my answer is just skeleton, while AZ_ has given the example. – Hanry Mar 27 '20 at 03:50
25

Detailed to the point answer

Create a color resource in

res/values/colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>


    <item name="yellow" type="color">#F7B500</item>
    <item name="yellow_dark" type="color">#AC7E00</item>

    <integer-array name="androidcolors">
        <item>@color/yellow</item>
        <item>@color/yellow_dark</item>
    </integer-array>

</resources>

Create a drawable at

res/drawable/bg_yellow_round.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <solid android:color="@color/yellow" />

    <stroke
        android:width="2dp"
        android:color="@color/yellow" />

    <corners
        android:bottomLeftRadius="20dp"
        android:bottomRightRadius="20dp"
        android:topLeftRadius="20dp"
        android:topRightRadius="20dp" />

</shape>

Create another drawable, you want for transition at same place and name it

res/drawable/bg_yellow_dark_round.xml

<solid android:color="@color/yellow_dark" />

<stroke
    android:width="2dp"
    android:color="@color/yellow_dark" />

<corners
    android:bottomLeftRadius="20dp"
    android:bottomRightRadius="20dp"
    android:topLeftRadius="20dp"
    android:topRightRadius="20dp" />

Now create a color state list at

res/color/btn_selector_yellow.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_shortAnimTime">

    <item android:drawable="@color/yellow" android:state_focused="true" android:state_pressed="false"/>
    <item android:drawable="@drawable/bg_yellow_dark_round" android:state_pressed="true"/>
    <item android:drawable="@drawable/bg_yellow_round"/>

</selector>

Now set it to your button as following

<Button
                android:id="@+id/button1"
                android:layout_width="248dp"
                android:layout_height="44dp"
                android:layout_gravity="center_horizontal"
                android:layout_marginBottom="10dp"
                android:layout_marginTop="20dp"
                android:background="@color/btn_selector_yellow"
                android:text="AZ_ is so cool" />

Now this will do transition from light yellow

to

dark yellow.

AZ_
  • 21,688
  • 25
  • 143
  • 191
  • This works, can you also guide to implement it for ripple effect? – hardik9850 Jun 27 '17 at 10:40
  • https://developer.android.com/reference/android/graphics/drawable/RippleDrawable.html – AZ_ Jun 30 '17 at 10:19
  • or just see this there are many https://www.google.com/search?q=android+ripple+effect&rlz=1C1GGRV_enDE749DE749&oq=android+ripple+effect&aqs=chrome..69i57j0l5.3479j0j7&sourceid=chrome&ie=UTF-8 – AZ_ Jun 30 '17 at 10:21
13

shape.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/star_off"/>
    <corners android:radius="5dp"/>
    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>

selector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime">

    <item android:drawable="@color/tab_focused" android:state_focused="true" android:state_pressed="false"/>
    <item android:drawable="@color/tab_pressed" android:state_pressed="true"/>
    <item android:drawable="@drawable/shape"/>

</selector>
Renan Bandeira
  • 3,238
  • 17
  • 27
7

You can also create a shape that is using a selector inside. If your shape is just changing its color in different states, this is a lot cleaner.

color/color_selector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/blue_dark" android:state_pressed="true" />
    <item android:color="@color/blue_light" />
</selector>

drawable/shape.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/color_selector" />
    <corners android:bottomLeftRadius="6dip" android:bottomRightRadius="6dp" />
    <padding android:bottom="0dip" android:left="0dip" android:right="0dip" android:top="0dip" />
</shape>
Till - Appviewer.io
  • 4,529
  • 1
  • 31
  • 35
  • This does not work for me, the selector in color is never used... Although I agree it is a lot cleaner – Gyome Sep 20 '15 at 19:25
  • @Gyome it is working. See this link http://stackoverflow.com/questions/1219312/android-selector-text-color – Ji Fang Apr 27 '16 at 22:20
  • 3
    I know this is old, but just for the record, this method only works in Android 5.0 and higher. – lionscribe Feb 15 '17 at 05:38
4

Well I know it's way too late But here is a solved example

 <TextView
            android:id="@+id/txt_out_going_calls"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="04dp"
            android:layout_weight="1"
            android:background="@drawable/header_text_view_selector"
            android:gravity="center"
            android:text="@string/outgoing_calls_tab_button_text"
            android:textColor="@color/home_text_color" />

and my header_text_view_selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true">

        <shape xmlns:android="http://schemas.android.com/apk/res/android">
            <solid android:color="@color/home_fragment_tab_color_selected"/>
            <corners android:radius="25dip" />
            <padding android:bottom="08dip" android:left="9dip" android:right="9dip" android:top="08dip" />
        </shape>
    </item>
    <item android:state_selected="false">

        <shape>
            <solid android:color="@color/home_fragment_tab_color_simple"/>
            <corners android:radius="25dip" />
            <padding android:bottom="08dip" android:left="9dip" android:right="9dip" android:top="08dip" />
        </shape>
    </item>
</selector>

So basically i m creating a rounded textview with selector. Here i m handling only state_selected and not_selected. Hope it helps

Nouman Ghaffar
  • 3,780
  • 1
  • 29
  • 37
3

This is my way, and it works!

<item android:state_pressed="true">

    <shape android:shape="oval">


        <gradient android:centerX=".6"
            android:centerY=".40"
            android:endColor="@color/colorPrimary"
            android:gradientRadius="20"
            android:startColor="@color/colorPrimary"
            android:type="radial" />

        <stroke android:width="1dp"
            android:color="#FFFFFF" />

        <size android:width="55dp"
            android:height="55dp" />

    </shape>
</item>

<item android:state_focused="false">
    <shape android:shape="oval">


        <gradient android:centerX=".6"
            android:centerY=".40"
            android:endColor="@android:color/transparent"
            android:gradientRadius="20"
            android:startColor="@android:color/transparent"
            android:type="radial" />

        <stroke android:width="1dp"
            android:color="#FFFFFF" />

        <size android:width="55dp"
            android:height="55dp" />

    </shape>
</item>

Aniket-Shinde
  • 213
  • 3
  • 9
2

My example is a circle button with state_pressed. code bellow:

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


    <item android:state_pressed="true">
        <shape android:shape="oval">
            <solid android:color="@color/light_primary_color" />
        </shape>

    </item>
    <item>
        <shape android:shape="oval">
            <solid android:color="@color/accent_color" />
        </shape>
    </item>

</selector>
vrbsm
  • 1,188
  • 15
  • 22
0

Use your shape name as you use any image and use it selector as you use image. Try out you will not face any problem. Is that what you were asking?

Vineet Shukla
  • 23,865
  • 10
  • 55
  • 63
-1

To be more reusable, you can set states on single properties. Avoid duplicating your shapes

<selector
    xmlns:android="http://schemas.android.com/apk/res/android"
>
    <item>
        <shape android:shape="rectangle" >
            <corners android:radius="5dp"/>
            <solid
                android:state_enabled="false"
                android:color="@color/transparent"
            />
            <solid
                android:state_enabled="true"
                android:color="@color/background"
            />
            <stroke
                android:width="@dimen/dividerHeight"
                android:color="@color/dividerLight"
            />
        </shape>
    </item>
</selector>

I was able to set background programmatically once disabled using this method.

Gibolt
  • 42,564
  • 15
  • 187
  • 127
  • This doesn't seem to work. I think the selector has to have multiple item children and the state has to be set on each item. – bmaupin Oct 17 '20 at 20:48