1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package androidx.core.widget;
18
19import android.content.res.ColorStateList;
20import android.graphics.PorterDuff;
21import android.graphics.drawable.Drawable;
22import android.os.Build;
23import android.widget.ImageView;
24
25import androidx.annotation.NonNull;
26import androidx.annotation.Nullable;
27
28/**
29 * Helper for accessing features in {@link ImageView}.
30 */
31public class ImageViewCompat {
32    /**
33     * Return the tint applied to the image drawable, if specified.
34     */
35    @Nullable
36    public static ColorStateList getImageTintList(@NonNull ImageView view) {
37        if (Build.VERSION.SDK_INT >= 21) {
38            return view.getImageTintList();
39        }
40        return (view instanceof TintableImageSourceView)
41                ? ((TintableImageSourceView) view).getSupportImageTintList()
42                : null;
43    }
44
45    /**
46     * Applies a tint to the image drawable.
47     */
48    public static void setImageTintList(@NonNull ImageView view,
49            @Nullable ColorStateList tintList) {
50        if (Build.VERSION.SDK_INT >= 21) {
51            view.setImageTintList(tintList);
52
53            if (Build.VERSION.SDK_INT == 21) {
54                // Work around a bug in L that did not update the state of the image source
55                // after applying the tint
56                Drawable imageViewDrawable = view.getDrawable();
57                boolean hasTint = (view.getImageTintList() != null)
58                        && (view.getImageTintMode() != null);
59                if ((imageViewDrawable != null) && hasTint) {
60                    if (imageViewDrawable.isStateful()) {
61                        imageViewDrawable.setState(view.getDrawableState());
62                    }
63                    view.setImageDrawable(imageViewDrawable);
64                }
65            }
66        } else if (view instanceof TintableImageSourceView) {
67            ((TintableImageSourceView) view).setSupportImageTintList(tintList);
68        }
69    }
70
71    /**
72     * Return the blending mode used to apply the tint to the image drawable, if specified.
73     */
74    @Nullable
75    public static PorterDuff.Mode getImageTintMode(@NonNull ImageView view) {
76        if (Build.VERSION.SDK_INT >= 21) {
77            return view.getImageTintMode();
78        }
79        return (view instanceof TintableImageSourceView)
80                ? ((TintableImageSourceView) view).getSupportImageTintMode()
81                : null;
82    }
83
84    /**
85     * Specifies the blending mode used to apply the tint specified by
86     * {@link #setImageTintList(android.widget.ImageView, android.content.res.ColorStateList)}
87     * to the image drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
88     */
89    public static void setImageTintMode(@NonNull ImageView view, @Nullable PorterDuff.Mode mode) {
90        if (Build.VERSION.SDK_INT >= 21) {
91            view.setImageTintMode(mode);
92
93            if (Build.VERSION.SDK_INT == 21) {
94                // Work around a bug in L that did not update the state of the image source
95                // after applying the tint
96                Drawable imageViewDrawable = view.getDrawable();
97                boolean hasTint = (view.getImageTintList() != null)
98                        && (view.getImageTintMode() != null);
99                if ((imageViewDrawable != null) && hasTint) {
100                    if (imageViewDrawable.isStateful()) {
101                        imageViewDrawable.setState(view.getDrawableState());
102                    }
103                    view.setImageDrawable(imageViewDrawable);
104                }
105            }
106        } else if (view instanceof TintableImageSourceView) {
107            ((TintableImageSourceView) view).setSupportImageTintMode(mode);
108        }
109    }
110
111    private ImageViewCompat() {}
112}
113