{Output Switcher} Update ui change

Update layout for Output Switcher, please reference bug for demo screen,
change for output group dialog will be modified in follow up cl.

Bug: 203070747
Bug: 203071939
Test: test on device
Change-Id: Ife2fde23a29504a688b61919fd30071a9c33af7f
This commit is contained in:
shaoweishen
2021-11-05 09:19:07 +00:00
parent bf59fe20e5
commit 42626e0f3f
23 changed files with 372 additions and 121 deletions

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 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.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="28dp" />
<solid android:color="@android:color/transparent" />
<size
android:height="64dp"/>
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners
android:radius="28dp"/>
<size
android:height="64dp"/>
<solid android:color="@*android:color/system_accent1_200" />
</shape>
</clip>
</item>
</layer-list>

View File

@@ -0,0 +1,29 @@
<!--
~ Copyright (C) 2021 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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
<stroke
android:color="@android:color/transparent"
android:width="1dp"/>
<corners android:radius="20dp"/>
<padding
android:left="@dimen/media_output_dialog_button_padding_horizontal"
android:right="@dimen/media_output_dialog_button_padding_horizontal"
android:top="@dimen/media_output_dialog_button_padding_vertical"
android:bottom="@dimen/media_output_dialog_button_padding_vertical" />
<solid android:color="?androidprv:attr/colorAccentPrimaryVariant" />
</shape>

View File

@@ -0,0 +1,23 @@
<!--
~ Copyright (C) 2021 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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
<corners
android:radius="16dp"/>
<solid android:color="?androidprv:attr/colorAccentSecondary" />
</shape>

View File

@@ -0,0 +1,23 @@
<!--
~ Copyright (C) 2021 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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
<corners
android:radius="50dp"/>
<solid android:color="?androidprv:attr/colorAccentSecondary" />
</shape>

View File

@@ -0,0 +1,27 @@
<!--
~ Copyright (C) 2021 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"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="?androidprv:attr/colorAccentPrimaryVariant"
android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
</vector>

View File

@@ -0,0 +1,27 @@
<!--
~ Copyright (C) 2021 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"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="?androidprv:attr/colorAccentPrimaryVariant"
android:pathData="M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
</vector>

View File

@@ -24,24 +24,30 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="96dp"
android:layout_height="wrap_content"
android:gravity="start|center_vertical"
android:paddingStart="16dp"
android:paddingTop="16dp"
android:paddingEnd="16dp"
android:paddingBottom="24dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/header_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_width="72dp"
android:layout_height="72dp"
android:importantForAccessibility="no"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="16dp"
android:paddingTop="20dp"
android:paddingBottom="24dp"
android:paddingEnd="24dp"
android:layout_height="wrap_content"
android:paddingStart="12dp"
android:orientation="vertical">
<ImageView
android:id="@+id/app_source_icon"
android:layout_width="20dp"
android:layout_height="20dp"
android:gravity="center_vertical"
android:importantForAccessibility="no"/>
<TextView
android:id="@+id/header_title"
android:layout_width="wrap_content"
@@ -51,7 +57,7 @@
android:maxLines="1"
android:textColor="?android:attr/textColorPrimary"
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
android:textSize="20sp"/>
android:textSize="16sp"/>
<TextView
android:id="@+id/header_subtitle"
android:layout_width="wrap_content"
@@ -59,17 +65,12 @@
android:gravity="center_vertical"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:attr/textColorTertiary"
android:textColor="?android:attr/textColorSecondary"
android:fontFamily="roboto-regular"
android:textSize="16sp"/>
android:textSize="14sp"/>
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"/>
<LinearLayout
android:id="@+id/device_list"
android:layout_width="match_parent"
@@ -88,10 +89,10 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginStart="24dp"
android:layout_marginBottom="18dp"
android:layout_marginEnd="24dp"
android:layout_marginTop="4dp"
android:layout_marginStart="16dp"
android:layout_marginBottom="24dp"
android:layout_marginEnd="16dp"
android:orientation="horizontal">
<Button
@@ -110,7 +111,7 @@
<Button
android:id="@+id/done"
style="@style/MediaOutputRoundedOutlinedButton"
style="@style/MediaOutputRoundedButton"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:minWidth="0dp"

View File

