Show volume dialog vertically in all rotations
The volume dialog will be volume_dialog_base_margin dp away from the nearest thing on its right, be that nav bar, cutout, or the side of the device. Additionally made the dialog a bit shorter and skinnier to fit. Test: manual, used dialog in all rotations in rtl and ltr Change-Id: Ia2642ede7670989dcc2b7612cc8c3bf2ba94fbc7 Fixes: 72711737
This commit is contained in:
@@ -20,14 +20,15 @@
|
||||
android:background="@android:color/transparent"
|
||||
android:theme="@style/qs_theme"
|
||||
android:clipChildren="false" >
|
||||
<!-- right-aligned to be physically near volume button -->
|
||||
<LinearLayout
|
||||
android:id="@+id/volume_dialog"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_gravity="center_vertical|right"
|
||||
android:minWidth="@dimen/volume_dialog_panel_width"
|
||||
android:background="@android:color/transparent"
|
||||
android:layout_margin="12dp"
|
||||
android:layout_margin="@dimen/volume_dialog_base_margin"
|
||||
android:translationZ="8dp"
|
||||
android:orientation="vertical"
|
||||
android:clipChildren="false" >
|
||||
@@ -38,8 +39,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:background="@drawable/rounded_bg_full"
|
||||
android:translationZ="8dp"
|
||||
android:orientation="horizontal" >
|
||||
@@ -71,7 +72,7 @@
|
||||
android:maxLines="1"
|
||||
android:layout_centerVertical="true"
|
||||
android:textColor="?android:attr/colorControlNormal"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
android:textAppearance="@style/TextAppearance.Volume.Header" />
|
||||
|
||||
<com.android.keyguard.AlphaOptimizedImageButton
|
||||
android:id="@+id/ringer_icon"
|
||||
@@ -89,7 +90,7 @@
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/colorControlNormal"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
android:textAppearance="@style/TextAppearance.Volume.Header.Secondary" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -29,15 +29,16 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:padding="10dp">
|
||||
android:padding="5dp">
|
||||
<TextView
|
||||
android:id="@+id/volume_row_header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLength="10"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/colorControlNormal"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
android:textAppearance="@style/TextAppearance.Volume.Header" />
|
||||
<LinearLayout
|
||||
android:id="@+id/output_chooser"
|
||||
android:orientation="vertical"
|
||||
@@ -53,9 +54,10 @@
|
||||
android:visibility="gone"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLength="10"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.QS.DetailItemSecondary" />
|
||||
android:textAppearance="@style/TextAppearance.Volume.Header.Secondary" />
|
||||
<com.android.keyguard.AlphaOptimizedImageButton
|
||||
android:id="@+id/output_chooser_button"
|
||||
android:layout_width="24dp"
|
||||
@@ -74,13 +76,13 @@
|
||||
android:padding="0dp"
|
||||
android:layout_width="@dimen/volume_dialog_panel_width"
|
||||
android:layoutDirection="rtl"
|
||||
android:layout_height="150dp">
|
||||
android:layout_height="@dimen/volume_dialog_panel_width">
|
||||
<SeekBar
|
||||
android:id="@+id/volume_row_slider"
|
||||
android:clickable="true"
|
||||
android:padding="0dp"
|
||||
android:layout_margin="0dp"
|
||||
android:layout_width="150dp"
|
||||
android:layout_width="@dimen/volume_dialog_panel_width"
|
||||
android:layout_height="@dimen/volume_dialog_panel_width"
|
||||
android:layoutDirection="rtl"
|
||||
android:layout_gravity="center"
|
||||
|
||||
@@ -262,7 +262,11 @@
|
||||
<!-- 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">120dp</dimen>
|
||||
<!-- the amount the volume panel should be offset at the end from the view next to it (or
|
||||
the scren edge, in portrait-->
|
||||
<dimen name="volume_dialog_base_margin">12dp</dimen>
|
||||
|
||||
<dimen name="volume_dialog_panel_width">100dp</dimen>
|
||||
|
||||
<dimen name="output_chooser_panel_width">320dp</dimen>
|
||||
|
||||
|
||||
@@ -410,16 +410,11 @@
|
||||
<item name="android:textColor">?android:attr/textColorSecondary</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Volume.ZenSummary">
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
<style name="TextAppearance.Volume.Header.Secondary">
|
||||
<item name="android:textSize">12sp</item>
|
||||
<item name="android:textColor">?android:attr/textColorTertiary</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Volume.ZenDetail">
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:fontFamily">sans-serif</item>
|
||||
<item name="android:textColor">?android:attr/textColorSecondary</item>
|
||||
</style>
|
||||
|
||||
<style name="VolumeButtons" parent="@android:style/Widget.Material.Button.Borderless">
|
||||
<item name="android:background">@drawable/btn_borderless_rect</item>
|
||||
|
||||
@@ -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.media.AudioManager.STREAM_ACCESSIBILITY;
|
||||
|
||||
import static com.android.systemui.volume.Events.DISMISS_REASON_OUTPUT_CHOOSER;
|
||||
import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED;
|
||||
@@ -47,6 +48,7 @@ import android.os.SystemClock;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.Global;
|
||||
import android.support.v7.media.MediaRouter;
|
||||
import android.text.InputFilter;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
@@ -219,7 +221,7 @@ public class VolumeDialogImpl implements VolumeDialog {
|
||||
R.drawable.ic_volume_bt_sco, R.drawable.ic_volume_bt_sco, false, false);
|
||||
addRow(AudioManager.STREAM_SYSTEM, R.drawable.ic_volume_system,
|
||||
R.drawable.ic_volume_system_mute, false, false);
|
||||
addRow(AudioManager.STREAM_ACCESSIBILITY, R.drawable.ic_volume_accessibility,
|
||||
addRow(STREAM_ACCESSIBILITY, R.drawable.ic_volume_accessibility,
|
||||
R.drawable.ic_volume_accessibility, true, false);
|
||||
}
|
||||
} else {
|
||||
@@ -334,6 +336,9 @@ public class VolumeDialogImpl implements VolumeDialog {
|
||||
row.view.setTag(row);
|
||||
row.header = row.view.findViewById(R.id.volume_row_header);
|
||||
row.header.setId(20 * row.stream);
|
||||
if (stream == STREAM_ACCESSIBILITY) {
|
||||
row.header.setFilters(new InputFilter[] {new InputFilter.LengthFilter(13)});
|
||||
}
|
||||
row.slider = row.view.findViewById(R.id.volume_row_slider);
|
||||
row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row));
|
||||
row.anim = null;
|
||||
@@ -643,7 +648,7 @@ public class VolumeDialogImpl implements VolumeDialog {
|
||||
if (ss.level == row.requestedLevel) {
|
||||
row.requestedLevel = -1;
|
||||
}
|
||||
final boolean isA11yStream = row.stream == AudioManager.STREAM_ACCESSIBILITY;
|
||||
final boolean isA11yStream = row.stream == STREAM_ACCESSIBILITY;
|
||||
final boolean isRingStream = row.stream == AudioManager.STREAM_RING;
|
||||
final boolean isSystemStream = row.stream == AudioManager.STREAM_SYSTEM;
|
||||
final boolean isAlarmStream = row.stream == AudioManager.STREAM_ALARM;
|
||||
@@ -949,7 +954,7 @@ public class VolumeDialogImpl implements VolumeDialog {
|
||||
public void onAccessibilityModeChanged(Boolean showA11yStream) {
|
||||
mShowA11yStream = showA11yStream == null ? false : showA11yStream;
|
||||
VolumeRow activeRow = getActiveRow();
|
||||
if (!mShowA11yStream && AudioManager.STREAM_ACCESSIBILITY == activeRow.stream) {
|
||||
if (!mShowA11yStream && STREAM_ACCESSIBILITY == activeRow.stream) {
|
||||
dismissH(Events.DISMISS_STREAM_GONE);
|
||||
} else {
|
||||
updateRowsH(activeRow);
|
||||
|
||||
@@ -14,26 +14,22 @@
|
||||
|
||||
package com.android.systemui.volume;
|
||||
|
||||
import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
|
||||
import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
|
||||
import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Slog;
|
||||
import android.view.Gravity;
|
||||
import android.view.DisplayCutout;
|
||||
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 android.widget.SeekBar;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.util.leak.RotationUtils;
|
||||
@@ -46,6 +42,9 @@ public class VolumeUiLayout extends FrameLayout {
|
||||
private AnimatorSet mAnimation;
|
||||
private boolean mHasOutsideTouch;
|
||||
private int mRotation = ROTATION_NONE;
|
||||
@Nullable
|
||||
private DisplayCutout mDisplayCutout;
|
||||
|
||||
public VolumeUiLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
@@ -60,6 +59,7 @@ public class VolumeUiLayout extends FrameLayout {
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsListener);
|
||||
mDisplayCutout = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,200 +86,64 @@ public class VolumeUiLayout extends FrameLayout {
|
||||
updateRotation();
|
||||
}
|
||||
|
||||
private void setDisplayCutout() {
|
||||
if (mDisplayCutout == null && getRootWindowInsets() != null) {
|
||||
DisplayCutout cutout = getRootWindowInsets().getDisplayCutout();
|
||||
if (cutout != null) {
|
||||
mDisplayCutout = cutout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRotation() {
|
||||
setDisplayCutout();
|
||||
int rotation = RotationUtils.getRotation(getContext());
|
||||
if (rotation != mRotation) {
|
||||
rotate(mRotation, rotation);
|
||||
updateSafeInsets(rotation);
|
||||
mRotation = rotation;
|
||||
}
|
||||
}
|
||||
|
||||
private void rotate(View view, int from, int to, boolean swapDimens) {
|
||||
if (from != ROTATION_NONE && to != ROTATION_NONE) {
|
||||
// Rather than handling this confusing case, just do 2 rotations.
|
||||
rotate(view, from, ROTATION_NONE, swapDimens);
|
||||
rotate(view, ROTATION_NONE, to, swapDimens);
|
||||
return;
|
||||
}
|
||||
if (from == ROTATION_LANDSCAPE || to == ROTATION_SEASCAPE) {
|
||||
rotateRight(view);
|
||||
} else {
|
||||
rotateLeft(view);
|
||||
}
|
||||
if (to != ROTATION_NONE) {
|
||||
if (swapDimens && view instanceof LinearLayout) {
|
||||
LinearLayout linearLayout = (LinearLayout) view;
|
||||
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||
swapDimens(view);
|
||||
}
|
||||
} else {
|
||||
if (swapDimens && view instanceof LinearLayout) {
|
||||
LinearLayout linearLayout = (LinearLayout) view;
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
swapDimens(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void updateSafeInsets(int rotation) {
|
||||
// Depending on our rotation, we may have to work around letterboxing from the right
|
||||
// side from the navigation bar or a cutout.
|
||||
|
||||
private void rotate(int from, int to) {
|
||||
View footer = mChild.findViewById(R.id.footer);
|
||||
rotate(footer, from, to, false);
|
||||
rotate(this, from, to, true);
|
||||
rotate(mChild, from, to, true);
|
||||
ViewGroup rows = mChild.findViewById(R.id.volume_dialog_rows);
|
||||
rotate(rows, from, to, true);
|
||||
swapOrientation((LinearLayout) rows);
|
||||
int rowCount = rows.getChildCount();
|
||||
for (int i = 0; i < rowCount; i++) {
|
||||
View row = rows.getChildAt(i);
|
||||
if (to == ROTATION_SEASCAPE) {
|
||||
rotateSeekBars(row, to, 0);
|
||||
} else if (to == ROTATION_LANDSCAPE) {
|
||||
rotateSeekBars(row, to, 180);
|
||||
} else {
|
||||
rotateSeekBars(row, to, 90);
|
||||
}
|
||||
rotate(row, from, to, true);
|
||||
}
|
||||
}
|
||||
MarginLayoutParams lp = (MarginLayoutParams) mChild.getLayoutParams();
|
||||
|
||||
private void swapOrientation(LinearLayout layout) {
|
||||
if(layout.getOrientation() == LinearLayout.HORIZONTAL) {
|
||||
layout.setOrientation(LinearLayout.VERTICAL);
|
||||
} else {
|
||||
layout.setOrientation(LinearLayout.HORIZONTAL);
|
||||
}
|
||||
}
|
||||
|
||||
private void swapDimens(View v) {
|
||||
if (v == null) {
|
||||
return;
|
||||
}
|
||||
ViewGroup.LayoutParams params = v.getLayoutParams();
|
||||
int h = params.width;
|
||||
params.width = params.height;
|
||||
params.height = h;
|
||||
v.setLayoutParams(params);
|
||||
}
|
||||
|
||||
private void rotateSeekBars(View row, int to, int rotation) {
|
||||
SeekBar seekbar = row.findViewById(R.id.volume_row_slider);
|
||||
if (seekbar != null) {
|
||||
seekbar.setRotation((float) rotation);
|
||||
}
|
||||
|
||||
View parent = row.findViewById(R.id.volume_row_slider_frame);
|
||||
swapDimens(parent);
|
||||
ViewGroup.LayoutParams params = seekbar.getLayoutParams();
|
||||
ViewGroup.LayoutParams parentParams = parent.getLayoutParams();
|
||||
if (to != ROTATION_NONE) {
|
||||
params.height = parentParams.height;
|
||||
params.width = parentParams.width;
|
||||
} else {
|
||||
params.height = parentParams.width;
|
||||
params.width = parentParams.height;
|
||||
}
|
||||
seekbar.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;
|
||||
int margin = (int) getResources().getDimension(R.dimen.volume_dialog_base_margin);
|
||||
switch (rotation) {
|
||||
/*
|
||||
* Landscape: <-|. Have to deal with the nav bar
|
||||
* Seascape: |->. Have to deal with the cutout
|
||||
*/
|
||||
case RotationUtils.ROTATION_LANDSCAPE:
|
||||
margin += getNavBarHeight();
|
||||
break;
|
||||
case Gravity.RIGHT:
|
||||
retGravity |= Gravity.BOTTOM;
|
||||
case RotationUtils.ROTATION_SEASCAPE:
|
||||
margin += getDisplayCutoutHeight();
|
||||
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;
|
||||
lp.rightMargin = margin;
|
||||
mChild.setLayoutParams(lp);
|
||||
}
|
||||
|
||||
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 int getNavBarHeight() {
|
||||
return (int) getResources().getDimension(R.dimen.navigation_bar_size);
|
||||
}
|
||||
|
||||
private void rotateLeft(View v) {
|
||||
if (v.getParent() instanceof FrameLayout) {
|
||||
LayoutParams p = (LayoutParams) v.getLayoutParams();
|
||||
p.gravity = rotateGravityLeft(p.gravity);
|
||||
//TODO: Find a better way
|
||||
private int getDisplayCutoutHeight() {
|
||||
if (mDisplayCutout == null || mDisplayCutout.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
Rect r = mDisplayCutout.getBoundingRect();
|
||||
return r.bottom - r.top;
|
||||
}
|
||||
|
||||
private void rotateRight(View v) {
|
||||
if (v.getParent() instanceof FrameLayout) {
|
||||
LayoutParams p = (LayoutParams) v.getLayoutParams();
|
||||
p.gravity = rotateGravityRight(p.gravity);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private void animateChild(int oldHeight, int newHeight) {
|
||||
if (true) return;
|
||||
|
||||
Reference in New Issue
Block a user