• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 package com.android.car.settings.quicksettings;
17 
18 import android.annotation.Nullable;
19 import android.content.Context;
20 import android.graphics.drawable.Drawable;
21 import android.support.v7.widget.GridLayoutManager;
22 import android.support.v7.widget.RecyclerView;
23 import android.text.TextUtils;
24 import android.view.LayoutInflater;
25 import android.view.View;
26 import android.view.View.OnClickListener;
27 import android.view.ViewGroup;
28 import android.widget.ImageView;
29 import android.widget.SeekBar;
30 import android.widget.TextView;
31 
32 import com.android.car.settings.R;
33 
34 import java.util.ArrayList;
35 import java.util.List;
36 
37 /**
38  * Controls the content in quick setting grid view.
39  */
40 public class QuickSettingGridAdapter
41         extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements StateChangedListener {
42     private static final int SEEKBAR_VIEWTYPE = 0;
43     private static final int TILE_VIEWTYPE = 1;
44     private final int mColumnCount;
45     private final Context mContext;
46     private final LayoutInflater mInflater;
47     private final List<Tile> mTiles = new ArrayList<>();
48     private final List<SeekbarTile> mSeekbarTiles = new ArrayList<>();
49     private final QsSpanSizeLookup mQsSpanSizeLookup = new QsSpanSizeLookup();
50 
QuickSettingGridAdapter(Context context)51     public QuickSettingGridAdapter(Context context) {
52         mContext = context;
53         mInflater = LayoutInflater.from(context);
54         mColumnCount = mContext.getResources().getInteger(R.integer.quick_setting_column_count);
55     }
56 
getGridLayoutManager()57     GridLayoutManager getGridLayoutManager() {
58         GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext,
59                 mContext.getResources().getInteger(R.integer.quick_setting_column_count));
60         gridLayoutManager.setSpanSizeLookup(mQsSpanSizeLookup);
61         return gridLayoutManager;
62     }
63 
64     /**
65      * Represents an UI tile in the quick setting grid.
66      */
67     interface Tile extends View.OnClickListener {
68 
69         /**
70          * A state to indicate how we want to render icon, this is independent of what to show
71          * in text.
72          */
73         enum State {OFF, ON}
74 
75         /**
76          * Called when activity owning this tile's onStop() gets called.
77          */
stop()78         void stop();
79 
getIcon()80         Drawable getIcon();
81 
82         @Nullable
getText()83         String getText();
84 
getState()85         State getState();
86 
87         /**
88          * Returns {@code true} if this tile should be displayed.
89          */
isAvailable()90         boolean isAvailable();
91 
92         /**
93          * Returns a listener for launching a setting fragment for advanced configuration for this
94          * tile, A.K.A deep dive, if available. {@code null} if deep dive is not available.
95          */
96         @Nullable
getDeepDiveListener()97         OnClickListener getDeepDiveListener();
98     }
99 
100     interface SeekbarTile extends SeekBar.OnSeekBarChangeListener {
101         /**
102          * Called when activity owning this tile's onStop() gets called.
103          */
stop()104         void stop();
105 
getMax()106         int getMax();
107 
getCurrent()108         int getCurrent();
109     }
110 
addSeekbarTile(SeekbarTile seekbarTile)111     QuickSettingGridAdapter addSeekbarTile(SeekbarTile seekbarTile) {
112         mSeekbarTiles.add(seekbarTile);
113         return this;
114     }
115 
addTile(Tile tile)116     QuickSettingGridAdapter addTile(Tile tile) {
117         if (tile.isAvailable()) {
118             mTiles.add(tile);
119         }
120         return this;
121     }
122 
stop()123     void stop() {
124         for (SeekbarTile tile : mSeekbarTiles) {
125             tile.stop();
126         }
127         for (Tile tile : mTiles) {
128             tile.stop();
129         }
130         mTiles.clear();
131         mSeekbarTiles.clear();
132     }
133 
134     @Override
onCreateViewHolder(ViewGroup parent, int viewType)135     public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
136         switch (viewType) {
137             case SEEKBAR_VIEWTYPE:
138                 return new BrightnessViewHolder(mInflater.inflate(
139                         R.layout.brightness_tile, parent, /* attachToRoot= */ false));
140             case TILE_VIEWTYPE:
141                 return new TileViewHolder(mInflater.inflate(
142                         R.layout.tile, parent, /* attachToRoot= */ false));
143             default:
144                 throw new RuntimeException("unknown viewType: " + viewType);
145         }
146     }
147 
148     @Override
onBindViewHolder(RecyclerView.ViewHolder holder, int position)149     public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
150         switch (holder.getItemViewType()) {
151             case SEEKBAR_VIEWTYPE:
152                 SeekbarTile seekbarTile = mSeekbarTiles.get(position);
153                 SeekBar seekbar = ((BrightnessViewHolder) holder).mSeekBar;
154                 seekbar.setMax(seekbarTile.getMax());
155                 seekbar.setProgress(seekbarTile.getCurrent());
156                 seekbar.setOnSeekBarChangeListener(seekbarTile);
157                 break;
158             case TILE_VIEWTYPE:
159                 Tile tile = mTiles.get(position - mSeekbarTiles.size());
160                 TileViewHolder vh = (TileViewHolder) holder;
161                 OnClickListener deepDiveListener = tile.getDeepDiveListener();
162                 vh.itemView.setOnClickListener(tile);
163                 if (deepDiveListener != null) {
164                     vh.mDeepDiveIcon.setVisibility(View.VISIBLE);
165                     vh.mTextContainer.setOnClickListener(deepDiveListener);
166                 } else {
167                     vh.mDeepDiveIcon.setVisibility(View.GONE);
168                     vh.mTextContainer.setClickable(false);
169                     vh.mTextContainer.setOnClickListener(null);
170                 }
171                 vh.mIcon.setImageDrawable(tile.getIcon());
172                 switch (tile.getState()) {
173                     case ON:
174                         vh.mIcon.setEnabled(true);
175                         vh.mIconBackground.setEnabled(true);
176                         break;
177                     case OFF:
178                         vh.mIcon.setEnabled(false);
179                         vh.mIconBackground.setEnabled(false);
180                         break;
181                     default:
182                 }
183                 String textString = tile.getText();
184                 if (!TextUtils.isEmpty(textString)) {
185                     vh.mText.setText(textString);
186                 }
187                 break;
188             default:
189         }
190     }
191 
192     private class BrightnessViewHolder extends RecyclerView.ViewHolder {
193         private final SeekBar mSeekBar;
194 
BrightnessViewHolder(View view)195         BrightnessViewHolder(View view) {
196             super(view);
197             mSeekBar = (SeekBar) view.findViewById(R.id.seekbar);
198         }
199     }
200 
201     private class TileViewHolder extends RecyclerView.ViewHolder {
202         private final View mIconContainer;
203         private final View mTextContainer;
204         private final View mIconBackground;
205         private final ImageView mIcon;
206         private final ImageView mDeepDiveIcon;
207         private final TextView mText;
208 
TileViewHolder(View view)209         TileViewHolder(View view) {
210             super(view);
211             mIconContainer = view.findViewById(R.id.icon_container);
212             mTextContainer = view.findViewById(R.id.text_container);
213             mIconBackground = view.findViewById(R.id.icon_background);
214             mIcon = (ImageView) view.findViewById(R.id.tile_icon);
215             mDeepDiveIcon = (ImageView) view.findViewById(R.id.deep_dive_icon);
216             mText = (TextView) view.findViewById(R.id.tile_text);
217         }
218     }
219 
220     class QsSpanSizeLookup extends GridLayoutManager.SpanSizeLookup {
221 
222         /**
223          * Each line item takes a full row, and each tile takes only 1 span.
224          */
225         @Override
getSpanSize(int position)226         public int getSpanSize(int position) {
227             return position < mSeekbarTiles.size() ? mColumnCount : 1;
228         }
229 
230         @Override
getSpanIndex(int position, int spanCount)231         public int getSpanIndex(int position, int spanCount) {
232             return position < mSeekbarTiles.size()
233                     ? 1 : (position - mSeekbarTiles.size()) % mColumnCount;
234         }
235     }
236 
237     @Override
getItemViewType(int position)238     public int getItemViewType(int position) {
239         return position < mSeekbarTiles.size() ? SEEKBAR_VIEWTYPE : TILE_VIEWTYPE;
240     }
241 
242     @Override
getItemCount()243     public int getItemCount() {
244         return mTiles.size() + mSeekbarTiles.size();
245     }
246 
247     @Override
onStateChanged()248     public void onStateChanged() {
249         notifyDataSetChanged();
250     }
251 }
252