1/* 2 * Copyright 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.slice.widget; 18 19import android.content.Context; 20import android.content.res.ColorStateList; 21import android.content.res.TypedArray; 22import android.graphics.Bitmap; 23import android.graphics.Bitmap.Config; 24import android.graphics.Canvas; 25import android.graphics.Color; 26import android.graphics.Paint; 27import android.graphics.PorterDuff.Mode; 28import android.graphics.PorterDuffXfermode; 29import android.graphics.Rect; 30import android.graphics.drawable.BitmapDrawable; 31import android.graphics.drawable.Drawable; 32import android.text.format.DateUtils; 33import android.view.Gravity; 34import android.view.ViewGroup; 35import android.widget.FrameLayout; 36import android.widget.ImageView; 37 38import androidx.annotation.AttrRes; 39import androidx.annotation.ColorInt; 40import androidx.annotation.NonNull; 41import androidx.annotation.RestrictTo; 42import androidx.core.content.ContextCompat; 43import androidx.core.graphics.drawable.IconCompat; 44 45import java.util.Calendar; 46 47/** 48 * A bunch of utilities for slice UI. 49 * 50 * @hide 51 */ 52@RestrictTo(RestrictTo.Scope.LIBRARY) 53public class SliceViewUtil { 54 55 /** 56 */ 57 @ColorInt 58 public static int getColorAccent(@NonNull Context context) { 59 return getColorAttr(context, android.R.attr.colorAccent); 60 } 61 62 /** 63 */ 64 @ColorInt 65 public static int getColorError(@NonNull Context context) { 66 return getColorAttr(context, android.R.attr.colorError); 67 } 68 69 /** 70 */ 71 @ColorInt 72 public static int getDefaultColor(@NonNull Context context, int resId) { 73 final ColorStateList list = ContextCompat.getColorStateList(context, resId); 74 return list.getDefaultColor(); 75 } 76 77 /** 78 */ 79 @ColorInt 80 public static int getDisabled(@NonNull Context context, int inputColor) { 81 return applyAlphaAttr(context, android.R.attr.disabledAlpha, inputColor); 82 } 83 84 /** 85 */ 86 @ColorInt 87 public static int applyAlphaAttr(@NonNull Context context, @AttrRes int attr, int inputColor) { 88 TypedArray ta = context.obtainStyledAttributes(new int[] { 89 attr 90 }); 91 float alpha = ta.getFloat(0, 0); 92 ta.recycle(); 93 return applyAlpha(alpha, inputColor); 94 } 95 96 /** 97 */ 98 @ColorInt 99 public static int applyAlpha(float alpha, int inputColor) { 100 alpha *= Color.alpha(inputColor); 101 return Color.argb((int) (alpha), Color.red(inputColor), Color.green(inputColor), 102 Color.blue(inputColor)); 103 } 104 105 /** 106 */ 107 @ColorInt 108 public static int getColorAttr(@NonNull Context context, @AttrRes int attr) { 109 TypedArray ta = context.obtainStyledAttributes(new int[] { 110 attr 111 }); 112 @ColorInt int colorAccent = ta.getColor(0, 0); 113 ta.recycle(); 114 return colorAccent; 115 } 116 117 /** 118 */ 119 public static int getThemeAttr(@NonNull Context context, @AttrRes int attr) { 120 TypedArray ta = context.obtainStyledAttributes(new int[] { 121 attr 122 }); 123 int theme = ta.getResourceId(0, 0); 124 ta.recycle(); 125 return theme; 126 } 127 128 /** 129 */ 130 public static Drawable getDrawable(@NonNull Context context, @AttrRes int attr) { 131 TypedArray ta = context.obtainStyledAttributes(new int[] { 132 attr 133 }); 134 Drawable drawable = ta.getDrawable(0); 135 ta.recycle(); 136 return drawable; 137 } 138 139 /** 140 */ 141 public static IconCompat createIconFromDrawable(Drawable d) { 142 if (d instanceof BitmapDrawable) { 143 return IconCompat.createWithBitmap(((BitmapDrawable) d).getBitmap()); 144 } 145 Bitmap b = Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(), 146 Bitmap.Config.ARGB_8888); 147 Canvas canvas = new Canvas(b); 148 d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 149 d.draw(canvas); 150 return IconCompat.createWithBitmap(b); 151 } 152 153 /** 154 */ 155 public static void createCircledIcon(@NonNull Context context, int iconSizePx, 156 IconCompat icon, boolean isLarge, ViewGroup parent) { 157 ImageView v = new ImageView(context); 158 v.setImageDrawable(icon.loadDrawable(context)); 159 v.setScaleType(isLarge ? ImageView.ScaleType.CENTER_CROP 160 : ImageView.ScaleType.CENTER_INSIDE); 161 parent.addView(v); 162 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams(); 163 if (isLarge) { 164 // XXX better way to convert from icon -> bitmap or crop an icon (?) 165 Bitmap iconBm = Bitmap.createBitmap(iconSizePx, iconSizePx, Config.ARGB_8888); 166 Canvas iconCanvas = new Canvas(iconBm); 167 v.layout(0, 0, iconSizePx, iconSizePx); 168 v.draw(iconCanvas); 169 v.setImageBitmap(getCircularBitmap(iconBm)); 170 } else { 171 v.setColorFilter(Color.WHITE); 172 } 173 lp.width = iconSizePx; 174 lp.height = iconSizePx; 175 lp.gravity = Gravity.CENTER; 176 } 177 178 /** 179 */ 180 public static @NonNull Bitmap getCircularBitmap(Bitmap bitmap) { 181 Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), 182 bitmap.getHeight(), Config.ARGB_8888); 183 Canvas canvas = new Canvas(output); 184 final Paint paint = new Paint(); 185 final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); 186 paint.setAntiAlias(true); 187 canvas.drawARGB(0, 0, 0, 0); 188 canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, 189 bitmap.getWidth() / 2, paint); 190 paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 191 canvas.drawBitmap(bitmap, rect, rect, paint); 192 return output; 193 } 194 195 /** 196 */ 197 public static CharSequence getRelativeTimeString(long time) { 198 return DateUtils.getRelativeTimeSpanString(time, Calendar.getInstance().getTimeInMillis(), 199 DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE); 200 } 201 202 private SliceViewUtil() { 203 } 204} 205