1 /* 2 * Copyright 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 17 package androidx.slice.builders; 18 19 import static androidx.annotation.RestrictTo.Scope.LIBRARY; 20 21 import android.app.PendingIntent; 22 import android.graphics.drawable.Icon; 23 import android.net.Uri; 24 25 import androidx.annotation.NonNull; 26 import androidx.annotation.Nullable; 27 import androidx.annotation.RequiresApi; 28 import androidx.annotation.RestrictTo; 29 import androidx.core.graphics.drawable.IconCompat; 30 import androidx.core.util.Consumer; 31 import androidx.slice.builders.impl.TemplateBuilderImpl; 32 33 34 /** 35 * Builder to construct a row of slice content in a grid format. 36 * <p> 37 * A grid row is composed of cells, each cell can have a combination of text and images. For more 38 * details see {@link CellBuilder}. 39 * </p> 40 * @deprecated TO BE REMOVED; please use {@link GridRowBuilder} instead. 41 */ 42 @Deprecated 43 public class GridBuilder extends TemplateSliceBuilder { 44 45 private androidx.slice.builders.impl.GridRowBuilder mImpl; 46 private boolean mHasSeeMore; 47 48 /** 49 * Indicates that an image should be presented as an icon and it can be tinted. 50 * 51 * @deprecated use {@link ListBuilder#ICON_IMAGE} 52 */ 53 @Deprecated 54 public static final int ICON_IMAGE = 0; 55 /** 56 * Indicates that an image should be presented in a smaller size and it shouldn't be tinted. 57 * 58 * @deprecated use {@link ListBuilder#SMALL_IMAGE} 59 */ 60 @Deprecated 61 public static final int SMALL_IMAGE = 1; 62 /** 63 * Indicates that an image presented in a larger size and it shouldn't be tinted. 64 * 65 * @deprecated use {@link ListBuilder#LARGE_IMAGE} 66 */ 67 @Deprecated 68 public static final int LARGE_IMAGE = 2; 69 70 /** 71 * Create a builder which will construct a slice displayed in a grid format. 72 * @param parent The builder constructing the parent slice. 73 */ 74 public GridBuilder(@NonNull ListBuilder parent) { 75 super(parent.getImpl().createGridBuilder()); 76 } 77 78 @Override 79 void setImpl(TemplateBuilderImpl impl) { 80 mImpl = (androidx.slice.builders.impl.GridRowBuilder) impl; 81 } 82 83 /** 84 * Add a cell to the grid builder. 85 */ 86 @NonNull 87 public GridBuilder addCell(@NonNull CellBuilder builder) { 88 mImpl.addCell((TemplateBuilderImpl) builder.mImpl); 89 return this; 90 } 91 92 /** 93 * Add a cell to the grid builder. 94 */ 95 @NonNull 96 public GridBuilder addCell(@NonNull Consumer<CellBuilder> c) { 97 CellBuilder b = new CellBuilder(this); 98 c.accept(b); 99 return addCell(b); 100 } 101 102 /** 103 * If all content in a slice cannot be shown, the cell added here may be displayed where the 104 * content is cut off. 105 * <p> 106 * This method should only be used if you want to display a custom cell to indicate more 107 * content, consider using {@link #addSeeMoreAction(PendingIntent)} otherwise. If you do 108 * choose to specify a custom cell, the cell should have 109 * {@link CellBuilder#setContentIntent(PendingIntent)} specified to take the user to an 110 * activity to see all of the content. 111 * </p> 112 * <p> 113 * Only one see more affordance can be added, this throws {@link IllegalStateException} if 114 * a row or action has been previously added. 115 * </p> 116 */ 117 @NonNull 118 public GridBuilder addSeeMoreCell(@NonNull CellBuilder builder) { 119 if (mHasSeeMore) { 120 throw new IllegalStateException("Trying to add see more cell when one has " 121 + "already been added"); 122 } 123 mImpl.setSeeMoreCell((TemplateBuilderImpl) builder.mImpl); 124 mHasSeeMore = true; 125 return this; 126 } 127 128 /** 129 * If all content in a slice cannot be shown, the cell added here may be displayed where the 130 * content is cut off. 131 * <p> 132 * This method should only be used if you want to display a custom cell to indicate more 133 * content, consider using {@link #addSeeMoreAction(PendingIntent)} otherwise. If you do 134 * choose to specify a custom cell, the cell should have 135 * {@link CellBuilder#setContentIntent(PendingIntent)} specified to take the user to an 136 * activity to see all of the content. 137 * </p> 138 * <p> 139 * Only one see more affordance can be added, this throws {@link IllegalStateException} if 140 * a row or action has been previously added. 141 * </p> 142 */ 143 @NonNull 144 public GridBuilder addSeeMoreCell(@NonNull Consumer<CellBuilder> c) { 145 CellBuilder b = new CellBuilder(this); 146 c.accept(b); 147 return addSeeMoreCell(b); 148 } 149 150 /** 151 * If all content in a slice cannot be shown, a "see more" affordance may be displayed where 152 * the content is cut off. The action added here should take the user to an activity to see 153 * all of the content, and will be invoked when the "see more" affordance is tapped. 154 * <p> 155 * Only one see more affordance can be added, this throws {@link IllegalStateException} if 156 * a row or action has been previously added. 157 * </p> 158 */ 159 @NonNull 160 public GridBuilder addSeeMoreAction(@NonNull PendingIntent intent) { 161 if (mHasSeeMore) { 162 throw new IllegalStateException("Trying to add see more action when one has " 163 + "already been added"); 164 } 165 mImpl.setSeeMoreAction(intent); 166 mHasSeeMore = true; 167 return this; 168 } 169 170 /** 171 * Sets the intent to send when the slice is activated. 172 */ 173 @NonNull 174 public GridBuilder setPrimaryAction(@NonNull SliceAction action) { 175 mImpl.setPrimaryAction(action); 176 return this; 177 } 178 179 /** 180 * Sets the content description for the entire grid row. 181 */ 182 @NonNull 183 public GridBuilder setContentDescription(@NonNull CharSequence description) { 184 mImpl.setContentDescription(description); 185 return this; 186 } 187 188 /** 189 * @hide 190 */ 191 @RestrictTo(LIBRARY) 192 public androidx.slice.builders.impl.GridRowBuilder getImpl() { 193 return mImpl; 194 } 195 196 /** 197 * Sub-builder to construct a cell to be displayed in a grid. 198 * <p> 199 * Content added to a cell will be displayed in order vertically, for example the below code 200 * would construct a cell with "First text", and image below it, and then "Second text" below 201 * the image. 202 * 203 * <pre class="prettyprint"> 204 * CellBuilder cb = new CellBuilder(parent, sliceUri); 205 * cb.addText("First text") 206 * .addImage(middleIcon) 207 * .addText("Second text"); 208 * </pre> 209 * 210 * A cell can have at most two text items and one image. 211 * </p> 212 * 213 * @deprecated TO BE REMOVED; please use {@link GridRowBuilder.CellBuilder} instead. 214 */ 215 @Deprecated 216 public static final class CellBuilder extends TemplateSliceBuilder { 217 private androidx.slice.builders.impl.GridRowBuilder.CellBuilder mImpl; 218 219 /** 220 * Create a builder which will construct a slice displayed as a cell in a grid. 221 * @param parent The builder constructing the parent slice. 222 */ 223 public CellBuilder(@NonNull GridBuilder parent) { 224 super(parent.mImpl.createGridRowBuilder()); 225 } 226 227 /** 228 * Create a builder which will construct a slice displayed as a cell in a grid. 229 * @param uri Uri to tag for this slice. 230 */ 231 public CellBuilder(@NonNull GridBuilder parent, @NonNull Uri uri) { 232 super(parent.mImpl.createGridRowBuilder(uri)); 233 } 234 235 @Override 236 void setImpl(TemplateBuilderImpl impl) { 237 mImpl = (androidx.slice.builders.impl.GridRowBuilder.CellBuilder) impl; 238 } 239 240 /** 241 * Adds text to the cell. There can be at most two text items, the first two added 242 * will be used, others will be ignored. 243 */ 244 @NonNull 245 public CellBuilder addText(@NonNull CharSequence text) { 246 return addText(text, false /* isLoading */); 247 } 248 249 /** 250 * Adds text to the cell. There can be at most two text items, the first two added 251 * will be used, others will be ignored. 252 * <p> 253 * Use this method to specify content that will appear in the template once it's been 254 * loaded. 255 * </p> 256 * @param isLoading indicates whether the app is doing work to load the added content in the 257 * background or not. 258 */ 259 @NonNull 260 public CellBuilder addText(@Nullable CharSequence text, boolean isLoading) { 261 mImpl.addText(text, isLoading); 262 return this; 263 } 264 265 /** 266 * Adds text to the cell. Text added with this method will be styled as a title. 267 * There can be at most two text items, the first two added will be used, others 268 * will be ignored. 269 */ 270 @NonNull 271 public CellBuilder addTitleText(@NonNull CharSequence text) { 272 return addTitleText(text, false /* isLoading */); 273 } 274 275 /** 276 * Adds text to the cell. Text added with this method will be styled as a title. 277 * There can be at most two text items, the first two added will be used, others 278 * will be ignored. 279 * <p> 280 * Use this method to specify content that will appear in the template once it's been 281 * loaded. 282 * </p> 283 * @param isLoading indicates whether the app is doing work to load the added content in the 284 * background or not. 285 */ 286 @NonNull 287 public CellBuilder addTitleText(@Nullable CharSequence text, boolean isLoading) { 288 mImpl.addTitleText(text, isLoading); 289 return this; 290 } 291 292 /** 293 * Adds an image to the cell that should be displayed as large as the cell allows. 294 * There can be at most one image, the first one added will be used, others will be ignored. 295 * 296 * @param image the image to display in the cell. 297 */ 298 @NonNull 299 @Deprecated 300 @RequiresApi(23) 301 public CellBuilder addLargeImage(@NonNull Icon image) { 302 return addImage(image, ListBuilder.LARGE_IMAGE, false /* isLoading */); 303 } 304 305 /** 306 * Adds an image to the cell that should be displayed as large as the cell allows. 307 * There can be at most one image, the first one added will be used, others will be ignored. 308 * <p> 309 * Use this method to specify content that will appear in the template once it's been 310 * loaded. 311 * </p> 312 * @param isLoading indicates whether the app is doing work to load the added content in the 313 * background or not. 314 */ 315 @NonNull 316 @Deprecated 317 @RequiresApi(23) 318 public CellBuilder addLargeImage(@Nullable Icon image, boolean isLoading) { 319 return addImage(image, ListBuilder.LARGE_IMAGE, isLoading); 320 } 321 322 /** 323 * Adds an image to the cell. There can be at most one image, the first one added 324 * will be used, others will be ignored. 325 * 326 * @param image the image to display in the cell. 327 */ 328 @NonNull 329 @Deprecated 330 @RequiresApi(23) 331 public CellBuilder addImage(@NonNull Icon image) { 332 return addImage(image, ListBuilder.SMALL_IMAGE, false /* isLoading */); 333 } 334 335 /** 336 * @deprecated TO BE REMOVED 337 */ 338 @NonNull 339 @Deprecated 340 @RequiresApi(23) 341 public CellBuilder addImage(@Nullable Icon image, boolean isLoading) { 342 return addImage(image, ListBuilder.SMALL_IMAGE, isLoading); 343 } 344 345 /** 346 * @deprecated TO BE REMOVED 347 */ 348 @NonNull 349 @Deprecated 350 @RequiresApi(23) 351 public CellBuilder addImage(@NonNull Icon image, @ListBuilder.ImageMode int imageMode) { 352 return addImage(image, imageMode, false /* isLoading */); 353 } 354 355 /** 356 * @deprecated TO BE REMOVED 357 */ 358 @NonNull 359 @Deprecated 360 @RequiresApi(23) 361 public CellBuilder addImage(@Nullable Icon image, @ListBuilder.ImageMode int imageMode, 362 boolean isLoading) { 363 mImpl.addImage(IconCompat.createFromIcon(image), imageMode, isLoading); 364 return this; 365 } 366 367 /** 368 * Adds an image to the cell. There can be at most one image, the first one added will be 369 * used, others will be ignored. 370 * 371 * @param image the image to display in the cell. 372 * @param imageMode the mode that image should be displayed in. 373 * 374 * @see ListBuilder#ICON_IMAGE 375 * @see ListBuilder#SMALL_IMAGE 376 * @see ListBuilder#LARGE_IMAGE 377 */ 378 @NonNull 379 public CellBuilder addImage(@NonNull IconCompat image, 380 @ListBuilder.ImageMode int imageMode) { 381 return addImage(image, imageMode, false /* isLoading */); 382 } 383 384 /** 385 * Adds an image to the cell. There can be at most one image, the first one added will be 386 * used, others will be ignored. 387 * <p> 388 * Use this method to specify content that will appear in the template once it's been 389 * loaded. 390 * </p> 391 * @param image the image to display in the cell. 392 * @param imageMode the mode that image should be displayed in. 393 * @param isLoading indicates whether the app is doing work to load the added content in the 394 * background or not. 395 * 396 * @see ListBuilder#ICON_IMAGE 397 * @see ListBuilder#SMALL_IMAGE 398 * @see ListBuilder#LARGE_IMAGE 399 */ 400 @NonNull 401 public CellBuilder addImage(@Nullable IconCompat image, 402 @ListBuilder.ImageMode int imageMode, 403 boolean isLoading) { 404 mImpl.addImage(image, imageMode, isLoading); 405 return this; 406 } 407 408 /** 409 * Sets the action to be invoked if the user taps on this cell in the row. 410 */ 411 @NonNull 412 public CellBuilder setContentIntent(@NonNull PendingIntent intent) { 413 mImpl.setContentIntent(intent); 414 return this; 415 } 416 417 /** 418 * Sets the content description for this cell. 419 */ 420 @NonNull 421 public CellBuilder setContentDescription(@NonNull CharSequence description) { 422 mImpl.setContentDescription(description); 423 return this; 424 } 425 } 426 } 427