@@ -17,26 +17,43 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/device_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="88dp"
android:paddingTop="24dp"
android:paddingBottom="16dp"
android:paddingStart="24dp"
android:paddingEnd="8dp">
android:layout_height="64dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="12dp">
<FrameLayout
android:id="@+id/item_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/media_output_item_background"
android:layout_gravity="center_vertical|start">
<SeekBar
android:id="@+id/volume_seekbar"
android:splitTrack="false"
android:visibility="gone"
android:paddingStart="0dp"
android:paddingEnd="0dp"
android:progressDrawable="@drawable/media_output_dialog_seekbar_background"
android:thumb="@null"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
<FrameLayout
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_width="56dp"
android:layout_height="64dp"
android:layout_gravity="center_vertical|start">
<ImageView
android:id="@+id/title_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center"/>
</FrameLayout>
@@ -45,55 +62,46 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|start"
android:layout_marginStart="64dp"
android:layout_marginStart="56dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:attr/textColorPrimary"
android:textColor="?androidprv:attr/colorAccentPrimaryVariant"
android:textSize="16sp"/>
<RelativeLayout
android:id="@+id/two_line_layout"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical|start"
android:layout_height="48dp"
android:layout_marginStart="48dp">
android:layout_marginStart="56dp">
<TextView
android:id="@+id/two_line_title"
android:gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="48dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:attr/textColorPrimary"
android:textColor="?androidprv:attr/colorAccentPrimaryVariant"
android:textSize="16sp"/>
<TextView
android:id="@+id/subtitle"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="15dp"
android:layout_marginTop="4dp"
android:layout_alignParentBottom="true"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:attr/textColorSecondary"
android:textColor="?androidprv:attr/colorAccentPrimaryVariant"
android:textSize="14sp"
android:fontFamily="roboto-regular"
android:visibility="gone"/>
<SeekBar
android:id="@+id/volume_seekbar"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
style="@*android:style/Widget.DeviceDefault.SeekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"/>
<ImageView
android:id="@+id/add_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="right"
android:layout_marginEnd="24dp"
android:layout_marginEnd="16dp"
android:layout_alignParentRight="true"
android:src="@drawable/ic_add"
android:tint="?android:attr/colorAccent"
@@ -103,30 +111,33 @@
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="right"
android:layout_marginEnd="24dp"
android:layout_marginEnd="16dp"
android:layout_alignParentRight="true"
android:button="@drawable/ic_check_box"
android:visibility="gone"
/>
/>
</RelativeLayout>
<ProgressBar
android:id="@+id/volume_indeterminate_progress"
style="@*android:style/Widget.Material.ProgressBar.Horizontal"
android:layout_width="258dp"
android:layout_height="18dp"
android:layout_marginStart="64dp"
android:layout_marginTop="28dp"
style="?android:attr/progressBarStyleSmallTitle"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="16dp"
android:indeterminate="true"
android:layout_gravity="right|center"
android:indeterminateOnly="true"
android:visibility="gone"/>
</FrameLayout>
<View
android:id="@+id/bottom_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="bottom"
android:background="?android:attr/listDivider"
android:visibility="gone"/>
<ImageView
android:id="@+id/media_output_item_status"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="16dp"
android:indeterminate="true"
android:layout_gravity="right|center"
android:indeterminateOnly="true"
android:importantForAccessibility="no"
android:visibility="gone"/>
</FrameLayout>
</LinearLayout>

View File

@@ -16,7 +16,8 @@
* limitations under the License.
*/
-->
<resources xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<drawable name="notification_number_text_color">#ffffffff</drawable>
<drawable name="system_bar_background">@color/system_bar_background_opaque</drawable>
<color name="system_bar_background_opaque">#ff000000</color>

View File

@@ -1085,11 +1085,13 @@
<!-- Output switcher panel related dimensions -->
<dimen name="media_output_dialog_list_margin">12dp</dimen>
<dimen name="media_output_dialog_list_max_height">364dp</dimen>
<dimen name="media_output_dialog_header_album_icon_size">48dp</dimen>
<dimen name="media_output_dialog_header_album_icon_size">72dp</dimen>
<dimen name="media_output_dialog_header_back_icon_size">32dp</dimen>
<dimen name="media_output_dialog_header_icon_padding">16dp</dimen>
<dimen name="media_output_dialog_icon_corner_radius">8dp</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_button_padding_horizontal">16dp</dimen>
<dimen name="media_output_dialog_button_padding_vertical">8dp</dimen>
<!-- Distance that the full shade transition takes in order for qs to fully transition to the
shade -->

View File

