Support arrow down animation

1. No need to use a FrameLayout for PagedListView.
2. Support arrow drop down animation.

BUG: 78474304,73134851
Test: manual

Change-Id: Iec4e046f1abca40d76bd76ab3d5dc2a02e4dfcc2
This commit is contained in:
Lin Guo
2018-04-23 15:19:35 -07:00
parent 13d650d7cf
commit a65cf94800
9 changed files with 330 additions and 60 deletions

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2018, 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together">
<objectAnimator
android:propertyName="rotation"
android:duration="0"
android:valueFrom="180"
android:valueTo="0"
android:interpolator="@android:interpolator/fast_out_slow_in" />
<objectAnimator
android:propertyName="alpha"
android:valueFrom="0.0"
android:valueTo="1.0"
android:valueType="floatType"
android:duration="300"
android:interpolator="@android:interpolator/fast_out_slow_in" />
<objectAnimator
android:propertyName="scaleX"
android:valueFrom="0.8"
android:valueTo="1.0"
android:valueType="floatType"
android:duration="300"
android:interpolator="@android:interpolator/fast_out_slow_in" />
<objectAnimator
android:propertyName="scaleY"
android:valueFrom="0.8"
android:valueTo="1.0"
android:valueType="floatType"
android:duration="300"
android:interpolator="@android:interpolator/fast_out_slow_in" />
</set>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2018, 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together">
<objectAnimator
android:propertyName="rotation"
android:duration="0"
android:valueFrom="0"
android:valueTo="180"
android:interpolator="@android:interpolator/fast_out_slow_in" />
<objectAnimator
android:propertyName="alpha"
android:valueFrom="0.0"
android:valueTo="1.0"
android:valueType="floatType"
android:duration="300"
android:interpolator="@android:interpolator/fast_out_slow_in" />
<objectAnimator
android:propertyName="scaleX"
android:valueFrom="0.8"
android:valueTo="1.0"
android:valueType="floatType"
android:duration="300"
android:interpolator="@android:interpolator/fast_out_slow_in" />
<objectAnimator
android:propertyName="scaleY"
android:valueFrom="0.8"
android:valueTo="1.0"
android:valueType="floatType"
android:duration="300"
android:interpolator="@android:interpolator/fast_out_slow_in" />
</set>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2018, 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together">
<objectAnimator
android:propertyName="alpha"
android:valueFrom="1.0"
android:valueTo="0.0"
android:valueType="floatType"
android:duration="300"
android:interpolator="@android:interpolator/fast_out_slow_in" />
<objectAnimator
android:propertyName="scaleX"
android:valueFrom="1.0"
android:valueTo="0.8"
android:valueType="floatType"
android:duration="300"
android:interpolator="@android:interpolator/fast_out_slow_in" />
<objectAnimator
android:propertyName="scaleY"
android:valueFrom="1.0"
android:valueTo="0.8"
android:valueType="floatType"
android:duration="300"
android:interpolator="@android:interpolator/fast_out_slow_in" />
</set>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~
~ Copyright (C) 2018 Google Inc.
~
~ 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.
~
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="44dp"
android:height="44dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0">
<path
android:pathData="M14.83 16.42L24 25.59l9.17-9.17L36 19.25l-12 12-12-12z"
android:fillColor="#ffffff"/>
</vector>

View File

@@ -0,0 +1,30 @@
<!--
Copyright (C) 2016 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="56dp"
android:height="56dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillAlpha=".1"
android:strokeAlpha=".1"
android:pathData="M0 0h48v48H0z" />
<path
android:fillColor="@color/car_grey_50"
android:pathData="M24 2C14.06 2 6 10.06 6 20v14c0 3.31 2.69 6 6 6h6V24h-8v-4c0-7.73 6.27-14
14-14s14 6.27 14 14v4h-8v16h6c3.31 0 6-2.69 6-6V20c0-9.94-8.06-18-18-18z" />
</vector>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2018 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
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="37dp"
android:viewportWidth="32.0"
android:viewportHeight="37.0">
<path
android:pathData="M16.62,0.61L31.33,35.21C31.55,35.72 31.31,36.3 30.8,36.52C30.48,36.66 30.12,36.62 29.83,36.42L15.7,26.44L1.58,36.42C1.13,36.73 0.5,36.63 0.18,36.18C-0.02,35.89 -0.06,35.53 0.08,35.21L14.78,0.61C15,0.1 15.59,-0.14 16.1,0.08C16.33,0.18 16.52,0.37 16.62,0.61Z"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:fillColor="@color/car_grey_50"
android:strokeWidth="1"/>
</vector>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2018 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
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="38dp"
android:viewportWidth="32"
android:viewportHeight="38" >
<group
android:translateX="-6"
android:translateY="-3">
<path
android:pathData="M26.6195649,6.98115478 C31.5083629,8.85235985 34.9817444,13.6069337 34.9817444,19.1767606 L34.9817444,27.9542254 L38,27.9542254 L38,34.2161972 L6,34.2161972 L6,27.9542254 L9.01825558,27.9542254 L9.01825558,19.1767606 C9.01825558,13.6069337 12.4916371,8.85235985 17.3804351,6.98115478 C17.723241,4.726863 19.6609451,3 22,3 C24.3390549,3 26.276759,4.726863 26.6195649,6.98115478 Z M17.326572,36.3035211 L26.673428,36.3035211 C26.673428,38.8973148 24.581063,41 22,41 C19.418937,41 17.326572,38.8973148 17.326572,36.3035211 Z"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:fillColor="@color/car_grey_50" />
</group>
</vector>

