NetworkImageView.java revision 54086f9c87af47015cb5de5356310598e4b7dbf5
1d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod/**
2d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod * Copyright (C) 2013 The Android Open Source Project
3d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod *
4d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod * Licensed under the Apache License, Version 2.0 (the "License");
5d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod * you may not use this file except in compliance with the License.
6d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod * You may obtain a copy of the License at
7d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod *
8d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod *      http://www.apache.org/licenses/LICENSE-2.0
9d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod *
10d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod * Unless required by applicable law or agreed to in writing, software
11d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod * distributed under the License is distributed on an "AS IS" BASIS,
12d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod * See the License for the specific language governing permissions and
14d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod * limitations under the License.
15d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod */
16d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbodpackage com.android.volley.toolbox;
17d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
18d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbodimport android.content.Context;
19d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbodimport android.text.TextUtils;
20d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbodimport android.util.AttributeSet;
21c3dce982fb05a7674d360255a9831adf83475099Vladimir Baryshnikovimport android.view.ViewGroup.LayoutParams;
22d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbodimport android.widget.ImageView;
23d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
24b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbodimport com.android.volley.VolleyError;
25d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbodimport com.android.volley.toolbox.ImageLoader.ImageContainer;
26b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbodimport com.android.volley.toolbox.ImageLoader.ImageListener;
27d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
28d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod/**
29d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod * Handles fetching an image from a URL as well as the life-cycle of the
30d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod * associated request.
31d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod */
32d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbodpublic class NetworkImageView extends ImageView {
33d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    /** The URL of the network image to load */
34d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    private String mUrl;
35d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
36d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    /**
37d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * Resource ID of the image to be used as a placeholder until the network image is loaded.
38d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     */
39d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    private int mDefaultImageId;
40d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
41d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    /**
42d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * Resource ID of the image to be used if the network response fails.
43d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     */
44d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    private int mErrorImageId;
45d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
46d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    /** Local copy of the ImageLoader. */
47d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    private ImageLoader mImageLoader;
48d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
49da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton    /** Current ImageContainer. (either in-flight or finished) */
50da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton    private ImageContainer mImageContainer;
51da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton
52d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    public NetworkImageView(Context context) {
53d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        this(context, null);
54d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    }
55d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
56d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    public NetworkImageView(Context context, AttributeSet attrs) {
57d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        this(context, attrs, 0);
58d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    }
59d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
60d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    public NetworkImageView(Context context, AttributeSet attrs, int defStyle) {
61d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        super(context, attrs, defStyle);
62d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    }
63d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
64d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    /**
65d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * Sets URL of the image that should be loaded into this view. Note that calling this will
66d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * immediately either set the cached image (if available) or the default image specified by
67d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * {@link NetworkImageView#setDefaultImageResId(int)} on the view.
68d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     *
69d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * NOTE: If applicable, {@link NetworkImageView#setDefaultImageResId(int)} and
70d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * {@link NetworkImageView#setErrorImageResId(int)} should be called prior to calling
71d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * this function.
72d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     *
73d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * @param url The URL that should be loaded into this ImageView.
74d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * @param imageLoader ImageLoader that will be used to make the request.
75d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     */
76d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    public void setImageUrl(String url, ImageLoader imageLoader) {
77d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        mUrl = url;
78d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        mImageLoader = imageLoader;
79d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        // The URL has potentially changed. See if we need to load it.
80b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod        loadImageIfNecessary(false);
81d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    }
82d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
83d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    /**
84d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * Sets the default image resource ID to be used for this view until the attempt to load it
85d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * completes.
86d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     */
87d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    public void setDefaultImageResId(int defaultImage) {
88d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        mDefaultImageId = defaultImage;
89d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    }
90d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
91d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    /**
92d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * Sets the error image resource ID to be used for this view in the event that the image
93d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * requested fails to load.
94d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     */
95d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    public void setErrorImageResId(int errorImage) {
96d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        mErrorImageId = errorImage;
97d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    }
98d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
99d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    /**
100d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     * Loads the image for the view if it isn't already loaded.
101b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod     * @param isInLayoutPass True if this was invoked from a layout pass, false otherwise.
102d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod     */
103b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod    private void loadImageIfNecessary(final boolean isInLayoutPass) {
104d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        int width = getWidth();
105d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        int height = getHeight();
106d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
107c3dce982fb05a7674d360255a9831adf83475099Vladimir Baryshnikov        boolean isFullyWrapContent = getLayoutParams() != null
108c3dce982fb05a7674d360255a9831adf83475099Vladimir Baryshnikov                && getLayoutParams().height == LayoutParams.WRAP_CONTENT
109aa6a5e69c646e8ef926a794a031ca4a9b5526a89Aurash Mahbod                && getLayoutParams().width == LayoutParams.WRAP_CONTENT;
110aa6a5e69c646e8ef926a794a031ca4a9b5526a89Aurash Mahbod        // if the view's bounds aren't known yet, and this is not a wrap-content/wrap-content
111aa6a5e69c646e8ef926a794a031ca4a9b5526a89Aurash Mahbod        // view, hold off on loading the image.
112aa6a5e69c646e8ef926a794a031ca4a9b5526a89Aurash Mahbod        if (width == 0 && height == 0 && !isFullyWrapContent) {
113d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod            return;
114d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        }
115d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
116d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        // if the URL to be loaded in this view is empty, cancel any old requests and clear the
117d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        // currently loaded image.
118d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        if (TextUtils.isEmpty(mUrl)) {
119da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton            if (mImageContainer != null) {
120da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton                mImageContainer.cancelRequest();
121da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton                mImageContainer = null;
122d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod            }
12354086f9c87af47015cb5de5356310598e4b7dbf5Adam W. Brown            setDefaultImageOrNull();
124d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod            return;
125d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        }
126d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
127d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        // if there was an old request in this view, check if it needs to be canceled.
128da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton        if (mImageContainer != null && mImageContainer.getRequestUrl() != null) {
129da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton            if (mImageContainer.getRequestUrl().equals(mUrl)) {
130d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod                // if the request is from the same URL, return.
131d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod                return;
132d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod            } else {
133d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod                // if there is a pre-existing request, cancel it if it's fetching a different URL.
134da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton                mImageContainer.cancelRequest();
13554086f9c87af47015cb5de5356310598e4b7dbf5Adam W. Brown                setDefaultImageOrNull();
136d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod            }
137d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        }
138d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
139d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        // The pre-existing content of this view didn't match the current URL. Load the new image
140d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        // from the network.
141d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        ImageContainer newContainer = mImageLoader.get(mUrl,
142b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                new ImageListener() {
143b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                    @Override
144b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                    public void onErrorResponse(VolleyError error) {
145b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                        if (mErrorImageId != 0) {
146b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                            setImageResource(mErrorImageId);
147b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                        }
148b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                    }
149b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod
150b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                    @Override
151b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                    public void onResponse(final ImageContainer response, boolean isImmediate) {
152b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                        // If this was an immediate response that was delivered inside of a layout
153b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                        // pass do not set the image immediately as it will trigger a requestLayout
154b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                        // inside of a layout. Instead, defer setting the image by posting back to
155b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                        // the main thread.
156b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                        if (isImmediate && isInLayoutPass) {
157b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                            post(new Runnable() {
158b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                                @Override
159b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                                public void run() {
160b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                                    onResponse(response, false);
161b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                                }
162b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                            });
163b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                            return;
164b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                        }
165b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod
166b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                        if (response.getBitmap() != null) {
167b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                            setImageBitmap(response.getBitmap());
168b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                        } else if (mDefaultImageId != 0) {
169b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                            setImageResource(mDefaultImageId);
170b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                        }
171b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                    }
172b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod                });
173d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
174da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton        // update the ImageContainer to be the new bitmap container.
175da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton        mImageContainer = newContainer;
176d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    }
177d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
17854086f9c87af47015cb5de5356310598e4b7dbf5Adam W. Brown    private void setDefaultImageOrNull() {
17954086f9c87af47015cb5de5356310598e4b7dbf5Adam W. Brown        if(mDefaultImageId != 0) {
18054086f9c87af47015cb5de5356310598e4b7dbf5Adam W. Brown            setImageResource(mDefaultImageId);
18154086f9c87af47015cb5de5356310598e4b7dbf5Adam W. Brown        }
18254086f9c87af47015cb5de5356310598e4b7dbf5Adam W. Brown        else {
18354086f9c87af47015cb5de5356310598e4b7dbf5Adam W. Brown            setImageBitmap(null);
18454086f9c87af47015cb5de5356310598e4b7dbf5Adam W. Brown        }
18554086f9c87af47015cb5de5356310598e4b7dbf5Adam W. Brown    }
18654086f9c87af47015cb5de5356310598e4b7dbf5Adam W. Brown
187d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    @Override
188d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
189d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        super.onLayout(changed, left, top, right, bottom);
190b25a6e0f4d3bfdeddfc10e8f5518bab5c16634fdAurash Mahbod        loadImageIfNecessary(true);
191d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    }
192d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
193d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    @Override
194d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    protected void onDetachedFromWindow() {
195da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton        if (mImageContainer != null) {
196d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod            // If the view was bound to an image request, cancel it and clear
197d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod            // out the image from the view.
198da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton            mImageContainer.cancelRequest();
199d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod            setImageBitmap(null);
200da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton            // also clear out the container so we can reload the image if necessary.
201da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8Evan Charlton            mImageContainer = null;
202d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        }
203d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        super.onDetachedFromWindow();
204d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    }
205d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod
206d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    @Override
207d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    protected void drawableStateChanged() {
208d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        super.drawableStateChanged();
209d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod        invalidate();
210d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod    }
211d62a616ebca5bfa4f9ec5517208e13f2d501b69aAurash Mahbod}
212