diff options
| author | 2017-12-08 14:13:24 +0000 | |
|---|---|---|
| committer | 2017-12-08 14:13:24 +0000 | |
| commit | 7d37e95d5475dd0575232439ce9bf036a9df2b6d (patch) | |
| tree | be5a780981269ec5294fbaa649091d38433e879d | |
| parent | 0e1209bedf9b93e550084ff1bb71d36c8ff9cfa8 (diff) | |
| parent | 36dd4f1fbe801417ed6cad5f3387ed35923f4a92 (diff) | |
Merge "Move and reshape volume dialog"
4 files changed, 245 insertions, 45 deletions
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml index fac254a0083a..f5637944e72e 100644 --- a/packages/SystemUI/res/layout/volume_dialog.xml +++ b/packages/SystemUI/res/layout/volume_dialog.xml @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. --> -<com.android.systemui.HardwareUiLayout +<com.android.systemui.volume.VolumeUiLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" @@ -21,18 +21,19 @@ android:clipChildren="false" > <RelativeLayout android:id="@+id/volume_dialog" - android:layout_width="@dimen/volume_dialog_panel_width" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_gravity="center_vertical|end" android:paddingTop="@dimen/volume_row_padding_bottom" - android:layout_margin="12dp" - android:background="?android:attr/actionBarItemBackground" - android:translationZ="8dp" > + android:background="@drawable/rounded_full_bg_bottom" + android:translationZ="8dp" + android:clipChildren="false" > <LinearLayout android:id="@+id/volume_dialog_content" android:layout_width="match_parent" android:layout_height="wrap_content" + android:clipChildren="false" + android:clipToPadding="false" android:orientation="vertical" > <LinearLayout @@ -42,7 +43,55 @@ android:orientation="vertical" > <!-- volume rows added and removed here! :-) --> </LinearLayout> - </LinearLayout> + <!-- special row for ringer mode --> + <RelativeLayout + android:id="@+id/ringer_mode" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@drawable/rounded_bg_full" + android:clipChildren="false" + android:clipToPadding="false" + android:layout_margin="10dp"> + + <com.android.keyguard.AlphaOptimizedImageButton + android:id="@+id/ringer_icon" + style="@style/VolumeButtons" + android:background="?android:selectableItemBackgroundBorderless" + android:layout_width="@dimen/volume_button_size" + android:layout_height="@dimen/volume_button_size" + android:layout_alignParentStart="true" + android:layout_centerVertical="true" + android:soundEffectsEnabled="false" /> + + <TextView + android:id="@+id/ringer_title" + android:text="@string/stream_ring" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:maxLines="1" + android:layout_alignParentStart="true" + android:layout_centerVertical="true" + android:layout_toEndOf="@+id/ringer_icon" + android:layout_marginStart="64dp" + android:textColor="?android:attr/colorControlNormal" + android:textAppearance="?android:attr/textAppearanceSmall" + android:paddingStart="@dimen/volume_row_header_padding_start" /> + + <TextView + android:id="@+id/ringer_status" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:layout_alignParentEnd="true" + android:layout_centerVertical="true" + android:layout_marginEnd="14dp" + android:maxLines="1" + android:textColor="?android:attr/colorControlNormal" + android:textAppearance="?android:attr/textAppearanceSmall" /> + + </RelativeLayout> + </LinearLayout> </RelativeLayout> -</com.android.systemui.HardwareUiLayout> +</com.android.systemui.volume.VolumeUiLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 659c5a8b03c0..62ab74d50713 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1248,6 +1248,10 @@ <string name="stream_tts" translatable="false">Transmitted Through Speaker</string> <!-- STREAM_TTS --> <string name="stream_accessibility">Accessibility</string> <!-- STREAM_ACCESSIBILITY --> + <string name="volume_ringer_status_normal">Ring</string> + <string name="volume_ringer_status_vibrate">Vibrate</string> + <string name="volume_ringer_status_silent">Mute</string> + <string name="volume_stream_muted" translatable="false">%s silent</string> <string name="volume_stream_vibrate" translatable="false">%s vibrate</string> <string name="volume_stream_suppressed" translatable="false">%1$s silent — %2$s</string> diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 0d41e2029086..3e70980fdc67 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -30,7 +30,6 @@ import android.app.KeyguardManager; import android.content.Context; import android.content.DialogInterface; import android.content.res.ColorStateList; -import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Color; import android.graphics.Rect; @@ -67,8 +66,6 @@ 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.VolumeDialog; import com.android.systemui.plugins.VolumeDialogController; @@ -97,11 +94,12 @@ public class VolumeDialogImpl implements VolumeDialog { private final VolumeDialogController mController; private Window mWindow; - private HardwareUiLayout mHardwareLayout; private CustomDialog mDialog; private ViewGroup mDialogView; private ViewGroup mDialogRowsView; private ViewGroup mDialogContentView; + private ImageButton mRingerIcon; + private TextView mRingerStatus; private final List<VolumeRow> mRows = new ArrayList<>(); private ConfigurableTexts mConfigurableTexts; private final SparseBooleanArray mDynamic = new SparseBooleanArray(); @@ -111,6 +109,7 @@ public class VolumeDialogImpl implements VolumeDialog { private final Accessibility mAccessibility = new Accessibility(); private final ColorStateList mActiveSliderTint; private final ColorStateList mInactiveSliderTint; + private VolumeUiLayout mHardwareLayout; private boolean mShowing; private boolean mShowA11yStream; @@ -160,17 +159,34 @@ public class VolumeDialogImpl implements VolumeDialog { mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); - mWindow.addFlags( - WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); + mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED + | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH + | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); + mWindow.setTitle(VolumeDialogImpl.class.getSimpleName()); mWindow.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY); mWindow.setWindowAnimations(com.android.internal.R.style.Animation_Toast); mDialog.setContentView(R.layout.volume_dialog); - mDialogView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog); + mDialog.setOnShowListener(new DialogInterface.OnShowListener() { + @Override + public void onShow(DialogInterface dialog) { + mDialogView.setTranslationY(-mDialogView.getHeight()); + mDialogView.setAlpha(0); + mDialogView.animate() + .alpha(1) + .translationY(0) + .setDuration(300) + .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator()) + .withEndAction(() -> { + mWindow.getDecorView().requestAccessibilityFocus(); + }) + .start(); + } + }); + mDialogView = mDialog.findViewById(R.id.volume_dialog); mDialogView.setOnHoverListener(new View.OnHoverListener() { @Override public boolean onHover(View v, MotionEvent event) { @@ -181,18 +197,20 @@ public class VolumeDialogImpl implements VolumeDialog { return true; } }); - mHardwareLayout = HardwareUiLayout.get(mDialogView); + mHardwareLayout = VolumeUiLayout.get(mDialogView); mHardwareLayout.setOutsideTouchListener(view -> dismiss(DISMISS_REASON_TOUCH_OUTSIDE)); mDialogContentView = mDialog.findViewById(R.id.volume_dialog_content); mDialogRowsView = mDialogContentView.findViewById(R.id.volume_dialog_rows); + mRingerIcon = mDialogContentView.findViewById(R.id.ringer_icon); + mRingerStatus = mDialogContentView.findViewById(R.id.ringer_status); if (mRows.isEmpty()) { addRow(AudioManager.STREAM_MUSIC, R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true); if (!AudioSystem.isSingleVolume(mContext)) { addRow(AudioManager.STREAM_RING, - R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true); + R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, false); addRow(AudioManager.STREAM_ALARM, R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, false); addRow(AudioManager.STREAM_VOICE_CALL, @@ -208,6 +226,7 @@ public class VolumeDialogImpl implements VolumeDialog { addExistingRows(); } updateRowsH(getActiveRow()); + initRingerH(); } private ColorStateList loadColorStateList(int colorResId) { @@ -374,6 +393,30 @@ public class VolumeDialogImpl implements VolumeDialog { } } + public void initRingerH() { + mRingerIcon.setOnClickListener(v -> { + Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, AudioManager.STREAM_RING, + mRingerIcon.getTag()); + final StreamState ss = mState.states.get(AudioManager.STREAM_RING); + final boolean hasVibrator = mController.hasVibrator(); + if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) { + if (hasVibrator) { + mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false); + } else { + final boolean wasZero = ss.level == 0; + mController.setStreamVolume(AudioManager.STREAM_RING, wasZero ? 1 : 0); + } + } else { + mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false); + if (ss.level == 0) { + mController.setStreamVolume(AudioManager.STREAM_RING, 1); + } + } + updateRingerH(); + }); + updateRingerH(); + } + public void show(int reason) { mHandler.obtainMessage(H.SHOW, reason, 0).sendToTarget(); } @@ -389,27 +432,12 @@ public class VolumeDialogImpl implements VolumeDialog { rescheduleTimeoutH(); if (mShowing) return; mShowing = true; - mHardwareLayout.setTranslationX(getAnimTranslation()); - mHardwareLayout.setAlpha(0); - mHardwareLayout.animate() - .alpha(1) - .translationX(0) - .setDuration(300) - .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) - .withEndAction(() -> { - mDialog.show(); - mWindow.getDecorView().requestAccessibilityFocus(); - }) - .start(); + + mDialog.show(); Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked()); mController.notifyVisible(true); } - private float getAnimTranslation() { - return mContext.getResources().getDimension( - R.dimen.volume_dialog_panel_width) / 2; - } - protected void rescheduleTimeoutH() { mHandler.removeMessages(H.DISMISS); final int timeout = computeTimeoutH(); @@ -423,7 +451,6 @@ public class VolumeDialogImpl implements VolumeDialog { if (mAccessibility.mFeedbackEnabled) return 20000; if (mHovering) return 16000; if (mSafetyWarning != null) return 5000; - if (mActiveStream == AudioManager.STREAM_MUSIC) return 1500; return 3000; } @@ -431,16 +458,22 @@ public class VolumeDialogImpl implements VolumeDialog { mHandler.removeMessages(H.DISMISS); mHandler.removeMessages(H.SHOW); if (!mShowing) return; + mDialogView.animate().cancel(); mShowing = false; - mHardwareLayout.setTranslationX(0); - mHardwareLayout.setAlpha(1); - mHardwareLayout.animate() + + mDialogView.setTranslationY(0); + mDialogView.setAlpha(1); + mDialogView.animate() .alpha(0) - .translationX(getAnimTranslation()) - .setDuration(300) - .withEndAction(() -> mDialog.dismiss()) + .translationY(-mDialogView.getHeight()) + .setDuration(250) .setInterpolator(new SystemUIInterpolators.LogAccelerateInterpolator()) + .withEndAction(() -> mHandler.postDelayed(() -> { + if (D.BUG) Log.d(TAG, "mDialog.dismiss()"); + mDialog.dismiss(); + }, 50)) .start(); + if (mAccessibilityMgr.isEnabled()) { AccessibilityEvent event = AccessibilityEvent.obtain(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); @@ -493,6 +526,53 @@ public class VolumeDialogImpl implements VolumeDialog { } } + protected void updateRingerH() { + if (mState != null) { + final StreamState ss = mState.states.get(AudioManager.STREAM_RING); + switch (mState.ringerModeInternal) { + case AudioManager.RINGER_MODE_VIBRATE: + mRingerStatus.setText(R.string.volume_ringer_status_vibrate); + mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_vibrate); + mRingerIcon.setTag(Events.ICON_STATE_VIBRATE); + break; + case AudioManager.RINGER_MODE_SILENT: + mRingerStatus.setText(R.string.volume_ringer_status_silent); + mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute); + mRingerIcon.setContentDescription(mContext.getString( + R.string.volume_stream_content_description_unmute, + getStreamLabelH(ss))); + mRingerIcon.setTag(Events.ICON_STATE_MUTE); + break; + case AudioManager.RINGER_MODE_NORMAL: + default: + boolean muted = (mAutomute && ss.level == 0) || ss.muted ? true : false; + if (muted) { + mRingerStatus.setText(R.string.volume_ringer_status_silent); + mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute); + mRingerIcon.setContentDescription(mContext.getString( + R.string.volume_stream_content_description_unmute, + getStreamLabelH(ss))); + mRingerIcon.setTag(Events.ICON_STATE_MUTE); + } else { + mRingerStatus.setText(R.string.volume_ringer_status_normal); + mRingerIcon.setImageResource(R.drawable.ic_volume_ringer); + if (mController.hasVibrator()) { + mRingerIcon.setContentDescription(mContext.getString( + mShowA11yStream + ? R.string.volume_stream_content_description_vibrate_a11y + : R.string.volume_stream_content_description_vibrate, + getStreamLabelH(ss))); + + } else { + mRingerIcon.setContentDescription(getStreamLabelH(ss)); + } + mRingerIcon.setTag(Events.ICON_STATE_UNMUTE); + } + break; + } + } + } + private void trimObsoleteH() { if (D.BUG) Log.d(TAG, "trimObsoleteH"); for (int i = mRows.size() - 1; i >= 0; i--) { @@ -529,6 +609,7 @@ public class VolumeDialogImpl implements VolumeDialog { for (VolumeRow row : mRows) { updateVolumeRowH(row); } + updateRingerH(); } private void updateVolumeRowH(VolumeRow row) { diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java new file mode 100644 index 000000000000..49ac9b6b7ffe --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java @@ -0,0 +1,66 @@ +/* + * 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.volume; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewOutlineProvider; +import android.view.ViewTreeObserver; +import android.widget.FrameLayout; + +public class VolumeUiLayout extends FrameLayout { + + public VolumeUiLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsListener); + } + + @Override + public ViewOutlineProvider getOutlineProvider() { + return super.getOutlineProvider(); + } + + public void setOutsideTouchListener(OnClickListener onClickListener) { + requestLayout(); + setOnClickListener(onClickListener); + setClickable(true); + setFocusable(true); + } + + public static VolumeUiLayout get(View v) { + if (v instanceof VolumeUiLayout) return (VolumeUiLayout) v; + if (v.getParent() instanceof View) { + return get((View) v.getParent()); + } + return null; + } + + private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener = inoutInfo -> { + inoutInfo.setTouchableInsets( + ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME); + }; +} |