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 17 package com.android.settingslib.graph; 18 19 import android.annotation.NonNull; 20 import android.content.Context; 21 import android.content.res.Resources; 22 import android.graphics.PorterDuff; 23 import android.graphics.PorterDuffColorFilter; 24 import android.graphics.drawable.Drawable; 25 import android.graphics.drawable.LayerDrawable; 26 import android.view.Gravity; 27 28 import androidx.annotation.VisibleForTesting; 29 30 import com.android.settingslib.R; 31 import com.android.settingslib.Utils; 32 33 /** 34 * LayerDrawable contains the bluetooth device icon and battery gauge icon 35 */ 36 public class BluetoothDeviceLayerDrawable extends LayerDrawable { 37 38 private BluetoothDeviceLayerDrawableState mState; 39 BluetoothDeviceLayerDrawable(@onNull Drawable[] layers)40 private BluetoothDeviceLayerDrawable(@NonNull Drawable[] layers) { 41 super(layers); 42 } 43 44 /** 45 * Create the {@link LayerDrawable} that contains bluetooth device icon and battery icon. 46 * This is a horizontal layout drawable while bluetooth icon at start and battery icon at end. 47 * 48 * @param context used to get the spec for icon 49 * @param resId represents the bluetooth device drawable 50 * @param batteryLevel the battery level for bluetooth device 51 */ createLayerDrawable(Context context, int resId, int batteryLevel)52 public static BluetoothDeviceLayerDrawable createLayerDrawable(Context context, int resId, 53 int batteryLevel) { 54 return createLayerDrawable(context, resId, batteryLevel, 1 /*iconScale*/); 55 } 56 57 /** 58 * Create the {@link LayerDrawable} that contains bluetooth device icon and battery icon. 59 * This is a horizontal layout drawable while bluetooth icon at start and battery icon at end. 60 * 61 * @param context used to get the spec for icon 62 * @param resId represents the bluetooth device drawable 63 * @param batteryLevel the battery level for bluetooth device 64 * @param iconScale the ratio of height between battery icon and bluetooth icon 65 */ createLayerDrawable(Context context, int resId, int batteryLevel, float iconScale)66 public static BluetoothDeviceLayerDrawable createLayerDrawable(Context context, int resId, 67 int batteryLevel, float iconScale) { 68 final Drawable deviceDrawable = context.getDrawable(resId); 69 70 final BatteryMeterDrawable batteryDrawable = new BatteryMeterDrawable(context, 71 context.getColor(R.color.meter_background_color), batteryLevel); 72 final int pad = context.getResources().getDimensionPixelSize(R.dimen.bt_battery_padding); 73 batteryDrawable.setPadding(pad, pad, pad, pad); 74 75 final BluetoothDeviceLayerDrawable drawable = new BluetoothDeviceLayerDrawable( 76 new Drawable[]{deviceDrawable, batteryDrawable}); 77 // Set the bluetooth icon at the left 78 drawable.setLayerGravity(0 /* index of deviceDrawable */, Gravity.START); 79 // Set battery icon to the right of the bluetooth icon 80 drawable.setLayerInsetStart(1 /* index of batteryDrawable */, 81 deviceDrawable.getIntrinsicWidth()); 82 drawable.setLayerInsetTop(1 /* index of batteryDrawable */, 83 (int) (deviceDrawable.getIntrinsicHeight() * (1 - iconScale))); 84 85 drawable.setConstantState(context, resId, batteryLevel, iconScale); 86 87 return drawable; 88 } 89 setConstantState(Context context, int resId, int batteryLevel, float iconScale)90 public void setConstantState(Context context, int resId, int batteryLevel, float iconScale) { 91 mState = new BluetoothDeviceLayerDrawableState(context, resId, batteryLevel, iconScale); 92 } 93 94 @Override getConstantState()95 public ConstantState getConstantState() { 96 return mState; 97 } 98 99 /** 100 * Battery gauge icon with new spec. 101 */ 102 @VisibleForTesting 103 static class BatteryMeterDrawable extends BatteryMeterDrawableBase { 104 private final float mAspectRatio; 105 @VisibleForTesting 106 int mFrameColor; 107 BatteryMeterDrawable(Context context, int frameColor, int batteryLevel)108 public BatteryMeterDrawable(Context context, int frameColor, int batteryLevel) { 109 super(context, frameColor); 110 final Resources resources = context.getResources(); 111 mButtonHeightFraction = resources.getFraction( 112 R.fraction.bt_battery_button_height_fraction, 1, 1); 113 mAspectRatio = resources.getFraction(R.fraction.bt_battery_ratio_fraction, 1, 1); 114 115 final int tintColor = Utils.getColorAttrDefaultColor(context, 116 android.R.attr.colorControlNormal); 117 setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN)); 118 setBatteryLevel(batteryLevel); 119 mFrameColor = frameColor; 120 } 121 122 @Override getAspectRatio()123 protected float getAspectRatio() { 124 return mAspectRatio; 125 } 126 127 @Override getRadiusRatio()128 protected float getRadiusRatio() { 129 // Remove the round edge 130 return 0; 131 } 132 } 133 134 /** 135 * {@link ConstantState} to restore the {@link BluetoothDeviceLayerDrawable} 136 */ 137 private static class BluetoothDeviceLayerDrawableState extends ConstantState { 138 Context context; 139 int resId; 140 int batteryLevel; 141 float iconScale; 142 BluetoothDeviceLayerDrawableState(Context context, int resId, int batteryLevel, float iconScale)143 public BluetoothDeviceLayerDrawableState(Context context, int resId, 144 int batteryLevel, float iconScale) { 145 this.context = context; 146 this.resId = resId; 147 this.batteryLevel = batteryLevel; 148 this.iconScale = iconScale; 149 } 150 151 @Override newDrawable()152 public Drawable newDrawable() { 153 return createLayerDrawable(context, resId, batteryLevel, iconScale); 154 } 155 156 @Override getChangingConfigurations()157 public int getChangingConfigurations() { 158 return 0; 159 } 160 } 161 } 162