Early version of new volume + power menus

Still needs a bunch of code cleanup, but this will get a version
into the tree for testing.

Test: visual
Bug: 37013646
Change-Id: I29800b57d80ea120c691663392f368c17325ab54
This commit is contained in:
Jason Monk
2017-04-27 14:28:49 -04:00
parent ecb3d1139d
commit 16fbd9dd1d
14 changed files with 845 additions and 197 deletions

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ffffffff" />
<corners
android:bottomLeftRadius="@dimen/corner_size"
android:topLeftRadius="@dimen/corner_size"
android:bottomRightRadius="0dp"
android:topRightRadius="0dp"
/>
</shape>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ffeeeeee" />
<corners
android:bottomLeftRadius="@dimen/corner_size"
android:topLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topRightRadius="0dp"
/>
</shape>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ffffffff" />
<corners
android:bottomLeftRadius="@dimen/corner_size"
android:topLeftRadius="@dimen/corner_size"
android:bottomRightRadius="@dimen/corner_size"
android:topRightRadius="@dimen/corner_size"
/>
</shape>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ffeeeeee" />
<corners
android:bottomLeftRadius="@dimen/corner_size"
android:topLeftRadius="0dp"
android:bottomRightRadius="@dimen/corner_size"
android:topRightRadius="0dp"
/>
</shape>

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 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.
-->
<!-- RelativeLayouts have an issue enforcing minimum heights, so just
work around this for now with LinearLayouts. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/global_actions_panel_width"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="vertical"
android:paddingBottom="24dip"
android:paddingEnd="8dip"
android:paddingStart="8dip"
android:paddingTop="24dip">
<ImageView
android:id="@*android:id/icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:scaleType="center"/>
<TextView
android:id="@*android:id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|center_horizontal"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
<TextView
android:id="@*android:id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|center_horizontal"
android:gravity="center"
android:minHeight="26dp"
android:textColor="?android:attr/textColorTertiary"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
</LinearLayout>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<com.android.systemui.HardwareUiLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="0dp"
android:paddingTop="@dimen/global_actions_top_padding"
android:clipToPadding="false"
android:clipChildren="false">
<LinearLayout
android:id="@android:id/list"
android:layout_width="@dimen/global_actions_panel_width"
android:layout_height="wrap_content"
android:layout_gravity="top|end"
android:layout_marginBottom="@dimen/volume_dialog_margin_bottom"
android:orientation="vertical"
android:paddingTop="@dimen/volume_dialog_padding_top"
android:divider="@null"
android:dividerHeight="0dp"
android:translationZ="8dp">
</LinearLayout>
</com.android.systemui.HardwareUiLayout>

View File

@@ -16,12 +16,12 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/volume_dialog"
android:layout_width="match_parent"
android:layout_width="@dimen/volume_dialog_panel_width"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/volume_dialog_margin_bottom"
android:background="@drawable/volume_dialog_background"
android:layout_gravity="center_vertical|end"
android:paddingTop="@dimen/volume_dialog_padding_top"
android:translationZ="4dp" >
android:translationZ="8dp" >
<LinearLayout
android:id="@+id/volume_dialog_content"
@@ -57,6 +57,7 @@
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:visibility="gone"
android:textAppearance="@style/TextAppearance.Volume.Header" />
<com.android.keyguard.AlphaOptimizedImageButton
xmlns:android="http://schemas.android.com/apk/res/android"

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<com.android.systemui.HardwareUiLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/top_padding"
android:layout_marginBottom="@dimen/bottom_padding">
<include layout="@layout/volume_dialog"/>
</com.android.systemui.HardwareUiLayout>

View File

