diff --git a/res/layout/panel_slice_slider_row.xml b/res/layout/panel_slice_slider_row.xml new file mode 100644 index 00000000000..f886a85ec8c --- /dev/null +++ b/res/layout/panel_slice_slider_row.xml @@ -0,0 +1,30 @@ + + + + + + \ No newline at end of file diff --git a/res/values/styles.xml b/res/values/styles.xml index 6ffd6df864d..bd89a6178c0 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -512,6 +512,17 @@ ?android:attr/colorBackgroundFloating + + + + diff --git a/src/com/android/settings/panel/MediaOutputGroupPanel.java b/src/com/android/settings/panel/MediaOutputGroupPanel.java index fdac4e797b3..4a37c520824 100644 --- a/src/com/android/settings/panel/MediaOutputGroupPanel.java +++ b/src/com/android/settings/panel/MediaOutputGroupPanel.java @@ -156,4 +156,9 @@ public class MediaOutputGroupPanel implements PanelContent, LocalMediaManager.De public int getMetricsCategory() { return SettingsEnums.PANEL_MEDIA_OUTPUT_GROUP; } + + @Override + public int getViewType() { + return PanelContent.VIEW_TYPE_SLIDER; + } } diff --git a/src/com/android/settings/panel/MediaOutputPanel.java b/src/com/android/settings/panel/MediaOutputPanel.java index 0bb1430b245..1145c428b2f 100644 --- a/src/com/android/settings/panel/MediaOutputPanel.java +++ b/src/com/android/settings/panel/MediaOutputPanel.java @@ -240,4 +240,9 @@ public class MediaOutputPanel implements PanelContent, LocalMediaManager.DeviceC mLocalMediaManager.unregisterCallback(this); mLocalMediaManager.stopScan(); } + + @Override + public int getViewType() { + return PanelContent.VIEW_TYPE_SLIDER; + } } diff --git a/src/com/android/settings/panel/PanelContent.java b/src/com/android/settings/panel/PanelContent.java index 0f60e29a8ca..2e8d709e5c1 100644 --- a/src/com/android/settings/panel/PanelContent.java +++ b/src/com/android/settings/panel/PanelContent.java @@ -30,6 +30,8 @@ import java.util.List; */ public interface PanelContent extends Instrumentable { + int VIEW_TYPE_SLIDER = 1; + /** * @return a icon for the title of the Panel. */ @@ -101,4 +103,11 @@ public interface PanelContent extends Instrumentable { * @param callback the callback to add. */ default void registerCallback(PanelContentCallback callback) {} + + /** + * @return a view type to customized it. 0 for default layout. + */ + default int getViewType() { + return 0; + } } diff --git a/src/com/android/settings/panel/PanelFragment.java b/src/com/android/settings/panel/PanelFragment.java index 0e41421644f..30cc2a8dd6a 100644 --- a/src/com/android/settings/panel/PanelFragment.java +++ b/src/com/android/settings/panel/PanelFragment.java @@ -411,6 +411,10 @@ public class PanelFragment extends Fragment { }; } + int getPanelViewType() { + return mPanel.getViewType(); + } + class LocalPanelCallback implements PanelContentCallback { @Override diff --git a/src/com/android/settings/panel/PanelSlicesAdapter.java b/src/com/android/settings/panel/PanelSlicesAdapter.java index 779c582b5f8..1b69cc269b9 100644 --- a/src/com/android/settings/panel/PanelSlicesAdapter.java +++ b/src/com/android/settings/panel/PanelSlicesAdapter.java @@ -69,7 +69,12 @@ public class PanelSlicesAdapter public SliceRowViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { final Context context = viewGroup.getContext(); final LayoutInflater inflater = LayoutInflater.from(context); - final View view = inflater.inflate(R.layout.panel_slice_row, viewGroup, false); + View view; + if (viewType == PanelContent.VIEW_TYPE_SLIDER) { + view = inflater.inflate(R.layout.panel_slice_slider_row, viewGroup, false); + } else { + view = inflater.inflate(R.layout.panel_slice_row, viewGroup, false); + } return new SliceRowViewHolder(view); } @@ -87,6 +92,11 @@ public class PanelSlicesAdapter return Math.min(mSliceLiveData.size(), MAX_NUM_OF_SLICES); } + @Override + public int getItemViewType(int position) { + return mPanelFragment.getPanelViewType(); + } + /** * Return the available data from the adapter. If the number of Slices over the max number * allowed, the list will only have the first MAX_NUM_OF_SLICES of slices. diff --git a/src/com/android/settings/panel/VolumePanel.java b/src/com/android/settings/panel/VolumePanel.java index dd9b53c8dd1..d45bfd1f5e1 100644 --- a/src/com/android/settings/panel/VolumePanel.java +++ b/src/com/android/settings/panel/VolumePanel.java @@ -73,4 +73,9 @@ public class VolumePanel implements PanelContent { public int getMetricsCategory() { return SettingsEnums.PANEL_VOLUME; } + + @Override + public int getViewType() { + return PanelContent.VIEW_TYPE_SLIDER; + } } \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/panel/FakePanelContent.java b/tests/robotests/src/com/android/settings/panel/FakePanelContent.java index 8888093493a..4d91f52444d 100644 --- a/tests/robotests/src/com/android/settings/panel/FakePanelContent.java +++ b/tests/robotests/src/com/android/settings/panel/FakePanelContent.java @@ -44,6 +44,7 @@ public class FakePanelContent implements PanelContent { private CharSequence mSubTitle; private IconCompat mIcon; + private int mViewType; @Override public IconCompat getIcon() { @@ -82,4 +83,13 @@ public class FakePanelContent implements PanelContent { public int getMetricsCategory() { return SettingsEnums.TESTING; } + + public void setViewType(int viewType) { + mViewType = viewType; + } + + @Override + public int getViewType() { + return mViewType; + } } diff --git a/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java index 37036c48ac6..9e96d0f40cf 100644 --- a/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java +++ b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java @@ -16,19 +16,23 @@ package com.android.settings.panel; +import static com.android.settings.panel.PanelContent.VIEW_TYPE_SLIDER; import static com.android.settings.panel.PanelSlicesAdapter.MAX_NUM_OF_SLICES; import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.net.Uri; +import android.view.LayoutInflater; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -36,23 +40,31 @@ import androidx.lifecycle.LiveData; import androidx.slice.Slice; import com.android.settings.R; +import com.android.settings.panel.PanelSlicesAdapter.SliceRowViewHolder; import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.android.controller.ActivityController; +import org.robolectric.annotation.Config; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; import java.util.LinkedHashMap; import java.util.Map; @RunWith(RobolectricTestRunner.class) +@Config(shadows = PanelSlicesAdapterTest.ShadowLayoutInflater.class) public class PanelSlicesAdapterTest { + private static LayoutInflater sLayoutInflater; + private Context mContext; private PanelFragment mPanelFragment; private PanelFeatureProvider mPanelFeatureProvider; @@ -104,7 +116,7 @@ public class PanelSlicesAdapterTest { final PanelSlicesAdapter adapter = new PanelSlicesAdapter(mPanelFragment, mData, 0 /* metrics category */); final ViewGroup view = new FrameLayout(mContext); - final PanelSlicesAdapter.SliceRowViewHolder viewHolder = + final SliceRowViewHolder viewHolder = adapter.onCreateViewHolder(view, 0); assertThat(adapter.getItemCount()).isEqualTo(MAX_NUM_OF_SLICES); @@ -119,11 +131,52 @@ public class PanelSlicesAdapterTest { new PanelSlicesAdapter(mPanelFragment, mData, 0 /* metrics category */); final int position = 0; final ViewGroup view = new FrameLayout(mContext); - final PanelSlicesAdapter.SliceRowViewHolder viewHolder = + final SliceRowViewHolder viewHolder = adapter.onCreateViewHolder(view, 0 /* view type*/); adapter.onBindViewHolder(viewHolder, position); assertThat(viewHolder.isDividerAllowedAbove()).isFalse(); } + + @Test + public void onCreateViewHolder_viewTypeSlider_verifyLayout() { + final PanelSlicesAdapter adapter = + new PanelSlicesAdapter(mPanelFragment, mData, 0); + final ViewGroup view = new FrameLayout(mContext); + final ArgumentCaptor intArgumentCaptor = ArgumentCaptor.forClass(Integer.class); + + adapter.onCreateViewHolder(view, VIEW_TYPE_SLIDER); + + verify(sLayoutInflater).inflate(intArgumentCaptor.capture(), eq(view), eq(false)); + assertThat(intArgumentCaptor.getValue()).isEqualTo(R.layout.panel_slice_slider_row); + } + + @Test + public void onCreateViewHolder_viewTypeDefault_verifyLayout() { + final PanelSlicesAdapter adapter = + new PanelSlicesAdapter(mPanelFragment, mData, 0); + final ViewGroup view = new FrameLayout(mContext); + final ArgumentCaptor intArgumentCaptor = ArgumentCaptor.forClass(Integer.class); + + adapter.onCreateViewHolder(view, 0); + + verify(sLayoutInflater).inflate(intArgumentCaptor.capture(), eq(view), eq(false)); + assertThat(intArgumentCaptor.getValue()).isEqualTo(R.layout.panel_slice_row); + } + + @Implements(LayoutInflater.class) + public static class ShadowLayoutInflater { + + @Implementation + public static LayoutInflater from(Context context) { + final LayoutInflater inflater = + (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + if (inflater == null) { + throw new AssertionError("LayoutInflater not found."); + } + sLayoutInflater = spy(inflater); + return sLayoutInflater; + } + } }