View File

@@ -13,26 +13,19 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<FrameLayout
<androidx.car.widget.PagedListView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/volume_dialog"
android:clipChildren="false"
android:background="@drawable/car_card_rounded_background"
android:id="@+id/volume_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/car_margin"
android:layout_marginEnd="@dimen/car_margin"
android:theme="@style/qs_theme" >
<androidx.car.widget.PagedListView
android:id="@+id/volume_list"
android:background="@drawable/car_rounded_bg_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minWidth="@dimen/volume_dialog_panel_width"
android:theme="?attr/dialogListTheme"
app:dividerStartMargin="@dimen/car_keyline_1"
app:dividerEndMargin="@dimen/car_keyline_1"
app:gutter="none"
app:showPagedListViewDivider="true"
app:scrollBarEnabled="false" />
</FrameLayout>
android:minWidth="@dimen/volume_dialog_panel_width"
android:theme="@style/Theme.Car.NoActionBar"
app:dividerStartMargin="@dimen/car_keyline_1"
app:dividerEndMargin="@dimen/car_keyline_1"
app:gutter="none"
app:showPagedListViewDivider="true"
app:scrollBarEnabled="false" />

View File

@@ -16,6 +16,9 @@
package com.android.systemui.volume;
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorSet;
import android.annotation.Nullable;
import android.app.Dialog;
import android.app.KeyguardManager;
@@ -24,6 +27,7 @@ import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.os.Debug;
@@ -80,7 +84,6 @@ public class CarVolumeDialogImpl implements VolumeDialog {
private Window mWindow;
private CustomDialog mDialog;
private ViewGroup mDialogView;
private PagedListView mListView;
private ListItemAdapter mPagedListAdapter;
private final List<ListItem> mVolumeLineItems = new ArrayList<>();
@@ -99,29 +102,6 @@ public class CarVolumeDialogImpl implements VolumeDialog {
private boolean mHovering = false;
private boolean mExpanded;
private final View.OnClickListener mSupplementalIconListener = v -> {
mExpanded = !mExpanded;
if (mExpanded) {
for (VolumeRow row : mRows) {
// Adding the items which are not coming from default stream.
if (!row.defaultStream) {
addSeekbarListItem(row, null);
}
}
} else {
// Only keeping the default stream if it is not expended.
Iterator itr = mVolumeLineItems.iterator();
while (itr.hasNext()) {
SeekbarListItem item = (SeekbarListItem) itr.next();
VolumeRow row = findRow(item);
if (!row.defaultStream) {
itr.remove();
}
}
}
mPagedListAdapter.notifyDataSetChanged();
};
public CarVolumeDialogImpl(Context context) {
mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
mController = Dependency.get(VolumeDialogController.class);
@@ -175,31 +155,31 @@ public class CarVolumeDialogImpl implements VolumeDialog {
mDialog.setCanceledOnTouchOutside(true);
mDialog.setContentView(R.layout.car_volume_dialog);
mDialog.setOnShowListener(dialog -> {
mDialogView.setTranslationY(-mDialogView.getHeight());
mDialogView.setAlpha(0);
mDialogView.animate()
mListView.setTranslationY(-mListView.getHeight());
mListView.setAlpha(0);
mListView.animate()
.alpha(1)
.translationY(0)
.setDuration(300)
.setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator())
.start();
});
mDialogView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog);
mDialogView.setOnHoverListener((v, event) -> {
mListView = (PagedListView) mWindow.findViewById(R.id.volume_list);
mListView.setOnHoverListener((v, event) -> {
int action = event.getActionMasked();
mHovering = (action == MotionEvent.ACTION_HOVER_ENTER)
|| (action == MotionEvent.ACTION_HOVER_MOVE);
rescheduleTimeoutH();
return true;
});
mListView = (PagedListView) mWindow.findViewById(R.id.volume_list);
// TODO: apply tint to the supplement icon.
addSeekbarListItem(addVolumeRow(AudioManager.STREAM_MUSIC, R.drawable.ic_volume_media,
R.drawable.car_ic_arrow_drop_up, true, true), mSupplementalIconListener);
addVolumeRow(AudioManager.STREAM_RING, R.drawable.ic_volume_ringer, 0,
addSeekbarListItem(addVolumeRow(AudioManager.STREAM_MUSIC, R.drawable.car_ic_music,
R.drawable.car_ic_keyboard_arrow_down, true, true),
new ExpandIconListener());
// We map AudioManager.STREAM_RING to a navigation icon for demo.
addVolumeRow(AudioManager.STREAM_RING, R.drawable.car_ic_navigation, 0,
true, false);
addVolumeRow(AudioManager.STREAM_ALARM, R.drawable.ic_volume_alarm, 0,
addVolumeRow(AudioManager.STREAM_NOTIFICATION, R.drawable.car_ic_notification_2, 0,
true, false);
mPagedListAdapter = new ListItemAdapter(mContext, new ListProvider(mVolumeLineItems),
@@ -248,9 +228,13 @@ public class CarVolumeDialogImpl implements VolumeDialog {
SeekbarListItem listItem =
new SeekbarListItem(mContext, volumeMax, currentVolume,
new VolumeSeekBarChangeListener(volumeRow), null);
listItem.setPrimaryActionIcon(volumeRow.primaryActionIcon);
Drawable primaryIcon = mContext.getResources().getDrawable(volumeRow.primaryActionIcon);
listItem.setPrimaryActionIcon(primaryIcon);
if (volumeRow.supplementalIcon != 0) {
listItem.setSupplementalIcon(volumeRow.supplementalIcon, true, supplementalIconOnClickListener);
Drawable supplementalIcon = mContext.getResources()
.getDrawable(volumeRow.supplementalIcon);
listItem.setSupplementalIcon(supplementalIcon, true,
supplementalIconOnClickListener);
} else {
listItem.setSupplementalEmptyIcon(true);
}
@@ -309,14 +293,14 @@ public class CarVolumeDialogImpl implements VolumeDialog {
mHandler.removeMessages(H.DISMISS);
mHandler.removeMessages(H.SHOW);
if (!mShowing) return;
mDialogView.animate().cancel();
mListView.animate().cancel();
mShowing = false;
mDialogView.setTranslationY(0);
mDialogView.setAlpha(1);
mDialogView.animate()
mListView.setTranslationY(0);
mListView.setAlpha(1);
mListView.animate()
.alpha(0)
.translationY(-mDialogView.getHeight())
.translationY(-mListView.getHeight())
.setDuration(250)
.setInterpolator(new SystemUIInterpolators.LogAccelerateInterpolator())
.withEndAction(() -> mHandler.postDelayed(() -> {
@@ -487,7 +471,7 @@ public class CarVolumeDialogImpl implements VolumeDialog {
@Override
public void onLayoutDirectionChanged(int layoutDirection) {
mDialogView.setLayoutDirection(layoutDirection);
mListView.setLayoutDirection(layoutDirection);
}
@Override
@@ -642,6 +626,45 @@ public class CarVolumeDialogImpl implements VolumeDialog {
}
}
private final class ExpandIconListener implements View.OnClickListener {
@Override
public void onClick(final View v) {
mExpanded = !mExpanded;
Animator inAnimator;
if (mExpanded) {
for (VolumeRow row : mRows) {
// Adding the items which are not coming from default stream.
if (!row.defaultStream) {
addSeekbarListItem(row, null);
}
}
inAnimator = AnimatorInflater.loadAnimator(
mContext, R.anim.car_arrow_fade_in_rotate_up);
} else {
// Only keeping the default stream if it is not expended.
Iterator itr = mVolumeLineItems.iterator();
while (itr.hasNext()) {
SeekbarListItem item = (SeekbarListItem) itr.next();
VolumeRow row = findRow(item);
if (!row.defaultStream) {
itr.remove();
}
}
inAnimator = AnimatorInflater.loadAnimator(
mContext, R.anim.car_arrow_fade_in_rotate_down);
}
Animator outAnimator = AnimatorInflater.loadAnimator(
mContext, R.anim.car_arrow_fade_out);
inAnimator.setStartDelay(100);
AnimatorSet animators = new AnimatorSet();
animators.playTogether(outAnimator, inAnimator);
animators.setTarget(v);
animators.start();
mPagedListAdapter.notifyDataSetChanged();
}
}
private static class VolumeRow {
private int stream;
private StreamState ss;