@@ -2203,7 +2203,7 @@
<!-- Summary for disconnected status [CHAR LIMIT=50] -->
<string name="media_output_dialog_disconnected">(disconnected)</string>
<!-- Summary for connecting error message [CHAR LIMIT=NONE] -->
<string name="media_output_dialog_connect_failed">Couldn\'t connect. Try again.</string>
<string name="media_output_dialog_connect_failed">Can\'t switch. Tap to try again.</string>
<!-- Title for pairing item [CHAR LIMIT=60] -->
<string name="media_output_dialog_pairing_new">Pair new device</string>

View File

@@ -454,6 +454,12 @@
<item name="android:background">@drawable/media_output_dialog_button_background</item>
</style>
<style name="MediaOutputRoundedButton" parent="@android:style/Widget.Material.Button">
<item name="android:background">@drawable/media_output_dialog_solid_button_background</item>
<item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
<item name="android:textSize">14sp</item>
</style>
<style name="TunerSettings" parent="@android:style/Theme.DeviceDefault.Settings">
<item name="android:windowActionBar">false</item>
<item name="preferenceTheme">@style/TunerPreferenceTheme</item>

View File

@@ -40,6 +40,8 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
private static final String TAG = "MediaOutputAdapter";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final float DEVICE_DISCONNECTED_ALPHA = 0.5f;
private static final float DEVICE_CONNECTED_ALPHA = 1f;
private final MediaOutputDialog mMediaOutputDialog;
private ViewGroup mConnectedItem;
@@ -109,8 +111,8 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
if (currentlyConnected) {
mConnectedItem = mContainerLayout;
}
mBottomDivider.setVisibility(View.GONE);
mCheckBox.setVisibility(View.GONE);
mStatusIcon.setVisibility(View.GONE);
if (currentlyConnected && mController.isActiveRemoteDevice(device)
&& mController.getSelectableMediaDevice().size() > 0) {
// Init active device layout
@@ -124,35 +126,42 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
if (mCurrentActivePosition == position) {
mCurrentActivePosition = -1;
}
if (device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
&& !device.isConnected()) {
mTitleText.setAlpha(DEVICE_DISCONNECTED_ALPHA);
mTitleIcon.setAlpha(DEVICE_DISCONNECTED_ALPHA);
} else {
mTitleText.setAlpha(DEVICE_CONNECTED_ALPHA);
mTitleIcon.setAlpha(DEVICE_CONNECTED_ALPHA);
}
if (mController.isTransferring()) {
if (device.getState() == MediaDeviceState.STATE_CONNECTING
&& !mController.hasAdjustVolumeUserRestriction()) {
setTwoLineLayout(device, true /* bFocused */, false /* showSeekBar*/,
true /* showProgressBar */, false /* showSubtitle */);
setSingleLineLayout(getItemTitle(device), true /* bFocused */,
false /* showSeekBar*/,
true /* showProgressBar */, false /* showStatus */);
} else {
setSingleLineLayout(getItemTitle(device), false /* bFocused */);
}
} else {
// Set different layout for each device
if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
mStatusIcon.setImageDrawable(
mContext.getDrawable(R.drawable.media_output_status_failed));
setTwoLineLayout(device, false /* bFocused */,
false /* showSeekBar */, false /* showProgressBar */,
true /* showSubtitle */);
true /* showSubtitle */, true /* showStatus */);
mSubTitleText.setText(R.string.media_output_dialog_connect_failed);
mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
} else if (!mController.hasAdjustVolumeUserRestriction() && currentlyConnected) {
setTwoLineLayout(device, true /* bFocused */, true /* showSeekBar */,
false /* showProgressBar */, false /* showSubtitle */);
mStatusIcon.setImageDrawable(
mContext.getDrawable(R.drawable.media_output_status_check));
setSingleLineLayout(getItemTitle(device), true /* bFocused */,
true /* showSeekBar */,
false /* showProgressBar */, true /* showStatus */);
initSeekbar(device);
mCurrentActivePosition = position;
} else if (
device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
&& !device.isConnected()) {
setTwoLineLayout(device, false /* bFocused */,
false /* showSeekBar */, false /* showProgressBar */,
true /* showSubtitle */);
mSubTitleText.setText(R.string.media_output_dialog_disconnected);
mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
} else {
setSingleLineLayout(getItemTitle(device), false /* bFocused */);
mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
@@ -165,7 +174,6 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) {
mCheckBox.setVisibility(View.GONE);
mAddIcon.setVisibility(View.GONE);
mBottomDivider.setVisibility(View.GONE);
setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new),
false /* bFocused */);
final Drawable d = mContext.getDrawable(R.drawable.ic_add);
@@ -175,7 +183,6 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
mContainerLayout.setOnClickListener(v -> onItemClick(CUSTOMIZED_ITEM_PAIR_NEW));
} else if (customizedItem == CUSTOMIZED_ITEM_DYNAMIC_GROUP) {
mConnectedItem = mContainerLayout;
mBottomDivider.setVisibility(View.GONE);
mCheckBox.setVisibility(View.GONE);
if (mController.getSelectableMediaDevice().size() > 0) {
mAddIcon.setVisibility(View.VISIBLE);
@@ -200,7 +207,6 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
}
mCurrentActivePosition = -1;
playSwitchingAnim(mConnectedItem, view);
mController.connectDevice(device);
device.setState(MediaDeviceState.STATE_CONNECTING);
if (!isAnimating()) {

View File

@@ -30,6 +30,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
@@ -40,7 +41,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.media.MediaDevice;
import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.R;
@@ -113,6 +113,7 @@ public abstract class MediaOutputBaseAdapter extends
private static final int ANIM_DURATION = 200;
final LinearLayout mContainerLayout;
final FrameLayout mItemLayout;
final TextView mTitleText;
final TextView mTwoLineTitleText;
final TextView mSubTitleText;
@@ -121,13 +122,14 @@ public abstract class MediaOutputBaseAdapter extends
final ProgressBar mProgressBar;
final SeekBar mSeekBar;
final RelativeLayout mTwoLineLayout;
final View mBottomDivider;
final ImageView mStatusIcon;
final CheckBox mCheckBox;
private String mDeviceId;
MediaDeviceBaseViewHolder(View view) {
super(view);
mContainerLayout = view.requireViewById(R.id.device_container);
mItemLayout = view.requireViewById(R.id.item_layout);
mTitleText = view.requireViewById(R.id.title);
mSubTitleText = view.requireViewById(R.id.subtitle);
mTwoLineLayout = view.requireViewById(R.id.two_line_layout);
@@ -135,8 +137,8 @@ public abstract class MediaOutputBaseAdapter extends
mTitleIcon = view.requireViewById(R.id.title_icon);
mProgressBar = view.requireViewById(R.id.volume_indeterminate_progress);
mSeekBar = view.requireViewById(R.id.volume_seekbar);
mBottomDivider = view.requireViewById(R.id.bottom_divider);
mAddIcon = view.requireViewById(R.id.add_icon);
mStatusIcon = view.requireViewById(R.id.media_output_item_status);
mCheckBox = view.requireViewById(R.id.check_box);
}
@@ -156,11 +158,26 @@ public abstract class MediaOutputBaseAdapter extends
abstract void onBind(int customizedItem, boolean topMargin, boolean bottomMargin);
void setSingleLineLayout(CharSequence title, boolean bFocused) {
setSingleLineLayout(title, bFocused, false, false, false);
}
void setSingleLineLayout(CharSequence title, boolean bFocused, boolean showSeekBar,
boolean showProgressBar, boolean showStatus) {
mTwoLineLayout.setVisibility(View.GONE);
mProgressBar.setVisibility(View.GONE);
final Drawable backgroundDrawable =
showSeekBar
? mContext.getDrawable(R.drawable.media_output_item_background_active)
.mutate() : mContext.getDrawable(
R.drawable.media_output_item_background)
.mutate();
mItemLayout.setBackground(backgroundDrawable);
mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
mSeekBar.setAlpha(1);
mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
mStatusIcon.setVisibility(showStatus ? View.VISIBLE : View.GONE);
mTitleText.setText(title);
mTitleText.setVisibility(View.VISIBLE);
mTitleText.setTranslationY(0);
mTitleText.setText(title);
if (bFocused) {
mTitleText.setTypeface(Typeface.create(mContext.getString(
com.android.internal.R.string.config_headlineFontFamilyMedium),
@@ -173,20 +190,32 @@ public abstract class MediaOutputBaseAdapter extends
void setTwoLineLayout(MediaDevice device, boolean bFocused, boolean showSeekBar,
boolean showProgressBar, boolean showSubtitle) {
setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle);
setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle,
false);
}
void setTwoLineLayout(MediaDevice device, boolean bFocused, boolean showSeekBar,
boolean showProgressBar, boolean showSubtitle, boolean showStatus) {
setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle,
showStatus);
}
void setTwoLineLayout(CharSequence title, boolean bFocused, boolean showSeekBar,
boolean showProgressBar, boolean showSubtitle) {
setTwoLineLayout(null, title, bFocused, showSeekBar, showProgressBar, showSubtitle);
setTwoLineLayout(null, title, bFocused, showSeekBar, showProgressBar, showSubtitle,
false);
}
private void setTwoLineLayout(MediaDevice device, CharSequence title, boolean bFocused,
boolean showSeekBar, boolean showProgressBar, boolean showSubtitle) {
boolean showSeekBar, boolean showProgressBar, boolean showSubtitle,
boolean showStatus) {
mTitleText.setVisibility(View.GONE);
mTwoLineLayout.setVisibility(View.VISIBLE);
mStatusIcon.setVisibility(showStatus ? View.VISIBLE : View.GONE);
mSeekBar.setAlpha(1);
mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
mItemLayout.setBackground(mContext.getDrawable(R.drawable.media_output_item_background)
.mutate());
mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
mSubTitleText.setVisibility(showSubtitle ? View.VISIBLE : View.GONE);
mTwoLineTitleText.setTranslationY(0);
@@ -334,7 +363,7 @@ public abstract class MediaOutputBaseAdapter extends
R.color.advanced_icon_color, mContext.getTheme());
drawable.setColorFilter(new PorterDuffColorFilter(list.getDefaultColor(),
PorterDuff.Mode.SRC_IN));
return BluetoothUtils.buildAdvancedDrawable(mContext, drawable);
return drawable;
}
private void disableSeekBar() {

View File

@@ -20,6 +20,7 @@ import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -64,6 +65,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
private TextView mHeaderTitle;
private TextView mHeaderSubtitle;
private ImageView mHeaderIcon;
private ImageView mAppResourceIcon;
private RecyclerView mDevicesRecyclerView;
private LinearLayout mDeviceListLayout;
private Button mDoneButton;
@@ -112,6 +114,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
mDeviceListLayout = mDialogView.requireViewById(R.id.device_list);
mDoneButton = mDialogView.requireViewById(R.id.done);
mStopButton = mDialogView.requireViewById(R.id.stop);
mAppResourceIcon = mDialogView.requireViewById(R.id.app_source_icon);
mDeviceListLayout.getViewTreeObserver().addOnGlobalLayoutListener(
mDeviceListLayoutListener);
@@ -145,6 +148,12 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
// Update header icon
final int iconRes = getHeaderIconRes();
final IconCompat iconCompat = getHeaderIcon();
final Drawable appSourceDrawable = getAppSourceIcon();
if (appSourceDrawable != null) {
mAppResourceIcon.setImageDrawable(appSourceDrawable);
} else {
mAppResourceIcon.setVisibility(View.GONE);
}
if (iconRes != 0) {
mHeaderIcon.setVisibility(View.VISIBLE);
mHeaderIcon.setImageResource(iconRes);
@@ -183,6 +192,8 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
mStopButton.setVisibility(getStopButtonVisibility());
}
abstract Drawable getAppSourceIcon();
abstract int getHeaderIconRes();
abstract IconCompat getHeaderIcon();

View File

@@ -19,6 +19,7 @@ package com.android.systemui.media.dialog;
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
@@ -181,6 +182,20 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
mMetricLogger.logOutputFailure(mMediaDevices, reason);
}
Drawable getAppSourceIcon() {
if (mPackageName.isEmpty()) {
return null;
}
try {
Log.d(TAG, "try to get app icon");
return mContext.getPackageManager()
.getApplicationIcon(mPackageName);
} catch (PackageManager.NameNotFoundException e) {
Log.d(TAG, "icon not found");
return null;
}
}
CharSequence getHeaderTitle() {
if (mMediaController != null) {
final MediaMetadata metadata = mMediaController.getMetadata();

View File

@@ -17,6 +17,7 @@
package com.android.systemui.media.dialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
@@ -78,6 +79,11 @@ public class MediaOutputDialog extends MediaOutputBaseDialog {
return mMediaOutputController.getHeaderSubTitle();
}
@Override
Drawable getAppSourceIcon() {
return mMediaOutputController.getAppSourceIcon();
}
@Override
int getStopButtonVisibility() {
return mMediaOutputController.isActiveRemoteDevice(

View File

@@ -97,7 +97,6 @@ public class MediaOutputGroupAdapter extends MediaOutputBaseAdapter {
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin, int position) {
super.onBind(device, topMargin, bottomMargin, position);
mAddIcon.setVisibility(View.GONE);
mBottomDivider.setVisibility(View.GONE);
mCheckBox.setVisibility(View.VISIBLE);
mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
onCheckBoxClicked(isChecked, device);
@@ -131,7 +130,6 @@ public class MediaOutputGroupAdapter extends MediaOutputBaseAdapter {
true /* bFocused */, true /* showSeekBar */, false /* showProgressBar */,
false /* showSubtitle*/);
mTitleIcon.setImageDrawable(getSpeakerDrawable());
mBottomDivider.setVisibility(View.VISIBLE);
mCheckBox.setVisibility(View.GONE);
mAddIcon.setVisibility(View.GONE);
initSessionSeekbar();

View File

@@ -17,6 +17,7 @@
package com.android.systemui.media.dialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
@@ -28,6 +29,7 @@ import com.android.systemui.R;
/**
* Dialog for media output group.
*/
// TODO(b/203073091): Remove this class once group logic been implemented.
public class MediaOutputGroupDialog extends MediaOutputBaseDialog {
MediaOutputGroupDialog(Context context, boolean aboveStatusbar, MediaOutputController
@@ -75,6 +77,11 @@ public class MediaOutputGroupDialog extends MediaOutputBaseDialog {
return mContext.getString(R.string.media_output_dialog_multiple_devices, size);
}
@Override
Drawable getAppSourceIcon() {
return null;
}
@Override
int getStopButtonVisibility() {
return View.VISIBLE;

View File

@@ -121,7 +121,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getText()).isEqualTo(mContext.getText(
R.string.media_output_dialog_pairing_new));
}
@@ -139,7 +138,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_SESSION_NAME);
}
@@ -156,7 +154,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(mContext.getString(
R.string.media_output_dialog_group));
}
@@ -165,14 +162,13 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
public void onBindViewHolder_bindConnectedDevice_verifyView() {
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_1);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
}
@Test
@@ -199,7 +195,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_2);
}
@@ -213,13 +208,10 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTwoLineTitleText.getText().toString()).isEqualTo(
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(
TEST_DEVICE_NAME_2);
assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(
mContext.getString(R.string.media_output_dialog_disconnected));
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
}
@Test
@@ -233,7 +225,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mSubTitleText.getText()).isEqualTo(mContext.getText(
@@ -248,14 +239,13 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
LocalMediaManager.MediaDeviceState.STATE_CONNECTING);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_1);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
}
@Test
@@ -268,7 +258,6 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
}

