1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.panel; 18 19 import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI; 20 21 import android.app.settings.SettingsEnums; 22 import android.content.Context; 23 import android.view.LayoutInflater; 24 import android.view.View; 25 import android.view.ViewGroup; 26 27 import androidx.annotation.NonNull; 28 import androidx.annotation.VisibleForTesting; 29 import androidx.lifecycle.LiveData; 30 import androidx.recyclerview.widget.RecyclerView; 31 import androidx.slice.Slice; 32 import androidx.slice.widget.SliceView; 33 34 import com.android.settings.R; 35 import com.android.settings.overlay.FeatureFactory; 36 37 import com.google.android.setupdesign.DividerItemDecoration; 38 39 import java.util.ArrayList; 40 import java.util.List; 41 42 /** 43 * RecyclerView adapter for Slices in Settings Panels. 44 */ 45 public class PanelSlicesAdapter 46 extends RecyclerView.Adapter<PanelSlicesAdapter.SliceRowViewHolder> { 47 48 /** 49 * Maximum number of slices allowed on the panel view. 50 */ 51 @VisibleForTesting 52 static final int MAX_NUM_OF_SLICES = 5; 53 54 private final List<LiveData<Slice>> mSliceLiveData; 55 private final int mMetricsCategory; 56 private final PanelFragment mPanelFragment; 57 PanelSlicesAdapter( PanelFragment fragment, List<LiveData<Slice>> sliceLiveData, int metricsCategory)58 public PanelSlicesAdapter( 59 PanelFragment fragment, List<LiveData<Slice>> sliceLiveData, int metricsCategory) { 60 mPanelFragment = fragment; 61 mSliceLiveData = new ArrayList<>(sliceLiveData); 62 mMetricsCategory = metricsCategory; 63 } 64 65 @NonNull 66 @Override onCreateViewHolder(@onNull ViewGroup viewGroup, int viewType)67 public SliceRowViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { 68 final Context context = viewGroup.getContext(); 69 final LayoutInflater inflater = LayoutInflater.from(context); 70 final View view = inflater.inflate(R.layout.panel_slice_row, viewGroup, false); 71 72 return new SliceRowViewHolder(view); 73 } 74 75 @Override onBindViewHolder(@onNull SliceRowViewHolder sliceRowViewHolder, int position)76 public void onBindViewHolder(@NonNull SliceRowViewHolder sliceRowViewHolder, int position) { 77 sliceRowViewHolder.onBind(mSliceLiveData.get(position)); 78 } 79 80 /** 81 * Return the number of available items in the adapter with max number of slices enforced. 82 */ 83 @Override getItemCount()84 public int getItemCount() { 85 return Math.min(mSliceLiveData.size(), MAX_NUM_OF_SLICES); 86 } 87 88 /** 89 * Return the available data from the adapter. If the number of Slices over the max number 90 * allowed, the list will only have the first MAX_NUM_OF_SLICES of slices. 91 */ 92 @VisibleForTesting getData()93 List<LiveData<Slice>> getData() { 94 return mSliceLiveData.subList(0, getItemCount()); 95 } 96 97 /** 98 * ViewHolder for binding Slices to SliceViews. 99 */ 100 public class SliceRowViewHolder extends RecyclerView.ViewHolder 101 implements DividerItemDecoration.DividedViewHolder { 102 103 private boolean mDividerAllowedAbove = true; 104 105 @VisibleForTesting 106 final SliceView sliceView; 107 SliceRowViewHolder(View view)108 public SliceRowViewHolder(View view) { 109 super(view); 110 sliceView = view.findViewById(R.id.slice_view); 111 sliceView.setMode(SliceView.MODE_LARGE); 112 sliceView.showTitleItems(true); 113 } 114 onBind(LiveData<Slice> sliceLiveData)115 public void onBind(LiveData<Slice> sliceLiveData) { 116 sliceLiveData.observe(mPanelFragment.getViewLifecycleOwner(), sliceView); 117 118 // Do not show the divider above media devices switcher slice per request 119 final Slice slice = sliceLiveData.getValue(); 120 if (slice != null && slice.getUri().equals(MEDIA_OUTPUT_INDICATOR_SLICE_URI)) { 121 mDividerAllowedAbove = false; 122 } 123 124 // Log Panel interaction 125 sliceView.setOnSliceActionListener( 126 ((eventInfo, sliceItem) -> { 127 FeatureFactory.getFactory(sliceView.getContext()) 128 .getMetricsFeatureProvider() 129 .action(0 /* attribution */, 130 SettingsEnums.ACTION_PANEL_INTERACTION, 131 mMetricsCategory, 132 sliceLiveData.getValue().getUri().getLastPathSegment() 133 /* log key */, 134 eventInfo.actionType /* value */); 135 }) 136 ); 137 } 138 139 @Override isDividerAllowedAbove()140 public boolean isDividerAllowedAbove() { 141 return mDividerAllowedAbove; 142 } 143 144 @Override isDividerAllowedBelow()145 public boolean isDividerAllowedBelow() { 146 return true; 147 } 148 } 149 } 150