Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit abe29d73 authored by Shaowei Shen's avatar Shaowei Shen Committed by Android (Google) Code Review
Browse files

Merge "DO NOT MERGE: Downbranch merge conflict [Output Switcher] Add animation...

Merge "DO NOT MERGE: Downbranch merge conflict [Output Switcher] Add animation when init connected" into tm-dev
parents d9803be1 de900861
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -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" />
+1 −1
Original line number Original line Diff line number Diff line
@@ -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"
+2 −0
Original line number Original line Diff line number Diff line
@@ -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". -->
+4 −5
Original line number Original line Diff line number Diff line
@@ -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) {
+107 −85
Original line number Original line Diff line number Diff line
@@ -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();
                layoutBackgroundDrawable.setCornerRadius(value);
                progressDrawable.setCornerRadius(value);
            });
            mVolumeAnimator.setIntValues(fromProgress, toProgress);
            mVolumeAnimator.start();
            mCornerAnimator.start();
        }
        }
            mIsAnimating = true;

            // Animation for title text
        private void initAnimator() {
            toTitleText.setTypeface(Typeface.create(mContext.getString(
            mCornerAnimator = ValueAnimator.ofFloat(mController.getInactiveRadius(),
                    com.android.internal.R.string.config_headlineFontFamilyMedium),
                    mController.getActiveRadius());
                    Typeface.NORMAL));
            mCornerAnimator.setDuration(ANIM_DURATION);
            toTitleText.animate()
            mCornerAnimator.setInterpolator(new LinearInterpolator());
                    .setDuration(ANIM_DURATION)

                    .translationY(-delta)
            mVolumeAnimator = ValueAnimator.ofInt();
                    .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
            mVolumeAnimator.addUpdateListener(animation -> {
                    .setListener(new AnimatorListenerAdapter() {
                int value = (int) animation.getAnimatedValue();
                mSeekBar.setProgress(value);
            });
            mVolumeAnimator.setDuration(ANIM_DURATION);
            mVolumeAnimator.setInterpolator(new LinearInterpolator());
            mVolumeAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                @Override
                        public void onAnimationEnd(Animator animation) {
                public void onAnimationStart(Animator animation) {
                            to.requireViewById(R.id.volume_indeterminate_progress).setVisibility(
                    mSeekBar.setEnabled(false);
                                    View.VISIBLE);
                            // Unset the listener, otherwise this may persist for another view
                            // property animation
                            toTitleText.animate().setListener(null);
                }
                }
                    });

            // Animation for seek bar
            fromSeekBar.animate()
                    .alpha(0)
                    .setDuration(ANIM_DURATION)
                    .setListener(new AnimatorListenerAdapter() {
                @Override
                @Override
                public void onAnimationEnd(Animator animation) {
                public void onAnimationEnd(Animator animation) {
                            final TextView fromTitleText = from.requireViewById(
                    mSeekBar.setEnabled(true);
                                    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
                @Override
                                        public void onAnimationEnd(Animator animation) {
                public void onAnimationCancel(Animator animation) {
                                            mIsAnimating = false;
                    mSeekBar.setEnabled(true);
                                            notifyDataSetChanged();
                                            // Unset the listener, otherwise this may persist for
                                            // another view property animation
                                            fromTitleText.animate().setListener(null);
                }
                }
                                    });

                            // Unset the listener, otherwise this may persist for another view
                @Override
                            // property animation
                public void onAnimationRepeat(Animator animation) {
                            fromSeekBar.animate().setListener(null);

                }
                }
            });
            });
        }
        }
Loading