@@ -208,8 +208,6 @@
<!-- The width of the panel that holds the quick settings. -->
<dimen name="qs_panel_width">@dimen/notification_panel_width</dimen>
<dimen name="volume_dialog_panel_width">@dimen/standard_notification_panel_width</dimen>
<!-- Gravity for the notification panel -->
<integer name="notification_panel_layout_gravity">0x31</integer><!-- center_horizontal|top -->
@@ -780,4 +778,15 @@
<dimen name="signal_icon_size">17dp</dimen>
<dimen name="hwui_edge_margin">16dp</dimen>
<dimen name="volume_dialog_panel_width">315dp</dimen>
<dimen name="global_actions_panel_width">125dp</dimen>
<dimen name="global_actions_top_padding">100dp</dimen>
<dimen name="corner_size">16dp</dimen>
<dimen name="top_padding">0dp</dimen>
<dimen name="bottom_padding">48dp</dimen>
<dimen name="edge_margin">16dp</dimen>
</resources>

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2017 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;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.Log;
public class HardwareBgDrawable extends LayerDrawable {
private final Paint mPaint = new Paint();
private final Drawable[] mLayers;
private final boolean mRoundTop;
private int mPoint;
private boolean mRotatedBackground;
public HardwareBgDrawable(boolean roundTop, boolean roundEnd, Context context) {
this(roundTop, getLayers(context, roundTop, roundEnd));
}
public HardwareBgDrawable(boolean roundTop, Drawable[] layers) {
super(layers);
if (layers.length != 2) {
throw new IllegalArgumentException("Need 2 layers");
}
mRoundTop = roundTop;
mLayers = layers;
mLayers[1].setTint(0xffeeeeee);
}
private static Drawable[] getLayers(Context context, boolean roundTop, boolean roundEnd) {
int drawable = roundEnd ? R.drawable.rounded_bg_full : R.drawable.rounded_bg;
if (roundTop) {
return new Drawable[]{
context.getDrawable(drawable).mutate(),
context.getDrawable(drawable).mutate(),
};
}
return new Drawable[]{
context.getDrawable(drawable).mutate(),
context.getDrawable(roundEnd ? R.drawable.rounded_full_bg_bottom
: R.drawable.rounded_bg_bottom).mutate(),
};
}
public void setCutPoint(int point) {
mPoint = point;
invalidateSelf();
}
public int getCutPoint() {
return mPoint;
}
@Override
public void draw(Canvas canvas) {
if (mPoint >= 0 && !mRotatedBackground) {
Rect bounds = getBounds();
int top = bounds.top + mPoint;
if (top > bounds.bottom) top = bounds.bottom;
if (mRoundTop) {
mLayers[0].setBounds(bounds.left, bounds.top, bounds.right, top);
} else {
mLayers[1].setBounds(bounds.left, top, bounds.right, bounds.bottom);
}
if (mRoundTop) {
mLayers[1].draw(canvas);
mLayers[0].draw(canvas);
} else {
mLayers[0].draw(canvas);
mLayers[1].draw(canvas);
}
} else {
mLayers[0].draw(canvas);
}
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
mPaint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return PixelFormat.OPAQUE;
}
public void setRotatedBackground(boolean rotatedBackground) {
mRotatedBackground = rotatedBackground;
}
}

View File

