me.at.coding
me.at.coding

Reputation: 17614

Understanding View.drawableStateChanged

Can anyone explain when exactly View.drawableStateChanged is called? I want to use it in conjunction with ViewGroup.setAddStatesFromChildren to make a complete ViewGroup "optically" focused, meaning e.g. change background color when e.g. an EditText of this ViewGroup gets focus.

When I implement View.drawableStateChanged it's called very often, how do I know that the current call is the one I care about? What's the advantage over settings focus listeners on the child Views?

Upvotes: 3

Views: 546

Answers (3)

Khalil Snoussi
Khalil Snoussi

Reputation: 86

to make it simple, you want your whole Viewgroup be focused when one of its children is actually focused for that you only need ViewGroup.setAddStatesFromChildren create a drawable file i call it view_focus in my code :

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="true" android:state_focused="true">
        <shape android:shape="rectangle">
            <solid android:color="@color/white"/>
            <corners android:radius="19dp"/>
            <stroke android:color="@color/green" android:width="2dp"/>
        </shape>
    </item>

    <item android:state_enabled="true" android:state_focused="false">
        <shape android:shape="rectangle">
            <solid android:color="@color/white"/>
            <corners android:radius="19dp"/>
            <stroke android:color="@color/black" android:width="2dp"/>
        </shape>
    </item>

</selector>

now in your activity layout you have to pass the above drawable as a background both in your Viewgroup and its children like the following :

    <RelativeLayout
        android:background="@drawable/view_focus"
        android:layout_centerInParent="true"
        android:id="@+id/parentlayout"
        android:layout_width="300dp"
        android:layout_height="250dp">
        <EditText
            android:padding="5dp"
            android:textSize="20sp"
            android:layout_centerInParent="true"
            android:background="@drawable/view_focus"
            android:id="@+id/edit"
            android:layout_width="200dp"
            android:layout_height="wrap_content"/>
        <EditText
            android:padding="5dp"
            android:textSize="20sp"
            android:layout_centerInParent="true"
            android:background="@drawable/view_focus"
            android:layout_below="@+id/edit"
            android:layout_marginTop="20dp"
            android:layout_width="200dp"
            android:layout_height="wrap_content"/>

    </RelativeLayout>

in this case RelativeLayout parentlayout is the Viewgroup and it's children are the two EditText if you execute this code only the children will gain Focus once clicked, if you want your whole ViewGroup gain Focus your need to add this line in your Activity Class file :

relativeLayout = findViewById(R.id.parentlayout);
relativeLayout.setAddStatesFromChildren(true);

this is the result after using the above line.

after
(source: fbcdn.net)

and this before using ViewGroup.setAddStatesFromChildren before
(source: fbcdn.net)

Upvotes: 0

Pranav P
Pranav P

Reputation: 1815

You can learn more about it here.

View.drawableStateChanged() is called whenever the state of the view changes in such a way that it impacts the state of drawables being shown.

If you create drawable like this:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"
          android:color="#ffff0000"/> 
    <item android:state_focused="true"
          android:color="#ff0000ff"/> 
    <item android:state_enabled="true"
          android:color="#ff00ffff"/> 
    <item android:color="#ff000000"/> 
</selector>

This drawable has mainly different states(like state_pressed, state_focused, state_enabled). If you have set drawable to a particular view and that view is clickable then when you click on of that view, this state generally changes.

You can use setOnFocusChangeListener to check about focus changes and setOnTouchListener touch events. Also, you can check to enable/disable the state onClick() event of that view.

Update: This method is deprecated, please follow this link for more.

Upvotes: 5

Jamil Hasnine Tamim
Jamil Hasnine Tamim

Reputation: 4448

From reading through the documentation which states:

This function is called whenever the state of the view changes in 
such a way that it impacts the state of drawables being shown.

It seems that this function will be called by the framework whenever the component needs to be redrawn and you can override it to (for example) perform so application specific logic which you need to do when the component is redrawn, like manually drawing something over the top of the component, or changing the font or doing something which is not possible using the stock attributes.

This question has an example of how you might implement it.

Upvotes: 0

Related Questions