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:
11
packages/SystemUI/res/drawable/rounded_bg.xml
Normal file
11
packages/SystemUI/res/drawable/rounded_bg.xml
Normal 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>
|
||||
11
packages/SystemUI/res/drawable/rounded_bg_bottom.xml
Normal file
11
packages/SystemUI/res/drawable/rounded_bg_bottom.xml
Normal 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>
|
||||
11
packages/SystemUI/res/drawable/rounded_bg_full.xml
Normal file
11
packages/SystemUI/res/drawable/rounded_bg_full.xml
Normal 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>
|
||||
11
packages/SystemUI/res/drawable/rounded_full_bg_bottom.xml
Normal file
11
packages/SystemUI/res/drawable/rounded_full_bg_bottom.xml
Normal 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>
|
||||
57
packages/SystemUI/res/layout/global_actions_item.xml
Normal file
57
packages/SystemUI/res/layout/global_actions_item.xml
Normal 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>
|
||||
25
packages/SystemUI/res/layout/global_actions_wrapped.xml
Normal file
25
packages/SystemUI/res/layout/global_actions_wrapped.xml
Normal 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>
|
||||
@@ -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"
|
||||
|
||||
11
packages/SystemUI/res/layout/volume_dialog_wrapped.xml
Normal file
11
packages/SystemUI/res/layout/volume_dialog_wrapped.xml
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
383
packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
Normal file
383
packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
Normal 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());
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user