| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.systemui.charging; |
| |
| import android.animation.AnimatorSet; |
| import android.animation.ObjectAnimator; |
| import android.animation.ValueAnimator; |
| import android.content.Context; |
| import android.graphics.Color; |
| import android.graphics.PointF; |
| import android.util.AttributeSet; |
| import android.util.TypedValue; |
| import android.view.ContextThemeWrapper; |
| import android.view.View; |
| import android.view.animation.PathInterpolator; |
| import android.widget.FrameLayout; |
| import android.widget.ImageView; |
| import android.widget.TextView; |
| |
| import com.android.settingslib.Utils; |
| import com.android.systemui.R; |
| import com.android.systemui.animation.Interpolators; |
| import com.android.systemui.statusbar.charging.ChargingRippleView; |
| |
| import java.text.NumberFormat; |
| |
| /** |
| * @hide |
| */ |
| public class WirelessChargingLayout extends FrameLayout { |
| public static final int UNKNOWN_BATTERY_LEVEL = -1; |
| private static final long RIPPLE_ANIMATION_DURATION = 1500; |
| private static final int SCRIM_COLOR = 0x4C000000; |
| private static final int SCRIM_FADE_DURATION = 300; |
| private ChargingRippleView mRippleView; |
| |
| public WirelessChargingLayout(Context context) { |
| super(context); |
| init(context, null, false); |
| } |
| |
| public WirelessChargingLayout(Context context, int transmittingBatteryLevel, int batteryLevel, |
| boolean isDozing) { |
| super(context); |
| init(context, null, transmittingBatteryLevel, batteryLevel, isDozing); |
| } |
| |
| public WirelessChargingLayout(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| init(context, attrs, false); |
| } |
| |
| private void init(Context c, AttributeSet attrs, boolean isDozing) { |
| init(c, attrs, -1, -1, false); |
| } |
| |
| private void init(Context context, AttributeSet attrs, int transmittingBatteryLevel, |
| int batteryLevel, boolean isDozing) { |
| final boolean showTransmittingBatteryLevel = |
| (transmittingBatteryLevel != UNKNOWN_BATTERY_LEVEL); |
| |
| // set style based on background |
| int style = R.style.ChargingAnim_WallpaperBackground; |
| if (isDozing) { |
| style = R.style.ChargingAnim_DarkBackground; |
| } |
| |
| inflate(new ContextThemeWrapper(context, style), R.layout.wireless_charging_layout, this); |
| |
| // amount of battery: |
| final TextView percentage = findViewById(R.id.wireless_charging_percentage); |
| |
| if (batteryLevel != UNKNOWN_BATTERY_LEVEL) { |
| percentage.setText(NumberFormat.getPercentInstance().format(batteryLevel / 100f)); |
| percentage.setAlpha(0); |
| } |
| |
| final long chargingAnimationFadeStartOffset = context.getResources().getInteger( |
| R.integer.wireless_charging_fade_offset); |
| final long chargingAnimationFadeDuration = context.getResources().getInteger( |
| R.integer.wireless_charging_fade_duration); |
| final float batteryLevelTextSizeStart = context.getResources().getFloat( |
| R.dimen.wireless_charging_anim_battery_level_text_size_start); |
| final float batteryLevelTextSizeEnd = context.getResources().getFloat( |
| R.dimen.wireless_charging_anim_battery_level_text_size_end) * ( |
| showTransmittingBatteryLevel ? 0.75f : 1.0f); |
| |
| // Animation Scale: battery percentage text scales from 0% to 100% |
| ValueAnimator textSizeAnimator = ObjectAnimator.ofFloat(percentage, "textSize", |
| batteryLevelTextSizeStart, batteryLevelTextSizeEnd); |
| textSizeAnimator.setInterpolator(new PathInterpolator(0, 0, 0, 1)); |
| textSizeAnimator.setDuration(context.getResources().getInteger( |
| R.integer.wireless_charging_battery_level_text_scale_animation_duration)); |
| |
| // Animation Opacity: battery percentage text transitions from 0 to 1 opacity |
| ValueAnimator textOpacityAnimator = ObjectAnimator.ofFloat(percentage, "alpha", 0, 1); |
| textOpacityAnimator.setInterpolator(Interpolators.LINEAR); |
| textOpacityAnimator.setDuration(context.getResources().getInteger( |
| R.integer.wireless_charging_battery_level_text_opacity_duration)); |
| textOpacityAnimator.setStartDelay(context.getResources().getInteger( |
| R.integer.wireless_charging_anim_opacity_offset)); |
| |
| // Animation Opacity: battery percentage text fades from 1 to 0 opacity |
| ValueAnimator textFadeAnimator = ObjectAnimator.ofFloat(percentage, "alpha", 1, 0); |
| textFadeAnimator.setDuration(chargingAnimationFadeDuration); |
| textFadeAnimator.setInterpolator(Interpolators.LINEAR); |
| textFadeAnimator.setStartDelay(chargingAnimationFadeStartOffset); |
| |
| // play all animations together |
| AnimatorSet animatorSet = new AnimatorSet(); |
| animatorSet.playTogether(textSizeAnimator, textOpacityAnimator, textFadeAnimator); |
| |
| ValueAnimator scrimFadeInAnimator = ObjectAnimator.ofArgb(this, |
| "backgroundColor", Color.TRANSPARENT, SCRIM_COLOR); |
| scrimFadeInAnimator.setDuration(SCRIM_FADE_DURATION); |
| scrimFadeInAnimator.setInterpolator(Interpolators.LINEAR); |
| ValueAnimator scrimFadeOutAnimator = ObjectAnimator.ofArgb(this, |
| "backgroundColor", SCRIM_COLOR, Color.TRANSPARENT); |
| scrimFadeOutAnimator.setDuration(SCRIM_FADE_DURATION); |
| scrimFadeOutAnimator.setInterpolator(Interpolators.LINEAR); |
| scrimFadeOutAnimator.setStartDelay(RIPPLE_ANIMATION_DURATION - SCRIM_FADE_DURATION); |
| AnimatorSet animatorSetScrim = new AnimatorSet(); |
| animatorSetScrim.playTogether(scrimFadeInAnimator, scrimFadeOutAnimator); |
| animatorSetScrim.start(); |
| |
| mRippleView = findViewById(R.id.wireless_charging_ripple); |
| OnAttachStateChangeListener listener = new OnAttachStateChangeListener() { |
| @Override |
| public void onViewAttachedToWindow(View view) { |
| mRippleView.setDuration(RIPPLE_ANIMATION_DURATION); |
| mRippleView.startRipple(); |
| mRippleView.removeOnAttachStateChangeListener(this); |
| } |
| |
| @Override |
| public void onViewDetachedFromWindow(View view) {} |
| }; |
| mRippleView.addOnAttachStateChangeListener(listener); |
| |
| if (!showTransmittingBatteryLevel) { |
| animatorSet.start(); |
| return; |
| } |
| |
| // amount of transmitting battery: |
| final TextView transmittingPercentage = findViewById( |
| R.id.reverse_wireless_charging_percentage); |
| transmittingPercentage.setVisibility(VISIBLE); |
| transmittingPercentage.setText( |
| NumberFormat.getPercentInstance().format(transmittingBatteryLevel / 100f)); |
| transmittingPercentage.setAlpha(0); |
| |
| // Animation Scale: transmitting battery percentage text scales from 0% to 100% |
| ValueAnimator textSizeAnimatorTransmitting = ObjectAnimator.ofFloat(transmittingPercentage, |
| "textSize", batteryLevelTextSizeStart, batteryLevelTextSizeEnd); |
| textSizeAnimatorTransmitting.setInterpolator(new PathInterpolator(0, 0, 0, 1)); |
| textSizeAnimatorTransmitting.setDuration(context.getResources().getInteger( |
| R.integer.wireless_charging_battery_level_text_scale_animation_duration)); |
| |
| // Animation Opacity: transmitting battery percentage text transitions from 0 to 1 opacity |
| ValueAnimator textOpacityAnimatorTransmitting = ObjectAnimator.ofFloat( |
| transmittingPercentage, "alpha", 0, 1); |
| textOpacityAnimatorTransmitting.setInterpolator(Interpolators.LINEAR); |
| textOpacityAnimatorTransmitting.setDuration(context.getResources().getInteger( |
| R.integer.wireless_charging_battery_level_text_opacity_duration)); |
| textOpacityAnimatorTransmitting.setStartDelay( |
| context.getResources().getInteger(R.integer.wireless_charging_anim_opacity_offset)); |
| |
| // Animation Opacity: transmitting battery percentage text fades from 1 to 0 opacity |
| ValueAnimator textFadeAnimatorTransmitting = ObjectAnimator.ofFloat(transmittingPercentage, |
| "alpha", 1, 0); |
| textFadeAnimatorTransmitting.setDuration(chargingAnimationFadeDuration); |
| textFadeAnimatorTransmitting.setInterpolator(Interpolators.LINEAR); |
| textFadeAnimatorTransmitting.setStartDelay(chargingAnimationFadeStartOffset); |
| |
| // play all animations together |
| AnimatorSet animatorSetTransmitting = new AnimatorSet(); |
| animatorSetTransmitting.playTogether(textSizeAnimatorTransmitting, |
| textOpacityAnimatorTransmitting, textFadeAnimatorTransmitting); |
| |
| // transmitting battery icon |
| final ImageView chargingViewIcon = findViewById(R.id.reverse_wireless_charging_icon); |
| chargingViewIcon.setVisibility(VISIBLE); |
| final int padding = Math.round( |
| TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, batteryLevelTextSizeEnd, |
| getResources().getDisplayMetrics())); |
| chargingViewIcon.setPadding(padding, 0, padding, 0); |
| |
| // Animation Opacity: transmitting battery icon transitions from 0 to 1 opacity |
| ValueAnimator textOpacityAnimatorIcon = ObjectAnimator.ofFloat(chargingViewIcon, "alpha", 0, |
| 1); |
| textOpacityAnimatorIcon.setInterpolator(Interpolators.LINEAR); |
| textOpacityAnimatorIcon.setDuration(context.getResources().getInteger( |
| R.integer.wireless_charging_battery_level_text_opacity_duration)); |
| textOpacityAnimatorIcon.setStartDelay( |
| context.getResources().getInteger(R.integer.wireless_charging_anim_opacity_offset)); |
| |
| // Animation Opacity: transmitting battery icon fades from 1 to 0 opacity |
| ValueAnimator textFadeAnimatorIcon = ObjectAnimator.ofFloat(chargingViewIcon, "alpha", 1, |
| 0); |
| textFadeAnimatorIcon.setDuration(chargingAnimationFadeDuration); |
| textFadeAnimatorIcon.setInterpolator(Interpolators.LINEAR); |
| textFadeAnimatorIcon.setStartDelay(chargingAnimationFadeStartOffset); |
| |
| // play all animations together |
| AnimatorSet animatorSetIcon = new AnimatorSet(); |
| animatorSetIcon.playTogether(textOpacityAnimatorIcon, textFadeAnimatorIcon); |
| |
| animatorSet.start(); |
| animatorSetTransmitting.start(); |
| animatorSetIcon.start(); |
| } |
| |
| @Override |
| protected void onLayout(boolean changed, int left, int top, int right, int bottom) { |
| if (mRippleView != null) { |
| int width = getMeasuredWidth(); |
| int height = getMeasuredHeight(); |
| mRippleView.setColor( |
| Utils.getColorAttr(mRippleView.getContext(), |
| android.R.attr.colorAccent).getDefaultColor()); |
| mRippleView.setOrigin(new PointF(width / 2, height / 2)); |
| mRippleView.setRadius(Math.max(width, height) * 0.5f); |
| } |
| |
| super.onLayout(changed, left, top, right, bottom); |
| } |
| } |