Android - Setting Pressed State and Border on a TextView - Only one Background

6.2k views Asked by At

I have 3 TextViews stacked vertically in a LinearLayout

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:textSize="@dimen/text_size_large"
        android:text="Item1"/>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:textSize="@dimen/text_size_large"
        android:text="Item2"/>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:textSize="@dimen/text_size_large"
        android:text="Item3"/>
</LinearLayout>

I could apply a drawable to the background attribute to render a Border

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:top="-2dp" android:right="-2dp" android:left="-2dp">
        <shape>
            <solid android:color="@android:color/transparent" />
            <stroke android:width="1dp" android:color="@color/pale_grey" />
            <padding android:left="24dp" android:right="24dp" 
                       android:top="12dp" android:bottom="12dp" />
        </shape>
    </item>
</layer-list>

I could also apply a selector, via a drawable, to the background property so that the TextView changed color depending on states such as Pressed. However there is only one background attribute.

I do not believe i can apply the <shape> xml and the <selector> xml within the same drawable. Therefore do I need to wrap a single layout element around each TextView just so can apply another background?

It looks like google solves this by encompassing border, padding and background colour into one drawable patch-9 image. I was hoping I didn't need to do that

Thanks

2

There are 2 answers

4
Sherif El Nady On BEST ANSWER

In the selector set the state pressed and unpressed with your XML's that render the border

Example:

<selector     xlmns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@drawable/border_unpressed" android:state_pressed="false"/> 
 <item android:drawable="@drawable/border_pressed" android:state_pressed="true"/>
 <item android:drawable="@drawable/border_unpressed" />

</selector>

Note: Make sure to set the TextView attribute android:clickable="true"

0
Bhargav Jethva On
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <shape
                xmlns:android="http://schemas.android.com/apk/res/android"
                android:shape="rectangle" >
            <corners
                android:radius="4dp">
            </corners>
            <stroke android:width="1dp" android:color="#ffffff"/>
            <gradient
                android:startColor="#187cb6"
                android:endColor="#187cb6"
                android:angle="270"/>
        </shape>
    </item>
    <item>
        <selector xmlns:android="http://schemas.android.com/apk/res/android">
            <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/gradient" />
            <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/gradient" />
        </selector>
    </item>
</layer-list>