xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="@android:color/transparent"
android:theme="@style/qs_theme"
android:clipChildren="false" >
- <RelativeLayout
+ <LinearLayout
android:id="@+id/volume_dialog"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingTop="@dimen/volume_row_padding_bottom"
- android:background="@drawable/rounded_full_bg_bottom"
+ android:layout_gravity="center_vertical|end"
+ android:minWidth="@dimen/volume_dialog_panel_width"
+ android:background="@android:color/transparent"
+ android:layout_margin="12dp"
android:translationZ="8dp"
+ android:orientation="vertical"
android:clipChildren="false" >
<LinearLayout
- android:id="@+id/volume_dialog_content"
- android:layout_width="match_parent"
+ android:id="@+id/volume_dialog_rows"
+ android:layout_width="@dimen/volume_dialog_panel_width"
android:layout_height="wrap_content"
- android:layout_toStartOf="@id/expand"
android:clipChildren="false"
android:clipToPadding="false"
- android:orientation="vertical" >
-
- <LinearLayout
- android:id="@+id/volume_dialog_rows"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" >
+ android:paddingTop="12dp"
+ android:paddingBottom="12dp"
+ android:background="@drawable/rounded_bg_full"
+ android:orientation="horizontal" >
<!-- volume rows added and removed here! :-) -->
- </LinearLayout>
-
-
</LinearLayout>
+
<LinearLayout
- android:id="@+id/expand"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_alignParentEnd="true"
- android:layout_alignParentTop="true"
- android:layout_marginEnd="@dimen/volume_expander_margin_end" >
+ android:id="@+id/footer"
+ android:layout_width="@dimen/volume_dialog_panel_width"
+ android:layout_height="@dimen/volume_dialog_panel_width"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ android:layout_below="@id/volume_dialog_rows"
+ android:background="@drawable/rounded_bg_full"
+ android:gravity="center"
+ android:orientation="vertical" >
+
<TextView
+ android:id="@+id/ringer_title"
+ android:text="@string/ring_toggle_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
- android:textAppearance="@style/TextAppearance.Volume.Header" />
- <com.android.keyguard.AlphaOptimizedImageButton
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/volume_expand_button"
- style="@style/VolumeButtons"
- android:layout_width="@dimen/volume_button_size"
- android:layout_height="@dimen/volume_button_size"
- android:clickable="true"
- android:soundEffectsEnabled="false"
- android:src="@drawable/ic_volume_expand_animation"
- android:background="@drawable/ripple_drawable"
- tools:ignore="RtlHardcoded" />
- </LinearLayout>
- <RelativeLayout
- android:id="@+id/footer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:layout_below="@id/volume_dialog_content"
- android:layout_margin="10dp">
- <!-- 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_toStartOf="@id/output_chooser"
- 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/ring_toggle_title"
- 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" />
+ android:layout_centerVertical="true"
+ android:textColor="?android:attr/colorControlNormal"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
- </RelativeLayout>
<com.android.keyguard.AlphaOptimizedImageButton
- android:id="@+id/output_chooser"
+ 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_alignParentEnd="true"
- android:layout_centerVertical="true"
- android:src="@drawable/ic_settings_bluetooth"
+ android:tint="?android:attr/colorAccent"
android:soundEffectsEnabled="false" />
- </RelativeLayout>
- </RelativeLayout>
+
+ <TextView
+ android:id="@+id/ringer_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:textColor="?android:attr/colorControlNormal"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ </LinearLayout>
+ </LinearLayout>
</com.android.systemui.volume.VolumeUiLayout>
\ No newline at end of file
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="@dimen/volume_row_height"
- android:clipChildren="false"
- android:clipToPadding="false"
+ android:tag="row"
+ android:layout_height="wrap_content"
+ android:layout_width="@dimen/volume_dialog_panel_width"
+ android:clipChildren="true"
+ android:clipToPadding="true"
android:theme="@style/qs_theme"
+ android:gravity="center"
android:orientation="vertical" >
- <TextView
- android:id="@+id/volume_row_header"
+ <LinearLayout
+ android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:ellipsize="end"
- android:maxLines="1"
- android:textColor="?android:attr/colorControlNormal"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:paddingStart="@dimen/volume_row_header_padding_start" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="@dimen/volume_row_slider_height"
- android:orientation="horizontal"
- android:paddingStart="@dimen/volume_row_padding_start" >
+ android:gravity="center"
+ android:padding="10dp">
+ <TextView
+ android:id="@+id/volume_row_header"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:textColor="?android:attr/colorControlNormal"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+ <TextView
+ android:id="@+id/volume_row_connected_device"
+ android:visibility="gone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemSecondary" />
<com.android.keyguard.AlphaOptimizedImageButton
- android:id="@+id/volume_row_icon"
- style="@style/VolumeButtons"
- android:layout_width="@dimen/volume_button_size"
- android:layout_height="@dimen/volume_button_size"
- android:soundEffectsEnabled="false" />
-
- <SeekBar
- android:id="@+id/volume_row_slider"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignWithParentIfMissing="true"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:paddingStart="@dimen/volume_row_slider_padding_start"/>
+ android:id="@+id/output_chooser"
+ style="@style/VolumeButtons"
+ android:background="?android:selectableItemBackgroundBorderless"
+ android:layout_width="@dimen/volume_button_size"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:src="@drawable/ic_volume_expand_animation"
+ android:soundEffectsEnabled="false" />
</LinearLayout>
+ <FrameLayout
+ android:id="@+id/volume_row_slider_frame"
+ android:padding="10dp"
+ android:layout_width="@dimen/volume_dialog_panel_width"
+ android:layout_height="150dp">
+ <SeekBar
+ android:id="@+id/volume_row_slider"
+ android:padding="0dp"
+ android:layout_margin="0dp"
+ android:layout_width="150dp"
+ android:layout_height="@dimen/volume_dialog_panel_width"
+ android:layout_gravity="center"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:rotation="270" />
+ </FrameLayout>
- <Space
- android:id="@+id/spacer"
- android:layout_width="match_parent"
- android:layout_height="@dimen/volume_row_padding_bottom"/>
+ <com.android.keyguard.AlphaOptimizedImageButton
+ android:id="@+id/volume_row_icon"
+ style="@style/VolumeButtons"
+ android:padding="10dp"
+ android:layout_width="@dimen/volume_button_size"
+ android:layout_height="@dimen/volume_button_size"
+ android:soundEffectsEnabled="false" />
</LinearLayout>
\ No newline at end of file
<!-- 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">315dp</dimen>
+ <dimen name="volume_dialog_panel_width">120dp</dimen>
<!-- Gravity for the notification panel -->
<integer name="notification_panel_layout_gravity">0x31</integer><!-- center_horizontal|top -->
public static final String VOLUME_UP_SILENT = "sysui_volume_up_silent";
public static final String VOLUME_SILENT_DO_NOT_DISTURB = "sysui_do_not_disturb";
- public static final boolean DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT = true;
+ public static final boolean DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT = false;
public static final boolean DEFAULT_VOLUME_UP_TO_EXIT_SILENT = true;
public static final boolean DEFAULT_DO_NOT_DISTURB_WHEN_SILENT = true;
import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_GENERIC;
import static com.android.systemui.volume.Events.DISMISS_REASON_OUTPUT_CHOOSER;
+import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED;
import static com.android.systemui.volume.Events.DISMISS_REASON_TOUCH_OUTSIDE;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
-import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.os.Debug;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
+import android.provider.Settings;
import android.provider.Settings.Global;
-import android.transition.AutoTransition;
-import android.transition.TransitionManager;
import android.util.Log;
import android.util.Slog;
import android.util.SparseBooleanArray;
import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.plugins.VolumeDialog;
import com.android.systemui.plugins.VolumeDialogController;
private CustomDialog mDialog;
private ViewGroup mDialogView;
private ViewGroup mDialogRowsView;
- private ImageButton mExpandButton;
private ImageButton mRingerIcon;
private ImageButton mOutputChooser;
private TextView mRingerStatus;
private final ColorStateList mInactiveSliderTint;
private boolean mShowing;
- private boolean mExpanded;
- private boolean mExpandButtonAnimationRunning;
private boolean mShowA11yStream;
private int mActiveStream;
mDialog.setContentView(R.layout.volume_dialog);
mDialog.setOnShowListener(dialog -> {
- mDialogView.setTranslationY(-mDialogView.getHeight());
+ mDialogView.setTranslationX(mDialogView.getWidth() / 2);
mDialogView.setAlpha(0);
mDialogView.animate()
.alpha(1)
- .translationY(0)
+ .translationX(0)
.setDuration(300)
.setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator())
.withEndAction(() -> {
VolumeUiLayout hardwareLayout = VolumeUiLayout.get(mDialogView);
hardwareLayout.setOutsideTouchListener(view -> dismiss(DISMISS_REASON_TOUCH_OUTSIDE));
- ViewGroup dialogContentView = mDialog.findViewById(R.id.volume_dialog_content);
- mDialogRowsView = dialogContentView.findViewById(R.id.volume_dialog_rows);
+ mDialogRowsView = mDialog.findViewById(R.id.volume_dialog_rows);
mRingerIcon = mDialog.findViewById(R.id.ringer_icon);
mRingerStatus = mDialog.findViewById(R.id.ringer_status);
- mExpanded = false;
- mExpandButton = mDialogView.findViewById(R.id.volume_expand_button);
- mExpandButton.setOnClickListener(mClickExpand);
- mExpandButton.setVisibility(
- AudioSystem.isSingleVolume(mContext) ? View.GONE : View.VISIBLE);
-
- mOutputChooser = mDialogView.findViewById(R.id.output_chooser);
- mOutputChooser.setOnClickListener(mClickOutputChooser);
-
if (mRows.isEmpty()) {
addRow(AudioManager.STREAM_MUSIC,
R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true, true);
} else {
addExistingRows();
}
+
+ mOutputChooser = mDialogView.findViewById(R.id.output_chooser);
+ mOutputChooser.setOnClickListener(mClickOutputChooser);
+
updateRowsH(getActiveRow());
initRingerH();
}
VolumeRow row = new VolumeRow();
initRow(row, stream, iconRes, iconMuteRes, important, defaultStream);
int rowSize;
- int viewSize;
- if (mShowA11yStream && dynamic && (rowSize = mRows.size()) > 1
- && (viewSize = mDialogRowsView.getChildCount()) > 1) {
- // A11y Stream should be the last in the list
- mDialogRowsView.addView(row.view, viewSize - 2);
+ if (mShowA11yStream && dynamic && (rowSize = mRows.size()) > 1) {
+ // A11y Stream should be the first in the list, so it's shown to start of other rows
+ mDialogRowsView.addView(row.view, 0);
mRows.add(rowSize - 2, row);
} else {
mDialogRowsView.addView(row.view);
public void dump(PrintWriter writer) {
writer.println(VolumeDialogImpl.class.getSimpleName() + " state:");
writer.print(" mShowing: "); writer.println(mShowing);
- writer.print(" mExpanded: "); writer.println(mExpanded);
writer.print(" mActiveStream: "); writer.println(mActiveStream);
writer.print(" mDynamic: "); writer.println(mDynamic);
writer.print(" mAutomute: "); writer.println(mAutomute);
}
updateRingerH();
});
+ mRingerIcon.setOnLongClickListener(v -> {
+ Intent intent = new Intent(Settings.ACTION_SOUND_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ dismissH(DISMISS_REASON_SETTINGS_CLICKED);
+ mContext.startActivity(intent);
+ return true;
+ });
updateRingerH();
}
private int computeTimeoutH() {
if (mAccessibility.mFeedbackEnabled) return 20000;
if (mHovering) return 16000;
- if (mExpanded) return 5000;
if (mSafetyWarning != null) return 5000;
return 3000;
}
mDialogView.animate().cancel();
mShowing = false;
- updateExpandedH(false /* expanding */, true /* dismissing */);
-
- mDialogView.setTranslationY(0);
+ mDialogView.setTranslationX(0);
mDialogView.setAlpha(1);
mDialogView.animate()
.alpha(0)
- .translationY(-mDialogView.getHeight())
+ .translationX(mDialogView.getWidth() / 2)
.setDuration(250)
.setInterpolator(new SystemUIInterpolators.LogAccelerateInterpolator())
.withEndAction(() -> mHandler.postDelayed(() -> {
}
}
- private void updateExpandedH(final boolean expanded, final boolean dismissing) {
- if (D.BUG) Log.d(TAG, "updateExpandedH " + expanded);
-
- if (mExpanded == expanded) return;
- mExpanded = expanded;
- mExpandButtonAnimationRunning = isAttached();
- updateExpandButtonH();
- TransitionManager.endTransitions(mDialogView);
- final VolumeRow activeRow = getActiveRow();
- if (!dismissing) {
- mWindow.setLayout(mWindow.getAttributes().width, ViewGroup.LayoutParams.MATCH_PARENT);
- TransitionManager.beginDelayedTransition(mDialogView, getTransition());
- }
- updateRowsH(activeRow);
- rescheduleTimeoutH();
- }
-
- private AutoTransition getTransition() {
- AutoTransition transition = new AutoTransition();
- transition.setDuration(300);
- transition.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- return transition;
- }
-
- private void updateExpandButtonH() {
- if (D.BUG) Log.d(TAG, "updateExpandButtonH");
-
- mExpandButton.setClickable(!mExpandButtonAnimationRunning);
- if (!(mExpandButtonAnimationRunning && isAttached())) {
- final int res = mExpanded ? R.drawable.ic_volume_collapse_animation
- : R.drawable.ic_volume_expand_animation;
- if (hasTouchFeature()) {
- mExpandButton.setImageResource(res);
- } else {
- // if there is no touch feature, show the volume ringer instead
- mExpandButton.setImageResource(R.drawable.ic_volume_ringer);
- mExpandButton.setBackgroundResource(0); // remove gray background emphasis
- }
- mExpandButton.setContentDescription(mContext.getString(mExpanded ?
- R.string.accessibility_volume_collapse : R.string.accessibility_volume_expand));
- }
- if (mExpandButtonAnimationRunning) {
- final Drawable d = mExpandButton.getDrawable();
- if (d instanceof AnimatedVectorDrawable) {
- // workaround to reset drawable
- final AnimatedVectorDrawable avd = (AnimatedVectorDrawable) d.getConstantState()
- .newDrawable();
- mExpandButton.setImageDrawable(avd);
- avd.start();
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- mExpandButtonAnimationRunning = false;
- updateExpandButtonH();
- rescheduleTimeoutH();
- }
- }, 300);
- }
- }
- }
-
private boolean isAttached() {
return mDialogView != null && mDialogView.isAttachedToWindow();
}
return true;
}
- return row.defaultStream || isActive || (mExpanded && row.important);
+ return row.defaultStream || isActive;
}
private void updateRowsH(final VolumeRow activeRow) {
}
}
- private final OnClickListener mClickExpand = new OnClickListener() {
- @Override
- public void onClick(View v) {
- mExpandButton.animate().cancel();
- final boolean newExpand = !mExpanded;
- Events.writeEvent(mContext, Events.EVENT_EXPAND, newExpand);
- updateExpandedH(newExpand, false /* dismissing */);
- }
- };
-
private final OnClickListener mClickOutputChooser = new OnClickListener() {
@Override
public void onClick(View v) {
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.content.Context;
+import android.content.res.Configuration;
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 android.widget.SeekBar;
+
+import com.android.systemui.R;
+import com.android.systemui.util.leak.RotationUtils;
public class VolumeUiLayout extends FrameLayout {
+ private View mChild;
+ private int mOldHeight;
+ private boolean mAnimating;
+ private AnimatorSet mAnimation;
+ private boolean mHasOutsideTouch;
+ private int mRotation = ROTATION_NONE;
public VolumeUiLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
@Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ if (mChild == null) {
+ if (getChildCount() != 0) {
+ mChild = getChildAt(0);
+ mOldHeight = mChild.getMeasuredHeight();
+ updateRotation();
+ } else {
+ return;
+ }
+ }
+ int newHeight = mChild.getMeasuredHeight();
+ if (newHeight != mOldHeight) {
+ animateChild(mOldHeight, newHeight);
+ }
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updateRotation();
+ }
+
+ private void updateRotation() {
+ int rotation = RotationUtils.getRotation(getContext());
+ if (rotation != mRotation) {
+ rotate(mRotation, 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 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);
+ int rowCount = rows.getChildCount();
+ for (int i = 0; i < rowCount; i++) {
+ View child = rows.getChildAt(i);
+ if (to == ROTATION_SEASCAPE) {
+ rotateSeekBars(to, 0);
+ } else if (to == ROTATION_LANDSCAPE) {
+ rotateSeekBars(to, 180);
+ } else {
+ rotateSeekBars(to, 270);
+ }
+ rotate(child, from, to, true);
+ }
+ }
+
+ 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(int to, int rotation) {
+ SeekBar seekbar = mChild.findViewById(R.id.volume_row_slider);
+ if (seekbar != null) {
+ seekbar.setRotation((float) rotation);
+ }
+
+ View parent = mChild.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;
+ 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 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) {
+ if (v.getParent() instanceof FrameLayout) {
+ LayoutParams p = (LayoutParams) v.getLayoutParams();
+ p.gravity = rotateGravityLeft(p.gravity);
+ }
+
+ 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) {
+ 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;
+ 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);
+ mAnimation.playTogether(top,
+ ObjectAnimator.ofInt(mChild, "bottom", fromBottom, toBottom));
+ }
+
+
+ @Override
public ViewOutlineProvider getOutlineProvider() {
return super.getOutlineProvider();
}
public void setOutsideTouchListener(OnClickListener onClickListener) {
+ mHasOutsideTouch = true;
requestLayout();
setOnClickListener(onClickListener);
setClickable(true);
}
private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener = inoutInfo -> {
+ if (mHasOutsideTouch || (mChild == null)) {
+ inoutInfo.setTouchableInsets(
+ ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
+ return;
+ }
inoutInfo.setTouchableInsets(
- ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
+ ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT);
+ inoutInfo.contentInsets.set(mChild.getLeft(), mChild.getTop(),
+ 0, getBottom() - mChild.getBottom());
};
}