1 /* 2 * Copyright (C) 2018 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.systemui.charging; 18 19 import android.animation.AnimatorSet; 20 import android.animation.ObjectAnimator; 21 import android.animation.ValueAnimator; 22 import android.content.Context; 23 import android.graphics.drawable.Animatable; 24 import android.util.AttributeSet; 25 import android.util.TypedValue; 26 import android.view.ContextThemeWrapper; 27 import android.view.animation.PathInterpolator; 28 import android.widget.FrameLayout; 29 import android.widget.ImageView; 30 import android.widget.TextView; 31 32 import com.android.systemui.Interpolators; 33 import com.android.systemui.R; 34 35 import java.text.NumberFormat; 36 37 /** 38 * @hide 39 */ 40 public class WirelessChargingLayout extends FrameLayout { 41 public final static int UNKNOWN_BATTERY_LEVEL = -1; 42 WirelessChargingLayout(Context context)43 public WirelessChargingLayout(Context context) { 44 super(context); 45 init(context, null, false); 46 } 47 WirelessChargingLayout(Context context, int transmittingBatteryLevel, int batteryLevel, boolean isDozing)48 public WirelessChargingLayout(Context context, int transmittingBatteryLevel, int batteryLevel, 49 boolean isDozing) { 50 super(context); 51 init(context, null, transmittingBatteryLevel, batteryLevel, isDozing); 52 } 53 WirelessChargingLayout(Context context, AttributeSet attrs)54 public WirelessChargingLayout(Context context, AttributeSet attrs) { 55 super(context, attrs); 56 init(context, attrs, false); 57 } 58 init(Context c, AttributeSet attrs, boolean isDozing)59 private void init(Context c, AttributeSet attrs, boolean isDozing) { 60 init(c, attrs, -1, -1, false); 61 } 62 init(Context context, AttributeSet attrs, int transmittingBatteryLevel, int batteryLevel, boolean isDozing)63 private void init(Context context, AttributeSet attrs, int transmittingBatteryLevel, 64 int batteryLevel, boolean isDozing) { 65 final boolean showTransmittingBatteryLevel = 66 (transmittingBatteryLevel != UNKNOWN_BATTERY_LEVEL); 67 68 // set style based on background 69 int style = R.style.ChargingAnim_WallpaperBackground; 70 if (isDozing) { 71 style = R.style.ChargingAnim_DarkBackground; 72 } 73 74 inflate(new ContextThemeWrapper(context, style), R.layout.wireless_charging_layout, this); 75 76 // where the circle animation occurs: 77 final ImageView chargingView = findViewById(R.id.wireless_charging_view); 78 final Animatable chargingAnimation = (Animatable) chargingView.getDrawable(); 79 80 // amount of battery: 81 final TextView percentage = findViewById(R.id.wireless_charging_percentage); 82 83 if (batteryLevel != UNKNOWN_BATTERY_LEVEL) { 84 percentage.setText(NumberFormat.getPercentInstance().format(batteryLevel / 100f)); 85 percentage.setAlpha(0); 86 } 87 88 final long chargingAnimationFadeStartOffset = context.getResources().getInteger( 89 R.integer.wireless_charging_fade_offset); 90 final long chargingAnimationFadeDuration = context.getResources().getInteger( 91 R.integer.wireless_charging_fade_duration); 92 final float batteryLevelTextSizeStart = context.getResources().getFloat( 93 R.dimen.wireless_charging_anim_battery_level_text_size_start); 94 final float batteryLevelTextSizeEnd = context.getResources().getFloat( 95 R.dimen.wireless_charging_anim_battery_level_text_size_end) * ( 96 showTransmittingBatteryLevel ? 0.75f : 1.0f); 97 98 // Animation Scale: battery percentage text scales from 0% to 100% 99 ValueAnimator textSizeAnimator = ObjectAnimator.ofFloat(percentage, "textSize", 100 batteryLevelTextSizeStart, batteryLevelTextSizeEnd); 101 textSizeAnimator.setInterpolator(new PathInterpolator(0, 0, 0, 1)); 102 textSizeAnimator.setDuration(context.getResources().getInteger( 103 R.integer.wireless_charging_battery_level_text_scale_animation_duration)); 104 105 // Animation Opacity: battery percentage text transitions from 0 to 1 opacity 106 ValueAnimator textOpacityAnimator = ObjectAnimator.ofFloat(percentage, "alpha", 0, 1); 107 textOpacityAnimator.setInterpolator(Interpolators.LINEAR); 108 textOpacityAnimator.setDuration(context.getResources().getInteger( 109 R.integer.wireless_charging_battery_level_text_opacity_duration)); 110 textOpacityAnimator.setStartDelay(context.getResources().getInteger( 111 R.integer.wireless_charging_anim_opacity_offset)); 112 113 // Animation Opacity: battery percentage text fades from 1 to 0 opacity 114 ValueAnimator textFadeAnimator = ObjectAnimator.ofFloat(percentage, "alpha", 1, 0); 115 textFadeAnimator.setDuration(chargingAnimationFadeDuration); 116 textFadeAnimator.setInterpolator(Interpolators.LINEAR); 117 textFadeAnimator.setStartDelay(chargingAnimationFadeStartOffset); 118 119 // play all animations together 120 AnimatorSet animatorSet = new AnimatorSet(); 121 animatorSet.playTogether(textSizeAnimator, textOpacityAnimator, textFadeAnimator); 122 123 if (!showTransmittingBatteryLevel) { 124 chargingAnimation.start(); 125 animatorSet.start(); 126 return; 127 } 128 129 // amount of transmitting battery: 130 final TextView transmittingPercentage = findViewById( 131 R.id.reverse_wireless_charging_percentage); 132 transmittingPercentage.setVisibility(VISIBLE); 133 transmittingPercentage.setText( 134 NumberFormat.getPercentInstance().format(transmittingBatteryLevel / 100f)); 135 transmittingPercentage.setAlpha(0); 136 137 // Animation Scale: transmitting battery percentage text scales from 0% to 100% 138 ValueAnimator textSizeAnimatorTransmitting = ObjectAnimator.ofFloat(transmittingPercentage, 139 "textSize", batteryLevelTextSizeStart, batteryLevelTextSizeEnd); 140 textSizeAnimatorTransmitting.setInterpolator(new PathInterpolator(0, 0, 0, 1)); 141 textSizeAnimatorTransmitting.setDuration(context.getResources().getInteger( 142 R.integer.wireless_charging_battery_level_text_scale_animation_duration)); 143 144 // Animation Opacity: transmitting battery percentage text transitions from 0 to 1 opacity 145 ValueAnimator textOpacityAnimatorTransmitting = ObjectAnimator.ofFloat( 146 transmittingPercentage, "alpha", 0, 1); 147 textOpacityAnimatorTransmitting.setInterpolator(Interpolators.LINEAR); 148 textOpacityAnimatorTransmitting.setDuration(context.getResources().getInteger( 149 R.integer.wireless_charging_battery_level_text_opacity_duration)); 150 textOpacityAnimatorTransmitting.setStartDelay( 151 context.getResources().getInteger(R.integer.wireless_charging_anim_opacity_offset)); 152 153 // Animation Opacity: transmitting battery percentage text fades from 1 to 0 opacity 154 ValueAnimator textFadeAnimatorTransmitting = ObjectAnimator.ofFloat(transmittingPercentage, 155 "alpha", 1, 0); 156 textFadeAnimatorTransmitting.setDuration(chargingAnimationFadeDuration); 157 textFadeAnimatorTransmitting.setInterpolator(Interpolators.LINEAR); 158 textFadeAnimatorTransmitting.setStartDelay(chargingAnimationFadeStartOffset); 159 160 // play all animations together 161 AnimatorSet animatorSetTransmitting = new AnimatorSet(); 162 animatorSetTransmitting.playTogether(textSizeAnimatorTransmitting, 163 textOpacityAnimatorTransmitting, textFadeAnimatorTransmitting); 164 165 // transmitting battery icon 166 final ImageView chargingViewIcon = findViewById(R.id.reverse_wireless_charging_icon); 167 chargingViewIcon.setVisibility(VISIBLE); 168 final int padding = Math.round( 169 TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, batteryLevelTextSizeEnd, 170 getResources().getDisplayMetrics())); 171 chargingViewIcon.setPadding(padding, 0, padding, 0); 172 173 // Animation Opacity: transmitting battery icon transitions from 0 to 1 opacity 174 ValueAnimator textOpacityAnimatorIcon = ObjectAnimator.ofFloat(chargingViewIcon, "alpha", 0, 175 1); 176 textOpacityAnimatorIcon.setInterpolator(Interpolators.LINEAR); 177 textOpacityAnimatorIcon.setDuration(context.getResources().getInteger( 178 R.integer.wireless_charging_battery_level_text_opacity_duration)); 179 textOpacityAnimatorIcon.setStartDelay( 180 context.getResources().getInteger(R.integer.wireless_charging_anim_opacity_offset)); 181 182 // Animation Opacity: transmitting battery icon fades from 1 to 0 opacity 183 ValueAnimator textFadeAnimatorIcon = ObjectAnimator.ofFloat(chargingViewIcon, "alpha", 1, 184 0); 185 textFadeAnimatorIcon.setDuration(chargingAnimationFadeDuration); 186 textFadeAnimatorIcon.setInterpolator(Interpolators.LINEAR); 187 textFadeAnimatorIcon.setStartDelay(chargingAnimationFadeStartOffset); 188 189 // play all animations together 190 AnimatorSet animatorSetIcon = new AnimatorSet(); 191 animatorSetIcon.playTogether(textOpacityAnimatorIcon, textFadeAnimatorIcon); 192 193 chargingAnimation.start(); 194 animatorSet.start(); 195 animatorSetTransmitting.start(); 196 animatorSetIcon.start(); 197 } 198 } 199