DO NOT MERGE: Downbranch merge conflict [Output Switcher] Add animation when init connected
Bug: 203074066 Test: Verified on device Change-Id: Ib40bb575796d077d7fcf89d510087e4fcb0bc00b
This commit is contained in:
@@ -27,7 +27,7 @@
|
|||||||
<clip>
|
<clip>
|
||||||
<shape>
|
<shape>
|
||||||
<corners
|
<corners
|
||||||
android:radius="28dp"/>
|
android:radius="16dp"/>
|
||||||
<size
|
<size
|
||||||
android:height="64dp"/>
|
android:height="64dp"/>
|
||||||
<solid android:color="@color/material_dynamic_primary80" />
|
<solid android:color="@color/material_dynamic_primary80" />
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@drawable/media_output_item_background"
|
android:background="@drawable/media_output_item_background"
|
||||||
android:layout_gravity="center_vertical|start">
|
android:layout_gravity="center_vertical|start">
|
||||||
<SeekBar
|
<com.android.systemui.media.dialog.MediaOutputSeekbar
|
||||||
android:id="@+id/volume_seekbar"
|
android:id="@+id/volume_seekbar"
|
||||||
android:splitTrack="false"
|
android:splitTrack="false"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
|
|||||||
@@ -1125,6 +1125,8 @@
|
|||||||
<dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
|
<dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
|
||||||
<dimen name="media_output_dialog_title_anim_y_delta">12.5dp</dimen>
|
<dimen name="media_output_dialog_title_anim_y_delta">12.5dp</dimen>
|
||||||
<dimen name="media_output_dialog_app_tier_icon_size">20dp</dimen>
|
<dimen name="media_output_dialog_app_tier_icon_size">20dp</dimen>
|
||||||
|
<dimen name="media_output_dialog_background_radius">16dp</dimen>
|
||||||
|
<dimen name="media_output_dialog_active_background_radius">28dp</dimen>
|
||||||
|
|
||||||
<!-- Distance that the full shade transition takes in order to complete by tapping on a button
|
<!-- Distance that the full shade transition takes in order to complete by tapping on a button
|
||||||
like "expand". -->
|
like "expand". -->
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
|||||||
super.onBind(device, topMargin, bottomMargin, position);
|
super.onBind(device, topMargin, bottomMargin, position);
|
||||||
final boolean currentlyConnected = !mIncludeDynamicGroup
|
final boolean currentlyConnected = !mIncludeDynamicGroup
|
||||||
&& isCurrentlyConnected(device);
|
&& isCurrentlyConnected(device);
|
||||||
|
boolean isCurrentSeekbarInvisible = mSeekBar.getVisibility() == View.GONE;
|
||||||
if (currentlyConnected) {
|
if (currentlyConnected) {
|
||||||
mConnectedItem = mContainerLayout;
|
mConnectedItem = mContainerLayout;
|
||||||
}
|
}
|
||||||
@@ -178,7 +179,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
|||||||
mCheckBox.setOnCheckedChangeListener(
|
mCheckBox.setOnCheckedChangeListener(
|
||||||
(buttonView, isChecked) -> onGroupActionTriggered(false, device));
|
(buttonView, isChecked) -> onGroupActionTriggered(false, device));
|
||||||
setCheckBoxColor(mCheckBox, mController.getColorItemContent());
|
setCheckBoxColor(mCheckBox, mController.getColorItemContent());
|
||||||
initSeekbar(device);
|
initSeekbar(device, isCurrentSeekbarInvisible);
|
||||||
mEndTouchArea.setVisibility(View.VISIBLE);
|
mEndTouchArea.setVisibility(View.VISIBLE);
|
||||||
mEndTouchArea.setOnClickListener(null);
|
mEndTouchArea.setOnClickListener(null);
|
||||||
mEndTouchArea.setOnClickListener((v) -> mCheckBox.performClick());
|
mEndTouchArea.setOnClickListener((v) -> mCheckBox.performClick());
|
||||||
@@ -193,7 +194,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
|||||||
setSingleLineLayout(getItemTitle(device), true /* bFocused */,
|
setSingleLineLayout(getItemTitle(device), true /* bFocused */,
|
||||||
true /* showSeekBar */,
|
true /* showSeekBar */,
|
||||||
false /* showProgressBar */, true /* showStatus */);
|
false /* showProgressBar */, true /* showStatus */);
|
||||||
initSeekbar(device);
|
initSeekbar(device, isCurrentSeekbarInvisible);
|
||||||
setUpContentDescriptionForView(mContainerLayout, false, device);
|
setUpContentDescriptionForView(mContainerLayout, false, device);
|
||||||
mCurrentActivePosition = position;
|
mCurrentActivePosition = position;
|
||||||
} else if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
|
} else if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
|
||||||
@@ -257,10 +258,8 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
|||||||
mCurrentActivePosition = -1;
|
mCurrentActivePosition = -1;
|
||||||
mController.connectDevice(device);
|
mController.connectDevice(device);
|
||||||
device.setState(MediaDeviceState.STATE_CONNECTING);
|
device.setState(MediaDeviceState.STATE_CONNECTING);
|
||||||
if (!isAnimating()) {
|
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void setUpContentDescriptionForView(View view, boolean clickable,
|
private void setUpContentDescriptionForView(View view, boolean clickable,
|
||||||
MediaDevice device) {
|
MediaDevice device) {
|
||||||
|
|||||||
@@ -17,18 +17,22 @@
|
|||||||
package com.android.systemui.media.dialog;
|
package com.android.systemui.media.dialog;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.ValueAnimator;
|
||||||
import android.app.WallpaperColors;
|
import android.app.WallpaperColors;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.PorterDuffColorFilter;
|
import android.graphics.PorterDuffColorFilter;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
|
import android.graphics.drawable.ClipDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.drawable.GradientDrawable;
|
||||||
import android.graphics.drawable.Icon;
|
import android.graphics.drawable.Icon;
|
||||||
|
import android.graphics.drawable.LayerDrawable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.animation.LinearInterpolator;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
@@ -44,7 +48,6 @@ import com.android.settingslib.Utils;
|
|||||||
import com.android.settingslib.media.MediaDevice;
|
import com.android.settingslib.media.MediaDevice;
|
||||||
import com.android.settingslib.utils.ThreadUtils;
|
import com.android.settingslib.utils.ThreadUtils;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.animation.Interpolators;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -61,7 +64,6 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
protected final MediaOutputController mController;
|
protected final MediaOutputController mController;
|
||||||
|
|
||||||
private int mMargin;
|
private int mMargin;
|
||||||
private boolean mIsAnimating;
|
|
||||||
|
|
||||||
Context mContext;
|
Context mContext;
|
||||||
View mHolderView;
|
View mHolderView;
|
||||||
@@ -114,10 +116,6 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
return mIsDragging;
|
return mIsDragging;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isAnimating() {
|
|
||||||
return mIsAnimating;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getCurrentActivePosition() {
|
int getCurrentActivePosition() {
|
||||||
return mCurrentActivePosition;
|
return mCurrentActivePosition;
|
||||||
}
|
}
|
||||||
@@ -131,7 +129,7 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
*/
|
*/
|
||||||
abstract class MediaDeviceBaseViewHolder extends RecyclerView.ViewHolder {
|
abstract class MediaDeviceBaseViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
private static final int ANIM_DURATION = 200;
|
private static final int ANIM_DURATION = 500;
|
||||||
|
|
||||||
final LinearLayout mContainerLayout;
|
final LinearLayout mContainerLayout;
|
||||||
final FrameLayout mItemLayout;
|
final FrameLayout mItemLayout;
|
||||||
@@ -140,12 +138,14 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
final TextView mSubTitleText;
|
final TextView mSubTitleText;
|
||||||
final ImageView mTitleIcon;
|
final ImageView mTitleIcon;
|
||||||
final ProgressBar mProgressBar;
|
final ProgressBar mProgressBar;
|
||||||
final SeekBar mSeekBar;
|
final MediaOutputSeekbar mSeekBar;
|
||||||
final LinearLayout mTwoLineLayout;
|
final LinearLayout mTwoLineLayout;
|
||||||
final ImageView mStatusIcon;
|
final ImageView mStatusIcon;
|
||||||
final CheckBox mCheckBox;
|
final CheckBox mCheckBox;
|
||||||
final LinearLayout mEndTouchArea;
|
final LinearLayout mEndTouchArea;
|
||||||
private String mDeviceId;
|
private String mDeviceId;
|
||||||
|
private ValueAnimator mCornerAnimator;
|
||||||
|
private ValueAnimator mVolumeAnimator;
|
||||||
|
|
||||||
MediaDeviceBaseViewHolder(View view) {
|
MediaDeviceBaseViewHolder(View view) {
|
||||||
super(view);
|
super(view);
|
||||||
@@ -161,6 +161,7 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
mStatusIcon = view.requireViewById(R.id.media_output_item_status);
|
mStatusIcon = view.requireViewById(R.id.media_output_item_status);
|
||||||
mCheckBox = view.requireViewById(R.id.check_box);
|
mCheckBox = view.requireViewById(R.id.check_box);
|
||||||
mEndTouchArea = view.requireViewById(R.id.end_action_area);
|
mEndTouchArea = view.requireViewById(R.id.end_action_area);
|
||||||
|
initAnimator();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin, int position) {
|
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin, int position) {
|
||||||
@@ -186,9 +187,11 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
boolean showProgressBar, boolean showStatus) {
|
boolean showProgressBar, boolean showStatus) {
|
||||||
mTwoLineLayout.setVisibility(View.GONE);
|
mTwoLineLayout.setVisibility(View.GONE);
|
||||||
boolean isActive = showSeekBar || showProgressBar;
|
boolean isActive = showSeekBar || showProgressBar;
|
||||||
|
if (!mCornerAnimator.isRunning()) {
|
||||||
final Drawable backgroundDrawable =
|
final Drawable backgroundDrawable =
|
||||||
isActive
|
showSeekBar
|
||||||
? mContext.getDrawable(R.drawable.media_output_item_background_active)
|
? mContext.getDrawable(
|
||||||
|
R.drawable.media_output_item_background_active)
|
||||||
.mutate() : mContext.getDrawable(
|
.mutate() : mContext.getDrawable(
|
||||||
R.drawable.media_output_item_background)
|
R.drawable.media_output_item_background)
|
||||||
.mutate();
|
.mutate();
|
||||||
@@ -197,9 +200,26 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
: mController.getColorItemBackground(),
|
: mController.getColorItemBackground(),
|
||||||
PorterDuff.Mode.SRC_IN));
|
PorterDuff.Mode.SRC_IN));
|
||||||
mItemLayout.setBackground(backgroundDrawable);
|
mItemLayout.setBackground(backgroundDrawable);
|
||||||
|
if (showSeekBar) {
|
||||||
|
final ClipDrawable clipDrawable =
|
||||||
|
(ClipDrawable) ((LayerDrawable) mSeekBar.getProgressDrawable())
|
||||||
|
.findDrawableByLayerId(android.R.id.progress);
|
||||||
|
final GradientDrawable progressDrawable =
|
||||||
|
(GradientDrawable) clipDrawable.getDrawable();
|
||||||
|
progressDrawable.setCornerRadius(mController.getActiveRadius());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mItemLayout.getBackground().setColorFilter(new PorterDuffColorFilter(
|
||||||
|
isActive ? mController.getColorConnectedItemBackground()
|
||||||
|
: mController.getColorItemBackground(),
|
||||||
|
PorterDuff.Mode.SRC_IN));
|
||||||
|
}
|
||||||
mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
|
mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
|
||||||
mSeekBar.setAlpha(1);
|
mSeekBar.setAlpha(1);
|
||||||
mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
|
mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
|
||||||
|
if (!showSeekBar) {
|
||||||
|
mSeekBar.resetVolume();
|
||||||
|
}
|
||||||
mStatusIcon.setVisibility(showStatus ? View.VISIBLE : View.GONE);
|
mStatusIcon.setVisibility(showStatus ? View.VISIBLE : View.GONE);
|
||||||
mTitleText.setText(title);
|
mTitleText.setText(title);
|
||||||
mTitleText.setVisibility(View.VISIBLE);
|
mTitleText.setVisibility(View.VISIBLE);
|
||||||
@@ -257,15 +277,21 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void initSeekbar(MediaDevice device) {
|
void initSeekbar(MediaDevice device, boolean isCurrentSeekbarInvisible) {
|
||||||
if (!mController.isVolumeControlEnabled(device)) {
|
if (!mController.isVolumeControlEnabled(device)) {
|
||||||
disableSeekBar();
|
disableSeekBar();
|
||||||
}
|
}
|
||||||
mSeekBar.setMax(device.getMaxVolume());
|
mSeekBar.setMaxVolume(device.getMaxVolume());
|
||||||
mSeekBar.setMin(0);
|
|
||||||
final int currentVolume = device.getCurrentVolume();
|
final int currentVolume = device.getCurrentVolume();
|
||||||
if (mSeekBar.getProgress() != currentVolume) {
|
if (mSeekBar.getVolume() != currentVolume) {
|
||||||
mSeekBar.setProgress(currentVolume, true);
|
if (isCurrentSeekbarInvisible) {
|
||||||
|
animateCornerAndVolume(mSeekBar.getProgress(),
|
||||||
|
MediaOutputSeekbar.scaleVolumeToProgress(currentVolume));
|
||||||
|
} else {
|
||||||
|
if (!mVolumeAnimator.isStarted()) {
|
||||||
|
mSeekBar.setVolume(currentVolume);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -273,7 +299,11 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
if (device == null || !fromUser) {
|
if (device == null || !fromUser) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mController.adjustVolume(device, progress);
|
int currentVolume = MediaOutputSeekbar.scaleProgressToVolume(progress);
|
||||||
|
int deviceVolume = device.getCurrentVolume();
|
||||||
|
if (currentVolume != deviceVolume) {
|
||||||
|
mController.adjustVolume(device, currentVolume);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -317,63 +347,55 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void playSwitchingAnim(@NonNull View from, @NonNull View to) {
|
private void animateCornerAndVolume(int fromProgress, int toProgress) {
|
||||||
final float delta = (float) (mContext.getResources().getDimensionPixelSize(
|
final GradientDrawable layoutBackgroundDrawable =
|
||||||
R.dimen.media_output_dialog_title_anim_y_delta));
|
(GradientDrawable) mItemLayout.getBackground();
|
||||||
final SeekBar fromSeekBar = from.requireViewById(R.id.volume_seekbar);
|
final ClipDrawable clipDrawable =
|
||||||
final TextView toTitleText = to.requireViewById(R.id.title);
|
(ClipDrawable) ((LayerDrawable) mSeekBar.getProgressDrawable())
|
||||||
if (fromSeekBar.getVisibility() != View.VISIBLE || toTitleText.getVisibility()
|
.findDrawableByLayerId(android.R.id.progress);
|
||||||
!= View.VISIBLE) {
|
final GradientDrawable progressDrawable = (GradientDrawable) clipDrawable.getDrawable();
|
||||||
return;
|
mCornerAnimator.addUpdateListener(animation -> {
|
||||||
}
|
float value = (float) animation.getAnimatedValue();
|
||||||
mIsAnimating = true;
|
layoutBackgroundDrawable.setCornerRadius(value);
|
||||||
// Animation for title text
|
progressDrawable.setCornerRadius(value);
|
||||||
toTitleText.setTypeface(Typeface.create(mContext.getString(
|
|
||||||
com.android.internal.R.string.config_headlineFontFamilyMedium),
|
|
||||||
Typeface.NORMAL));
|
|
||||||
toTitleText.animate()
|
|
||||||
.setDuration(ANIM_DURATION)
|
|
||||||
.translationY(-delta)
|
|
||||||
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
|
|
||||||
.setListener(new AnimatorListenerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation) {
|
|
||||||
to.requireViewById(R.id.volume_indeterminate_progress).setVisibility(
|
|
||||||
View.VISIBLE);
|
|
||||||
// Unset the listener, otherwise this may persist for another view
|
|
||||||
// property animation
|
|
||||||
toTitleText.animate().setListener(null);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
// Animation for seek bar
|
mVolumeAnimator.setIntValues(fromProgress, toProgress);
|
||||||
fromSeekBar.animate()
|
mVolumeAnimator.start();
|
||||||
.alpha(0)
|
mCornerAnimator.start();
|
||||||
.setDuration(ANIM_DURATION)
|
|
||||||
.setListener(new AnimatorListenerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation) {
|
|
||||||
final TextView fromTitleText = from.requireViewById(
|
|
||||||
R.id.two_line_title);
|
|
||||||
fromTitleText.setTypeface(Typeface.create(mContext.getString(
|
|
||||||
com.android.internal.R.string.config_headlineFontFamily),
|
|
||||||
Typeface.NORMAL));
|
|
||||||
fromTitleText.animate()
|
|
||||||
.setDuration(ANIM_DURATION)
|
|
||||||
.translationY(delta)
|
|
||||||
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
|
|
||||||
.setListener(new AnimatorListenerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation) {
|
|
||||||
mIsAnimating = false;
|
|
||||||
notifyDataSetChanged();
|
|
||||||
// Unset the listener, otherwise this may persist for
|
|
||||||
// another view property animation
|
|
||||||
fromTitleText.animate().setListener(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initAnimator() {
|
||||||
|
mCornerAnimator = ValueAnimator.ofFloat(mController.getInactiveRadius(),
|
||||||
|
mController.getActiveRadius());
|
||||||
|
mCornerAnimator.setDuration(ANIM_DURATION);
|
||||||
|
mCornerAnimator.setInterpolator(new LinearInterpolator());
|
||||||
|
|
||||||
|
mVolumeAnimator = ValueAnimator.ofInt();
|
||||||
|
mVolumeAnimator.addUpdateListener(animation -> {
|
||||||
|
int value = (int) animation.getAnimatedValue();
|
||||||
|
mSeekBar.setProgress(value);
|
||||||
});
|
});
|
||||||
// Unset the listener, otherwise this may persist for another view
|
mVolumeAnimator.setDuration(ANIM_DURATION);
|
||||||
// property animation
|
mVolumeAnimator.setInterpolator(new LinearInterpolator());
|
||||||
fromSeekBar.animate().setListener(null);
|
mVolumeAnimator.addListener(new Animator.AnimatorListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animator animation) {
|
||||||
|
mSeekBar.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
mSeekBar.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationCancel(Animator animation) {
|
||||||
|
mSeekBar.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationRepeat(Animator animation) {
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
|
|||||||
mHeaderSubtitle.setText(subTitle);
|
mHeaderSubtitle.setText(subTitle);
|
||||||
mHeaderTitle.setGravity(Gravity.NO_GRAVITY);
|
mHeaderTitle.setGravity(Gravity.NO_GRAVITY);
|
||||||
}
|
}
|
||||||
if (!mAdapter.isDragging() && !mAdapter.isAnimating()) {
|
if (!mAdapter.isDragging()) {
|
||||||
int currentActivePosition = mAdapter.getCurrentActivePosition();
|
int currentActivePosition = mAdapter.getCurrentActivePosition();
|
||||||
if (!colorSetUpdated && !deviceSetChanged && currentActivePosition >= 0
|
if (!colorSetUpdated && !deviceSetChanged && currentActivePosition >= 0
|
||||||
&& currentActivePosition < mAdapter.getItemCount()) {
|
&& currentActivePosition < mAdapter.getItemCount()) {
|
||||||
|
|||||||
@@ -127,6 +127,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
|
|||||||
private int mColorItemBackground;
|
private int mColorItemBackground;
|
||||||
private int mColorConnectedItemBackground;
|
private int mColorConnectedItemBackground;
|
||||||
private int mColorPositiveButtonText;
|
private int mColorPositiveButtonText;
|
||||||
|
private float mInactiveRadius;
|
||||||
|
private float mActiveRadius;
|
||||||
|
|
||||||
public enum BroadcastNotifyDialog {
|
public enum BroadcastNotifyDialog {
|
||||||
ACTION_FIRST_LAUNCH,
|
ACTION_FIRST_LAUNCH,
|
||||||
@@ -163,6 +165,10 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
|
|||||||
R.color.media_dialog_connected_item_background);
|
R.color.media_dialog_connected_item_background);
|
||||||
mColorPositiveButtonText = Utils.getColorStateListDefaultColor(mContext,
|
mColorPositiveButtonText = Utils.getColorStateListDefaultColor(mContext,
|
||||||
R.color.media_dialog_solid_button_text);
|
R.color.media_dialog_solid_button_text);
|
||||||
|
mInactiveRadius = mContext.getResources().getDimension(
|
||||||
|
R.dimen.media_output_dialog_background_radius);
|
||||||
|
mActiveRadius = mContext.getResources().getDimension(
|
||||||
|
R.dimen.media_output_dialog_active_background_radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
void start(@NonNull Callback cb) {
|
void start(@NonNull Callback cb) {
|
||||||
@@ -417,6 +423,14 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
|
|||||||
return mColorItemBackground;
|
return mColorItemBackground;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getInactiveRadius() {
|
||||||
|
return mInactiveRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getActiveRadius() {
|
||||||
|
return mActiveRadius;
|
||||||
|
}
|
||||||
|
|
||||||
private void buildMediaDevices(List<MediaDevice> devices) {
|
private void buildMediaDevices(List<MediaDevice> devices) {
|
||||||
// For the first time building list, to make sure the top device is the connected device.
|
// For the first time building list, to make sure the top device is the connected device.
|
||||||
if (mMediaDevices.isEmpty()) {
|
if (mMediaDevices.isEmpty()) {
|
||||||
|
|||||||
@@ -101,9 +101,10 @@ public class MediaOutputGroupAdapter extends MediaOutputBaseAdapter {
|
|||||||
mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||||
onCheckBoxClicked(isChecked, device);
|
onCheckBoxClicked(isChecked, device);
|
||||||
});
|
});
|
||||||
|
boolean isCurrentSeekbarInvisible = mSeekBar.getVisibility() == View.GONE;
|
||||||
setTwoLineLayout(device, false /* bFocused */, true /* showSeekBar */,
|
setTwoLineLayout(device, false /* bFocused */, true /* showSeekBar */,
|
||||||
false /* showProgressBar */, false /* showSubtitle*/);
|
false /* showProgressBar */, false /* showSubtitle*/);
|
||||||
initSeekbar(device);
|
initSeekbar(device, isCurrentSeekbarInvisible);
|
||||||
final List<MediaDevice> selectedDevices = mController.getSelectedMediaDevice();
|
final List<MediaDevice> selectedDevices = mController.getSelectedMediaDevice();
|
||||||
if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
|
if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
|
||||||
mCheckBox.setButtonDrawable(R.drawable.ic_check_box);
|
mCheckBox.setButtonDrawable(R.drawable.ic_check_box);
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.media.dialog;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.SeekBar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customized SeekBar for MediaOutputDialog, apply scale between device volume and progress, to make
|
||||||
|
* adjustment smoother.
|
||||||
|
*/
|
||||||
|
public class MediaOutputSeekbar extends SeekBar {
|
||||||
|
private static final int SCALE_SIZE = 1000;
|
||||||
|
|
||||||
|
public MediaOutputSeekbar(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setMin(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int scaleProgressToVolume(int progress) {
|
||||||
|
return progress / SCALE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int scaleVolumeToProgress(int volume) {
|
||||||
|
return volume * SCALE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getVolume() {
|
||||||
|
return getProgress() / SCALE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setVolume(int volume) {
|
||||||
|
setProgress(volume * SCALE_SIZE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMaxVolume(int maxVolume) {
|
||||||
|
setMax(maxVolume * SCALE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetVolume() {
|
||||||
|
setProgress(getMin());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -184,26 +184,15 @@ public class MediaOutputGroupAdapterTest extends SysuiTestCase {
|
|||||||
assertThat(mGroupViewHolder.mCheckBox.isEnabled()).isTrue();
|
assertThat(mGroupViewHolder.mCheckBox.isEnabled()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onBindViewHolder_verifySessionVolume() {
|
|
||||||
when(mMediaOutputController.getSessionVolume()).thenReturn(TEST_VOLUME);
|
|
||||||
when(mMediaOutputController.getSessionVolumeMax()).thenReturn(TEST_MAX_VOLUME);
|
|
||||||
|
|
||||||
mGroupAdapter.onBindViewHolder(mGroupViewHolder, 0);
|
|
||||||
|
|
||||||
assertThat(mGroupViewHolder.mSeekBar.getProgress()).isEqualTo(TEST_VOLUME);
|
|
||||||
assertThat(mGroupViewHolder.mSeekBar.getMax()).isEqualTo(TEST_MAX_VOLUME);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onBindViewHolder_verifyDeviceVolume() {
|
public void onBindViewHolder_verifyDeviceVolume() {
|
||||||
when(mMediaDevice1.getCurrentVolume()).thenReturn(TEST_VOLUME);
|
when(mMediaDevice1.getCurrentVolume()).thenReturn(TEST_VOLUME);
|
||||||
when(mMediaDevice1.getMaxVolume()).thenReturn(TEST_MAX_VOLUME);
|
when(mMediaDevice1.getMaxVolume()).thenReturn(TEST_MAX_VOLUME);
|
||||||
|
mGroupViewHolder.mSeekBar.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
mGroupAdapter.onBindViewHolder(mGroupViewHolder, 1);
|
mGroupAdapter.onBindViewHolder(mGroupViewHolder, 1);
|
||||||
|
|
||||||
assertThat(mGroupViewHolder.mSeekBar.getProgress()).isEqualTo(TEST_VOLUME);
|
assertThat(mGroupViewHolder.mSeekBar.getVolume()).isEqualTo(TEST_VOLUME);
|
||||||
assertThat(mGroupViewHolder.mSeekBar.getMax()).isEqualTo(TEST_MAX_VOLUME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user