@@ -0,0 +1,383 @@
/*
* Copyright (C) 2017 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;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.provider.Settings;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
public class HardwareUiLayout extends FrameLayout implements Tunable {
private static final String EDGE_BLEED = "sysui_hwui_edge_bleed";
private static final String ROUNDED_DIVIDER = "sysui_hwui_rounded_divider";
private final int[] mTmp2 = new int[2];
private View mChild;
private int mOldHeight;
private boolean mAnimating;
private AnimatorSet mAnimation;
private View mDivision;
private boolean mHasOutsideTouch;
private HardwareBgDrawable mBackground;
private Animator mAnimator;
private boolean mCollapse;
private int mEndPoint;
private boolean mEdgeBleed;
private boolean mRoundedDivider;
private boolean mLandscape;
private boolean mRotatedBackground;
public HardwareUiLayout(Context context, AttributeSet attrs) {
super(context, attrs);
updateSettings();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
updateSettings();
Dependency.get(TunerService.class).addTunable(this, EDGE_BLEED, ROUNDED_DIVIDER);
getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsListener);
Dependency.get(TunerService.class).removeTunable(this);
}
@Override
public void onTuningChanged(String key, String newValue) {
updateSettings();
}
private void updateSettings() {
mEdgeBleed = Settings.Secure.getInt(getContext().getContentResolver(),
EDGE_BLEED, 0) != 0;
mRoundedDivider = Settings.Secure.getInt(getContext().getContentResolver(),
ROUNDED_DIVIDER, 1) != 0;
updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
mBackground = new HardwareBgDrawable(mRoundedDivider, !mEdgeBleed, getContext());
if (mChild != null) {
mChild.setBackground(mBackground);
requestLayout();
}
}
private void updateEdgeMargin(int edge) {
if (mChild != null) {
MarginLayoutParams params = (MarginLayoutParams) mChild.getLayoutParams();
if (mLandscape) {
params.topMargin = edge;
} else {
params.rightMargin = edge;
}
mChild.setLayoutParams(params);
}
}
private int getEdgePadding() {
return getContext().getResources().getDimensionPixelSize(R.dimen.edge_margin);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mChild == null) {
if (getChildCount() != 0) {
mChild = getChildAt(0);
mChild.setBackground(mBackground);
updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
mOldHeight = mChild.getMeasuredHeight();
mChild.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
updatePosition());
} else {
return;
}
}
int newHeight = mChild.getMeasuredHeight();
if (newHeight != mOldHeight) {
animateChild(mOldHeight, newHeight);
}
post(() -> updatePosition());
boolean landscape = getMeasuredWidth() > getMeasuredHeight();
if (landscape != mLandscape) {
mLandscape = landscape;
if (mLandscape) {
toLandscape();
if (mChild instanceof LinearLayout) {
mRotatedBackground = true;
mBackground.setRotatedBackground(true);
((LinearLayout) mChild).setOrientation(LinearLayout.HORIZONTAL);
swapDimens(mChild);
}
} else {
fromLandscape();
if (mChild instanceof LinearLayout) {
mRotatedBackground = false;
mBackground.setRotatedBackground(false);
((LinearLayout) mChild).setOrientation(LinearLayout.VERTICAL);
swapDimens(mChild);
}
}
}
}
private void fromLandscape() {
rotateRight(this);
rotateRight(mChild);
swapDimens(this);
LayoutParams p = (LayoutParams) mChild.getLayoutParams();
p.gravity = rotateGravityRight(p.gravity);
mChild.setLayoutParams(p);
}
private void swapDimens(View v) {
ViewGroup.LayoutParams params = v.getLayoutParams();
int h = params.width;
params.width = params.height;
params.height = h;
v.setLayoutParams(params);
}
private int rotateGravityRight(int gravity) {
int retGravity = 0;
int layoutDirection = getLayoutDirection();
final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.CENTER_HORIZONTAL:
retGravity |= Gravity.CENTER_VERTICAL;
break;
case Gravity.RIGHT:
retGravity |= Gravity.BOTTOM;
break;
case Gravity.LEFT:
default:
retGravity |= Gravity.TOP;
break;
}
switch (verticalGravity) {
case Gravity.CENTER_VERTICAL:
retGravity |= Gravity.CENTER_HORIZONTAL;
break;
case Gravity.BOTTOM:
retGravity |= Gravity.LEFT;
break;
case Gravity.TOP:
default:
retGravity |= Gravity.RIGHT;
break;
}
return retGravity;
}
private void toLandscape() {
rotateLeft(this);
rotateLeft(mChild);
swapDimens(this);
LayoutParams p = (LayoutParams) mChild.getLayoutParams();
p.gravity = rotateGravityLeft(p.gravity);
mChild.setLayoutParams(p);
}
private int rotateGravityLeft(int gravity) {
if (gravity == -1) {
gravity = Gravity.TOP | Gravity.START;
}
int retGravity = 0;
int layoutDirection = getLayoutDirection();
final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.CENTER_HORIZONTAL:
retGravity |= Gravity.CENTER_VERTICAL;
break;
case Gravity.RIGHT:
retGravity |= Gravity.TOP;
break;
case Gravity.LEFT:
default:
retGravity |= Gravity.BOTTOM;
break;
}
switch (verticalGravity) {
case Gravity.CENTER_VERTICAL:
retGravity |= Gravity.CENTER_HORIZONTAL;
break;
case Gravity.BOTTOM:
retGravity |= Gravity.RIGHT;
break;
case Gravity.TOP:
default:
retGravity |= Gravity.LEFT;
break;
}
return retGravity;
}
private void rotateLeft(View v) {
v.setPadding(v.getPaddingTop(), v.getPaddingRight(), v.getPaddingBottom(),
v.getPaddingLeft());
MarginLayoutParams params = (MarginLayoutParams) v.getLayoutParams();
params.setMargins(params.topMargin, params.rightMargin, params.bottomMargin,
params.leftMargin);
v.setLayoutParams(params);
}
private void rotateRight(View v) {
v.setPadding(v.getPaddingBottom(), v.getPaddingLeft(), v.getPaddingTop(),
v.getPaddingRight());
MarginLayoutParams params = (MarginLayoutParams) v.getLayoutParams();
params.setMargins(params.bottomMargin, params.leftMargin, params.topMargin,
params.rightMargin);
v.setLayoutParams(params);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
post(() -> updatePosition());
}
private void animateChild(int oldHeight, int newHeight) {
if (true) return;
if (mAnimating) {
mAnimation.cancel();
}
mAnimating = true;
mAnimation = new AnimatorSet();
mAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mAnimating = false;
}
});
int fromTop = mChild.getTop();
int fromBottom = mChild.getBottom();
int toTop = fromTop - ((newHeight - oldHeight) / 2);
int toBottom = fromBottom + ((newHeight - oldHeight) / 2);
ObjectAnimator top = ObjectAnimator.ofInt(mChild, "top", fromTop, toTop);
top.addUpdateListener(animation -> mBackground.invalidateSelf());
mAnimation.playTogether(top,
ObjectAnimator.ofInt(mChild, "bottom", fromBottom, toBottom));
}
public void setDivisionView(View v) {
mDivision = v;
if (mDivision != null) {
mDivision.addOnLayoutChangeListener(
(v1, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
updatePosition());
}
updatePosition();
}
private void updatePosition() {
if (mChild == null) return;
if (mDivision != null && mDivision.getVisibility() == VISIBLE) {
int index = mRotatedBackground ? 0 : 1;
mDivision.getLocationOnScreen(mTmp2);
float trans = mRotatedBackground ? mDivision.getTranslationX()
: mDivision.getTranslationY();
int viewTop = (int) (mTmp2[index] + trans);
mChild.getLocationOnScreen(mTmp2);
viewTop -= mTmp2[index];
setCutPoint(viewTop);
} else {
setCutPoint(mChild.getMeasuredHeight());
}
}
private void setCutPoint(int point) {
int curPoint = mBackground.getCutPoint();
if (curPoint == point) return;
if (getAlpha() == 0 || curPoint == 0) {
mBackground.setCutPoint(point);
return;
}
if (mAnimator != null) {
if (mEndPoint == point) {
return;
}
mAnimator.cancel();
}
mEndPoint = point;
mAnimator = ObjectAnimator.ofInt(mBackground, "cutPoint", curPoint, point);
if (mCollapse) {
mAnimator.setStartDelay(300);
mCollapse = false;
}
mAnimator.start();
}
@Override
public ViewOutlineProvider getOutlineProvider() {
return super.getOutlineProvider();
}
public void setOutsideTouchListener(OnClickListener onClickListener) {
mHasOutsideTouch = true;
requestLayout();
setOnClickListener(onClickListener);
setClickable(true);
setFocusable(true);
}
public void setCollapse() {
mCollapse = true;
}
public static HardwareUiLayout get(View v) {
if (v instanceof HardwareUiLayout) return (HardwareUiLayout) v;
if (v.getParent() instanceof View) {
return get((View) v.getParent());
}
return null;
}
private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener = inoutInfo -> {
if (mHasOutsideTouch || (mChild == null)) {
inoutInfo.setTouchableInsets(
ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
return;
}
inoutInfo.setTouchableInsets(
ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT);
inoutInfo.contentInsets.set(mChild.getLeft(), mChild.getTop(),
0, getBottom() - mChild.getBottom());
};
}

View File

@@ -15,15 +15,16 @@
package com.android.systemui.globalactions;
import com.android.internal.R;
import com.android.internal.app.AlertController;
import com.android.internal.app.AlertController.AlertParams;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.EmergencyAffordanceManager;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.HardwareUiLayout;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
import com.android.systemui.volume.VolumeDialogMotion.LogAccelerateInterpolator;
import com.android.systemui.volume.VolumeDialogMotion.LogDecelerateInterpolator;
import android.app.ActivityManager;
import android.app.Dialog;
@@ -34,11 +35,13 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.database.DataSetObserver;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
@@ -56,8 +59,6 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -65,10 +66,11 @@ import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.ListView;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
@@ -79,7 +81,7 @@ import java.util.List;
* may show depending on whether the keyguard is showing, and whether the device
* is provisioned.
*/
class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener {
class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener {
static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
@@ -162,6 +164,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
/**
* Show the global actions dialog (creating if necessary)
*
* @param keyguardShowing True if keyguard is showing
*/
public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) {
@@ -205,12 +208,14 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
mDialog.getWindow().setAttributes(attrs);
mDialog.show();
mWindowManagerFuncs.onGlobalActionsShown();
mDialog.getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_DISABLE_EXPAND);
mDialog.getWindow().getDecorView().setSystemUiVisibility(
View.STATUS_BAR_DISABLE_EXPAND);
}
}
/**
* Create the global actions dialog.
*
* @return A new dialog.
*/
private ActionsDialog createDialog() {
@@ -314,28 +319,19 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
mAdapter = new MyAdapter();
AlertParams params = new AlertParams(mContext);
params.mAdapter = mAdapter;
params.mOnClickListener = this;
params.mForceInverseBackground = true;
ActionsDialog dialog = new ActionsDialog(mContext, params);
OnItemLongClickListener onItemLongClickListener = new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position,
long id) {
final Action action = mAdapter.getItem(position);
if (action instanceof LongPressAction) {
return ((LongPressAction) action).onLongPress();
}
return false;
}
};
ActionsDialog dialog = new ActionsDialog(mContext, this, mAdapter, onItemLongClickListener);
dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
dialog.getListView().setItemsCanFocus(true);
dialog.getListView().setLongClickable(true);
dialog.getListView().setOnItemLongClickListener(
new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position,
long id) {
final Action action = mAdapter.getItem(position);
if (action instanceof LongPressAction) {
return ((LongPressAction) action).onLongPress();
}
return false;
}
});
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
dialog.setOnDismissListener(this);
@@ -346,7 +342,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
private final class PowerAction extends SinglePressAction implements LongPressAction {
private PowerAction() {
super(R.drawable.ic_lock_power_off,
R.string.global_action_power_off);
R.string.global_action_power_off);
}
@Override
@@ -614,7 +610,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
SinglePressAction switchToUser = new SinglePressAction(
R.drawable.ic_menu_cc, icon,
(user.name != null ? user.name : "Primary")
+ (isCurrentUser ? " \u2714" : "")) {
+ (isCurrentUser ? " \u2714" : "")) {
public void onPress() {
try {
ActivityManager.getService().switchUser(user.id);
@@ -652,7 +648,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
if (!mHasVibrator) {
final boolean silentModeOn =
mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
((ToggleAction)mSilentModeAction).updateState(
((ToggleAction) mSilentModeAction).updateState(
silentModeOn ? ToggleAction.State.On : ToggleAction.State.Off);
}
}
@@ -681,7 +677,8 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
/**
* The adapter used for the list within the global actions dialog, taking
* into account whether the keyguard is showing via
* {@link com.android.systemui.globalactions.GlobalActionsDialog#mKeyguardShowing} and whether the device is provisioned
* {@link com.android.systemui.globalactions.GlobalActionsDialog#mKeyguardShowing} and whether
* the device is provisioned
* via {@link com.android.systemui.globalactions.GlobalActionsDialog#mDeviceProvisioned}.
*/
private class MyAdapter extends BaseAdapter {
@@ -744,7 +741,11 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
public View getView(int position, View convertView, ViewGroup parent) {
Action action = getItem(position);
return action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
View view = action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
if (position == 2) {
HardwareUiLayout.get(parent).setDivisionView(view);
}
return view;
}
}
@@ -760,7 +761,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
private interface Action {
/**
* @return Text that will be announced when dialog is created. null
* for none.
* for none.
*/
CharSequence getLabelForAccessibility(Context context);
@@ -770,13 +771,13 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
/**
* @return whether this action should appear in the dialog when the keygaurd
* is showing.
* is showing.
*/
boolean showDuringKeyguard();
/**
* @return whether this action should appear in the dialog before the
* device is provisioned.
* device is provisioned.
*/
boolean showBeforeProvisioning();
@@ -834,7 +835,8 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
public View create(
Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
View v = inflater.inflate(R.layout.global_actions_item, parent, false);
View v = inflater.inflate(com.android.systemui.R.layout.global_actions_item, parent,
false);
ImageView icon = (ImageView) v.findViewById(R.id.icon);
TextView messageView = (TextView) v.findViewById(R.id.message);
@@ -895,10 +897,10 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
protected int mDisabledStatusMessageResId;
/**
* @param enabledIconResId The icon for when this action is on.
* @param disabledIconResid The icon for when this action is off.
* @param message The general information message, e.g 'Silent Mode'
* @param enabledStatusMessageResId The on status message, e.g 'sound disabled'
* @param enabledIconResId The icon for when this action is on.
* @param disabledIconResid The icon for when this action is off.
* @param message The general information message, e.g 'Silent Mode'
* @param enabledStatusMessageResId The on status message, e.g 'sound disabled'
* @param disabledStatusMessageResId The off status message, e.g. 'sound enabled'
*/
public ToggleAction(int enabledIconResId,
@@ -931,7 +933,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
willCreate();
View v = inflater.inflate(R
.layout.global_actions_item, parent, false);
.layout.global_actions_item, parent, false);
ImageView icon = (ImageView) v.findViewById(R.id.icon);
TextView messageView = (TextView) v.findViewById(R.id.message);
@@ -979,6 +981,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
* Implementations may override this if their state can be in on of the intermediate
* states until some notification is received (e.g airplane mode is 'turning off' until
* we know the wireless connections are back online
*
* @param buttonOn Whether the button was turned on or off
*/
protected void changeStateFromPress(boolean buttonOn) {
@@ -1020,7 +1023,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
private static class SilentModeTriStateAction implements Action, View.OnClickListener {
private final int[] ITEM_IDS = { R.id.option1, R.id.option2, R.id.option3 };
private final int[] ITEM_IDS = {R.id.option1, R.id.option2, R.id.option3};
private final AudioManager mAudioManager;
private final Handler mHandler;
@@ -1145,19 +1148,19 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_DISMISS:
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
break;
case MESSAGE_REFRESH:
refreshSilentMode();
mAdapter.notifyDataSetChanged();
break;
case MESSAGE_SHOW:
handleShow();
break;
case MESSAGE_DISMISS:
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
break;
case MESSAGE_REFRESH:
refreshSilentMode();
mAdapter.notifyDataSetChanged();
break;
case MESSAGE_SHOW:
handleShow();
break;
}
}
};
@@ -1192,39 +1195,81 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
}
private static final class ActionsDialog extends Dialog implements DialogInterface {
private final Context mContext;
private final AlertController mAlert;
private final MyAdapter mAdapter;
public ActionsDialog(Context context, AlertParams params) {
super(context, getDialogTheme(context));
private final Context mContext;
private final MyAdapter mAdapter;
private final LinearLayout mListView;
private final HardwareUiLayout mHardwareLayout;
private final OnClickListener mClickListener;
private final OnItemLongClickListener mLongClickListener;
public ActionsDialog(Context context, OnClickListener clickListener, MyAdapter adapter,
OnItemLongClickListener longClickListener) {
super(context, android.R.style.Theme_DeviceDefault_Light_NoActionBar_Fullscreen);
mContext = getContext();
mAlert = AlertController.create(mContext, this, getWindow());
mAdapter = (MyAdapter) params.mAdapter;
params.apply(mAlert);
mAdapter = adapter;
mClickListener = clickListener;
mLongClickListener = longClickListener;
setContentView(com.android.systemui.R.layout.global_actions_wrapped);
getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
mListView = findViewById(android.R.id.list);
mHardwareLayout = HardwareUiLayout.get(mListView);
mHardwareLayout.setOutsideTouchListener(view -> dismiss());
}
private static int getDialogTheme(Context context) {
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.alertDialogTheme,
outValue, true);
return outValue.resourceId;
private void updateList() {
mListView.removeAllViews();
for (int i = 0; i < mAdapter.getCount(); i++) {
View v = mAdapter.getView(i, null, mListView);
final int pos = i;
v.setOnClickListener(view -> mClickListener.onClick(this, pos));
v.setOnLongClickListener(view ->
mLongClickListener.onItemLongClick(null, v, pos, 0));
mListView.addView(v);
}
}
@Override
protected void onStart() {
super.setCanceledOnTouchOutside(true);
super.onStart();
}
public ListView getListView() {
return mAlert.getListView();
updateList();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAlert.installContent();
protected void onStop() {
super.onStop();
}
@Override
public void show() {
super.show();
mHardwareLayout.setTranslationX(getAnimTranslation());
mHardwareLayout.setAlpha(0);
mHardwareLayout.animate()
.alpha(1)
.translationX(0)
.setDuration(300)
.setInterpolator(new LogDecelerateInterpolator())
.start();
}
@Override
public void dismiss() {
mHardwareLayout.setTranslationX(0);
mHardwareLayout.setAlpha(1);
mHardwareLayout.animate()
.alpha(0)
.translationX(getAnimTranslation())
.setDuration(300)
.withEndAction(() -> super.dismiss())
.setInterpolator(new LogAccelerateInterpolator())
.start();
}
private float getAnimTranslation() {
return getContext().getResources().getDimension(
com.android.systemui.R.dimen.global_actions_panel_width) / 2;
}
@Override
@@ -1240,21 +1285,5 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
}
return super.dispatchPopulateAccessibilityEvent(event);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (mAlert.onKeyDown(keyCode, event)) {
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (mAlert.onKeyUp(keyCode, event)) {
return true;
}
return super.onKeyUp(keyCode, event);
}
}
}

View File

@@ -18,6 +18,7 @@ package com.android.systemui.volume;
import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_GENERIC;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.animation.ObjectAnimator;
@@ -59,6 +60,7 @@ import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.Window;
import android.view.WindowManager;
@@ -73,6 +75,7 @@ import android.widget.TextView;
import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.HardwareUiLayout;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.plugins.VolumeDialogController;
@@ -199,53 +202,37 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable {
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
mDialog.setCanceledOnTouchOutside(true);
final Resources res = mContext.getResources();
final WindowManager.LayoutParams lp = mWindow.getAttributes();
lp.type = mWindowType;
lp.format = PixelFormat.TRANSLUCENT;
lp.setTitle(VolumeDialogImpl.class.getSimpleName());
lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
lp.y = res.getDimensionPixelSize(R.dimen.volume_offset_top);
lp.gravity = Gravity.TOP;
lp.windowAnimations = -1;
mWindow.setAttributes(lp);
mWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
mDialog.setContentView(R.layout.volume_dialog);
mDialogView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog);
mDialogView.setOnHoverListener(new View.OnHoverListener() {
@Override
public boolean onHover(View v, MotionEvent event) {
int action = event.getActionMasked();
mHovering = (action == MotionEvent.ACTION_HOVER_ENTER)
|| (action == MotionEvent.ACTION_HOVER_MOVE);
rescheduleTimeoutH();
return true;
}
mDialog.setContentView(R.layout.volume_dialog_wrapped);
mDialogView = mDialog.findViewById(R.id.volume_dialog);
mDialogView.setOnHoverListener((v, event) -> {
int action = event.getActionMasked();
mHovering = (action == MotionEvent.ACTION_HOVER_ENTER)
|| (action == MotionEvent.ACTION_HOVER_MOVE);
rescheduleTimeoutH();
return true;
});
mDialogContentView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog_content);
mDialogRowsView = (ViewGroup) mDialogContentView.findViewById(R.id.volume_dialog_rows);
mDialogContentView = mDialog.findViewById(R.id.volume_dialog_content);
mDialogRowsView = mDialogContentView.findViewById(R.id.volume_dialog_rows);
mExpanded = false;
mExpandButton = (ImageButton) mDialogView.findViewById(R.id.volume_expand_button);
mExpandButton = mDialogView.findViewById(R.id.volume_expand_button);
mExpandButton.setOnClickListener(mClickExpand);
mExpandButton.setVisibility(
AudioSystem.isSingleVolume(mContext) ? View.GONE : View.VISIBLE);
updateWindowWidthH();
updateExpandButtonH();
mMotion = new VolumeDialogMotion(mDialog, mDialogView, mDialogContentView, mExpandButton,
new VolumeDialogMotion.Callback() {
@Override
public void onAnimatingChanged(boolean animating) {
if (animating) return;
if (mPendingStateChanged) {
mHandler.sendEmptyMessage(H.STATE_CHANGED);
mPendingStateChanged = false;
}
if (mPendingRecheckAll) {
mHandler.sendEmptyMessage(H.RECHECK_ALL);
mPendingRecheckAll = false;
}
mMotion = new VolumeDialogMotion(mDialog, (View) mDialogView.getParent(),
mDialogContentView, mExpandButton, animating -> {
if (animating) return;
if (mPendingStateChanged) {
mHandler.sendEmptyMessage(H.STATE_CHANGED);
mPendingStateChanged = false;
}
if (mPendingRecheckAll) {
mHandler.sendEmptyMessage(H.RECHECK_ALL);
mPendingRecheckAll = false;
}
});
@@ -270,11 +257,20 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable {
addExistingRows();
}
mExpandButtonAnimationDuration = res.getInteger(R.integer.volume_expand_animation_duration);
mZenFooter = (ZenFooter) mDialog.findViewById(R.id.volume_zen_footer);
mZenFooter = mDialog.findViewById(R.id.volume_zen_footer);
mZenFooter.init(mZenModeController);
mZenPanel = (TunerZenModePanel) mDialog.findViewById(R.id.tuner_zen_mode_panel);
mZenPanel = mDialog.findViewById(R.id.tuner_zen_mode_panel);
mZenPanel.init(mZenModeController);
mZenPanel.setCallback(mZenPanelCallback);
final WindowManager.LayoutParams lp = mWindow.getAttributes();
lp.width = MATCH_PARENT;
lp.height = MATCH_PARENT;
lp.type = mWindowType;
lp.format = PixelFormat.TRANSLUCENT;
lp.setTitle(VolumeDialogImpl.class.getSimpleName());
lp.windowAnimations = -1;
mWindow.setAttributes(lp);
}
@Override
@@ -288,20 +284,6 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable {
return ColorStateList.valueOf(mContext.getColor(colorResId));
}
private void updateWindowWidthH() {
final ViewGroup.LayoutParams lp = mDialogView.getLayoutParams();
final DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
if (D.BUG) Log.d(TAG, "updateWindowWidth dm.w=" + dm.widthPixels);
int w = dm.widthPixels;
final int max = mContext.getResources()
.getDimensionPixelSize(R.dimen.volume_dialog_panel_width);
if (w > max) {
w = max;
}
lp.width = w;
mDialogView.setLayoutParams(lp);
}
public void setStreamImportant(int stream, boolean important) {
mHandler.obtainMessage(H.SET_STREAM_IMPORTANT, stream, important ? 1 : 0).sendToTarget();
}
@@ -542,10 +524,8 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable {
}
private void updateDialogBottomMarginH() {
final long diff = System.currentTimeMillis() - mCollapseTime;
final boolean collapsing = mCollapseTime != 0 && diff < getConservativeCollapseDuration();
final ViewGroup.MarginLayoutParams mlp = (MarginLayoutParams) mDialogView.getLayoutParams();
final int bottomMargin = collapsing ? mDialogContentView.getHeight() :
final int bottomMargin =
mContext.getResources().getDimensionPixelSize(R.dimen.volume_dialog_margin_bottom);
if (bottomMargin != mlp.bottomMargin) {
if (D.BUG) Log.d(TAG, "bottomMargin " + mlp.bottomMargin + " -> " + bottomMargin);
@@ -575,7 +555,7 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable {
TransitionManager.endTransitions(mDialogView);
final VolumeRow activeRow = getActiveRow();
if (!dismissing) {
mWindow.setLayout(mWindow.getAttributes().width, ViewGroup.LayoutParams.MATCH_PARENT);
mWindow.setLayout(mWindow.getAttributes().width, MATCH_PARENT);
TransitionManager.beginDelayedTransition(mDialogView, getTransistion());
}
updateRowsH(activeRow);
@@ -637,7 +617,7 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable {
final boolean isActive = row == activeRow;
final boolean shouldBeVisible = shouldBeVisibleH(row, isActive);
Util.setVisOrGone(row.view, shouldBeVisible);
Util.setVisOrGone(row.header, shouldBeVisible);
Util.setVisOrGone(row.header, shouldBeVisible && mExpanded);
if (row.view.isShown()) {
updateVolumeRowSliderTintH(row, isActive);
}
@@ -699,6 +679,16 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable {
if (wasVisible != visible && !visible) {
prepareForCollapse();
}
if (visible != wasVisible) {
if (visible) {
HardwareUiLayout.get(mZenFooter).setDivisionView(mZenFooter);
} else {
mHandler.postDelayed(() ->
HardwareUiLayout.get(mZenFooter).setDivisionView(mZenFooter),
mExpandButtonAnimationDuration);
}
}
Util.setVisOrGone(mZenFooter, visible);
mZenFooter.update();
@@ -962,8 +952,7 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable {
@Override
public void onTransitionEnd(Transition transition) {
mWindow.setLayout(
mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT);
mWindow.setLayout(MATCH_PARENT, MATCH_PARENT);
}
@Override
@@ -972,8 +961,7 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable {
@Override
public void onTransitionPause(Transition transition) {
mWindow.setLayout(
mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT);
mWindow.setLayout(MATCH_PARENT, MATCH_PARENT);
}
@Override
@@ -1025,7 +1013,6 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable {
initDialog();
mDensity = density;
}
updateWindowWidthH();
mConfigurableTexts.update();
mZenFooter.onConfigurationChanged();
}
@@ -1081,6 +1068,9 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable {
if (mExpandButtonAnimationRunning) return;
final boolean newExpand = !mExpanded;
Events.writeEvent(mContext, Events.EVENT_EXPAND, newExpand);
if (!newExpand) {
HardwareUiLayout.get(mDialogContentView).setCollapse();
}
updateExpandedH(newExpand, false /* dismissing */);
}
};
@@ -1156,8 +1146,8 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable {
event.setPackageName(mContext.getPackageName());
ViewGroup.LayoutParams params = getWindow().getAttributes();
boolean isFullScreen = (params.width == ViewGroup.LayoutParams.MATCH_PARENT) &&
(params.height == ViewGroup.LayoutParams.MATCH_PARENT);
boolean isFullScreen = (params.width == MATCH_PARENT) &&
(params.height == MATCH_PARENT);
event.setFullScreen(isFullScreen);
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.volume;
import android.animation.Animator;
@@ -67,8 +66,8 @@ public class VolumeDialogMotion {
@Override
public void onShow(DialogInterface dialog) {
if (D.BUG) Log.d(TAG, "mDialog.onShow");
final int h = mDialogView.getHeight();
mDialogView.setTranslationY(-h);
final int w = mDialogView.getWidth() / 4;
mDialogView.setTranslationX(w);
startShowAnimation();
}
});
@@ -117,7 +116,7 @@ public class VolumeDialogMotion {
}
private int chevronDistance() {
return mChevron.getHeight() / 6;
return 0;
}
private int chevronPosY() {
@@ -128,7 +127,9 @@ public class VolumeDialogMotion {
private void startShowAnimation() {
if (D.BUG) Log.d(TAG, "startShowAnimation");
mDialogView.animate()
.translationX(0)
.translationY(0)
.alpha(1)
.setDuration(scaledDuration(300))
.setInterpolator(new LogDecelerateInterpolator())
.setListener(null)
@@ -139,7 +140,6 @@ public class VolumeDialogMotion {
// reposition chevron
final float v = (Float) mChevronPositionAnimator.getAnimatedValue();
final int posY = chevronPosY();
mChevron.setTranslationY(posY + v + -mDialogView.getTranslationY());
}
})
.withEndAction(new Runnable() {
@@ -148,7 +148,6 @@ public class VolumeDialogMotion {
if (mChevronPositionAnimator == null) return;
// reposition chevron
final int posY = chevronPosY();
mChevron.setTranslationY(posY + -mDialogView.getTranslationY());
}
})
.start();
@@ -164,19 +163,13 @@ public class VolumeDialogMotion {
if (D.BUG) Log.d(TAG, "show.onAnimationEnd");
setShowing(false);
}
@Override
public void onAnimationCancel(Animator animation) {
if (D.BUG) Log.d(TAG, "show.onAnimationCancel");
mCancelled = true;
}
});
mContentsPositionAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float v = (Float) animation.getAnimatedValue();
mContents.setTranslationY(v + -mDialogView.getTranslationY());
}
});
mContentsPositionAnimator.setInterpolator(new LogDecelerateInterpolator());
mContentsPositionAnimator.start();
@@ -218,34 +211,26 @@ public class VolumeDialogMotion {
setShowing(false);
}
mDialogView.animate()
.translationY(-mDialogView.getHeight())
.translationX(mDialogView.getWidth() / 4)
.alpha(0)
.setDuration(scaledDuration(250))
.setInterpolator(new LogAccelerateInterpolator())
.setUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mContents.setTranslationY(-mDialogView.getTranslationY());
final int posY = chevronPosY();
mChevron.setTranslationY(posY + -mDialogView.getTranslationY());
}
})
.setListener(new AnimatorListenerAdapter() {
private boolean mCancelled;
@Override
public void onAnimationEnd(Animator animation) {
if (mCancelled) return;
if (D.BUG) Log.d(TAG, "dismiss.onAnimationEnd");
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (D.BUG) Log.d(TAG, "mDialog.dismiss()");
mDialog.dismiss();
onComplete.run();
setDismissing(false);
}
mHandler.postDelayed(() -> {
if (D.BUG) Log.d(TAG, "mDialog.dismiss()");
mDialog.dismiss();
onComplete.run();
setDismissing(false);
}, PRE_DISMISS_DELAY);
}
@Override
public void onAnimationCancel(Animator animation) {
if (D.BUG) Log.d(TAG, "dismiss.onAnimationCancel");
@@ -258,13 +243,13 @@ public class VolumeDialogMotion {
return (int) (base * ANIMATION_SCALE);
}
private static final class LogDecelerateInterpolator implements TimeInterpolator {
public static final class LogDecelerateInterpolator implements TimeInterpolator {
private final float mBase;
private final float mDrift;
private final float mTimeScale;
private final float mOutputScale;
private LogDecelerateInterpolator() {
public LogDecelerateInterpolator() {
this(400f, 1.4f, 0);
}
@@ -286,12 +271,12 @@ public class VolumeDialogMotion {
}
}
private static final class LogAccelerateInterpolator implements TimeInterpolator {
public static final class LogAccelerateInterpolator implements TimeInterpolator {
private final int mBase;
private final int mDrift;
private final float mLogScale;
private LogAccelerateInterpolator() {
public LogAccelerateInterpolator() {
this(100, 0);
}