View File

@@ -24,6 +24,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.media.session.MediaSessionManager;
import android.os.Bundle;
import android.testing.AndroidTestingRunner;
@@ -70,6 +71,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
private MediaOutputController mMediaOutputController;
private int mHeaderIconRes;
private IconCompat mIconCompat;
private Drawable mAppSourceDrawable;
private CharSequence mHeaderTitle;
private CharSequence mHeaderSubtitle;
@@ -172,6 +174,11 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
mAdapter = mMediaOutputBaseAdapter;
}
@Override
Drawable getAppSourceIcon() {
return mAppSourceDrawable;
}
@Override
int getHeaderIconRes() {
return mHeaderIconRes;

View File

@@ -19,6 +19,7 @@ package com.android.systemui.media.dialog;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -234,7 +235,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
mMediaOutputController.onRequestFailed(0 /* reason */);
verify(mCb).onRouteChanged();
verify(mCb, atLeastOnce()).onRouteChanged();
}
@Test

View File

@@ -100,7 +100,6 @@ public class MediaOutputGroupAdapterTest extends SysuiTestCase {
assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mTwoLineTitleText.getText()).isEqualTo(mContext.getText(
@@ -114,7 +113,6 @@ public class MediaOutputGroupAdapterTest extends SysuiTestCase {
assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -140,7 +138,6 @@ public class MediaOutputGroupAdapterTest extends SysuiTestCase {
assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -165,7 +162,6 @@ public class MediaOutputGroupAdapterTest extends SysuiTestCase {
assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -183,7 +179,6 @@ public class MediaOutputGroupAdapterTest extends SysuiTestCase {
assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);