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 17 package com.example.android.wearable.watchface.config; 18 19 import static com.example.android.wearable.watchface.config.ColorSelectionActivity.EXTRA_SHARED_PREF; 20 21 import android.app.Activity; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.SharedPreferences; 26 import android.graphics.Color; 27 import android.graphics.PorterDuff; 28 import android.graphics.PorterDuffColorFilter; 29 import android.graphics.drawable.Drawable; 30 import android.support.wearable.complications.ComplicationHelperActivity; 31 import android.support.wearable.complications.ComplicationProviderInfo; 32 import android.support.wearable.complications.ProviderInfoRetriever; 33 import android.support.wearable.complications.ProviderInfoRetriever.OnProviderInfoReceivedCallback; 34 import android.util.Log; 35 import android.view.Gravity; 36 import android.view.LayoutInflater; 37 import android.view.View; 38 import android.view.View.OnClickListener; 39 import android.view.ViewGroup; 40 import android.widget.Button; 41 import android.widget.ImageButton; 42 import android.widget.ImageView; 43 import android.widget.Switch; 44 import android.widget.Toast; 45 46 import androidx.annotation.Nullable; 47 import androidx.recyclerview.widget.RecyclerView; 48 49 import com.example.android.wearable.watchface.R; 50 import com.example.android.wearable.watchface.model.AnalogComplicationConfigData.BackgroundComplicationConfigItem; 51 import com.example.android.wearable.watchface.model.AnalogComplicationConfigData.ColorConfigItem; 52 import com.example.android.wearable.watchface.model.AnalogComplicationConfigData.ConfigItemType; 53 import com.example.android.wearable.watchface.model.AnalogComplicationConfigData.MoreOptionsConfigItem; 54 import com.example.android.wearable.watchface.model.AnalogComplicationConfigData.PreviewAndComplicationsConfigItem; 55 import com.example.android.wearable.watchface.model.AnalogComplicationConfigData.UnreadNotificationConfigItem; 56 import com.example.android.wearable.watchface.watchface.AnalogComplicationWatchFaceService; 57 58 import java.util.ArrayList; 59 import java.util.concurrent.Executors; 60 61 /** 62 * Displays different layouts for configuring watch face's complications and appearance settings 63 * (highlight color [second arm], background color, unread notifications, etc.). 64 * 65 * <p>All appearance settings are saved via {@link SharedPreferences}. 66 * 67 * <p>Layouts provided by this adapter are split into 5 main view types. 68 * 69 * <p>A watch face preview including complications. Allows user to tap on the complications to 70 * change the complication data and see a live preview of the watch face. 71 * 72 * <p>Simple arrow to indicate there are more options below the fold. 73 * 74 * <p>Color configuration options for both highlight (seconds hand) and background color. 75 * 76 * <p>Toggle for unread notifications. 77 * 78 * <p>Background image complication configuration for changing background image of watch face. 79 */ 80 public class AnalogComplicationConfigRecyclerViewAdapter 81 extends RecyclerView.Adapter<RecyclerView.ViewHolder> { 82 83 private static final String TAG = "CompConfigAdapter"; 84 85 /** 86 * Used by associated watch face ({@link AnalogComplicationWatchFaceService}) to let this 87 * adapter know which complication locations are supported, their ids, and supported 88 * complication data types. 89 */ 90 public enum ComplicationLocation { 91 BACKGROUND, 92 LEFT, 93 RIGHT, 94 TOP, 95 BOTTOM 96 } 97 98 public static final int TYPE_PREVIEW_AND_COMPLICATIONS_CONFIG = 0; 99 public static final int TYPE_MORE_OPTIONS = 1; 100 public static final int TYPE_COLOR_CONFIG = 2; 101 public static final int TYPE_UNREAD_NOTIFICATION_CONFIG = 3; 102 public static final int TYPE_BACKGROUND_COMPLICATION_IMAGE_CONFIG = 4; 103 104 // ComponentName associated with watch face service (service that renders watch face). Used 105 // to retrieve complication information. 106 private ComponentName mWatchFaceComponentName; 107 108 private ArrayList<ConfigItemType> mSettingsDataSet; 109 110 private Context mContext; 111 112 SharedPreferences mSharedPref; 113 114 // Selected complication id by user. 115 private int mSelectedComplicationId; 116 117 private int mBackgroundComplicationId; 118 private int mLeftComplicationId; 119 private int mRightComplicationId; 120 121 // Required to retrieve complication data from watch face for preview. 122 private ProviderInfoRetriever mProviderInfoRetriever; 123 124 // Maintains reference view holder to dynamically update watch face preview. Used instead of 125 // notifyItemChanged(int position) to avoid flicker and re-inflating the view. 126 private PreviewAndComplicationsViewHolder mPreviewAndComplicationsViewHolder; 127 AnalogComplicationConfigRecyclerViewAdapter( Context context, Class watchFaceServiceClass, ArrayList<ConfigItemType> settingsDataSet)128 public AnalogComplicationConfigRecyclerViewAdapter( 129 Context context, 130 Class watchFaceServiceClass, 131 ArrayList<ConfigItemType> settingsDataSet) { 132 133 mContext = context; 134 mWatchFaceComponentName = new ComponentName(mContext, watchFaceServiceClass); 135 mSettingsDataSet = settingsDataSet; 136 137 // Default value is invalid (only changed when user taps to change complication). 138 mSelectedComplicationId = -1; 139 140 mBackgroundComplicationId = 141 AnalogComplicationWatchFaceService.getComplicationId( 142 ComplicationLocation.BACKGROUND); 143 144 mLeftComplicationId = 145 AnalogComplicationWatchFaceService.getComplicationId(ComplicationLocation.LEFT); 146 mRightComplicationId = 147 AnalogComplicationWatchFaceService.getComplicationId(ComplicationLocation.RIGHT); 148 149 mSharedPref = 150 context.getSharedPreferences( 151 context.getString(R.string.analog_complication_preference_file_key), 152 Context.MODE_PRIVATE); 153 154 // Initialization of code to retrieve active complication data for the watch face. 155 mProviderInfoRetriever = 156 new ProviderInfoRetriever(mContext, Executors.newCachedThreadPool()); 157 mProviderInfoRetriever.init(); 158 } 159 160 @Override onCreateViewHolder(ViewGroup parent, int viewType)161 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 162 Log.d(TAG, "onCreateViewHolder(): viewType: " + viewType); 163 164 RecyclerView.ViewHolder viewHolder = null; 165 166 switch (viewType) { 167 case TYPE_PREVIEW_AND_COMPLICATIONS_CONFIG: 168 // Need direct reference to watch face preview view holder to update watch face 169 // preview based on selections from the user. 170 mPreviewAndComplicationsViewHolder = 171 new PreviewAndComplicationsViewHolder( 172 LayoutInflater.from(parent.getContext()) 173 .inflate( 174 R.layout.config_list_preview_and_complications_item, 175 parent, 176 false)); 177 viewHolder = mPreviewAndComplicationsViewHolder; 178 break; 179 180 case TYPE_MORE_OPTIONS: 181 viewHolder = 182 new MoreOptionsViewHolder( 183 LayoutInflater.from(parent.getContext()) 184 .inflate( 185 R.layout.config_list_more_options_item, 186 parent, 187 false)); 188 break; 189 190 case TYPE_COLOR_CONFIG: 191 viewHolder = 192 new ColorPickerViewHolder( 193 LayoutInflater.from(parent.getContext()) 194 .inflate(R.layout.config_list_color_item, parent, false)); 195 break; 196 197 case TYPE_UNREAD_NOTIFICATION_CONFIG: 198 viewHolder = 199 new UnreadNotificationViewHolder( 200 LayoutInflater.from(parent.getContext()) 201 .inflate( 202 R.layout.config_list_unread_notif_item, 203 parent, 204 false)); 205 break; 206 207 case TYPE_BACKGROUND_COMPLICATION_IMAGE_CONFIG: 208 viewHolder = 209 new BackgroundComplicationViewHolder( 210 LayoutInflater.from(parent.getContext()) 211 .inflate( 212 R.layout.config_list_background_complication_item, 213 parent, 214 false)); 215 break; 216 } 217 218 return viewHolder; 219 } 220 221 @Override onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)222 public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { 223 Log.d(TAG, "Element " + position + " set."); 224 225 // Pulls all data required for creating the UX for the specific setting option. 226 ConfigItemType configItemType = mSettingsDataSet.get(position); 227 228 switch (viewHolder.getItemViewType()) { 229 case TYPE_PREVIEW_AND_COMPLICATIONS_CONFIG: 230 PreviewAndComplicationsViewHolder previewAndComplicationsViewHolder = 231 (PreviewAndComplicationsViewHolder) viewHolder; 232 233 PreviewAndComplicationsConfigItem previewAndComplicationsConfigItem = 234 (PreviewAndComplicationsConfigItem) configItemType; 235 236 int defaultComplicationResourceId = 237 previewAndComplicationsConfigItem.getDefaultComplicationResourceId(); 238 previewAndComplicationsViewHolder.setDefaultComplicationDrawable( 239 defaultComplicationResourceId); 240 241 previewAndComplicationsViewHolder.initializesColorsAndComplications(); 242 break; 243 244 case TYPE_MORE_OPTIONS: 245 MoreOptionsViewHolder moreOptionsViewHolder = (MoreOptionsViewHolder) viewHolder; 246 MoreOptionsConfigItem moreOptionsConfigItem = 247 (MoreOptionsConfigItem) configItemType; 248 249 moreOptionsViewHolder.setIcon(moreOptionsConfigItem.getIconResourceId()); 250 break; 251 252 case TYPE_COLOR_CONFIG: 253 ColorPickerViewHolder colorPickerViewHolder = (ColorPickerViewHolder) viewHolder; 254 ColorConfigItem colorConfigItem = (ColorConfigItem) configItemType; 255 256 int iconResourceId = colorConfigItem.getIconResourceId(); 257 String name = colorConfigItem.getName(); 258 String sharedPrefString = colorConfigItem.getSharedPrefString(); 259 Class<ColorSelectionActivity> activity = 260 colorConfigItem.getActivityToChoosePreference(); 261 262 colorPickerViewHolder.setIcon(iconResourceId); 263 colorPickerViewHolder.setName(name); 264 colorPickerViewHolder.setSharedPrefString(sharedPrefString); 265 colorPickerViewHolder.setLaunchActivityToSelectColor(activity); 266 break; 267 268 case TYPE_UNREAD_NOTIFICATION_CONFIG: 269 UnreadNotificationViewHolder unreadViewHolder = 270 (UnreadNotificationViewHolder) viewHolder; 271 272 UnreadNotificationConfigItem unreadConfigItem = 273 (UnreadNotificationConfigItem) configItemType; 274 275 int unreadEnabledIconResourceId = unreadConfigItem.getIconEnabledResourceId(); 276 int unreadDisabledIconResourceId = unreadConfigItem.getIconDisabledResourceId(); 277 278 String unreadName = unreadConfigItem.getName(); 279 int unreadSharedPrefId = unreadConfigItem.getSharedPrefId(); 280 281 unreadViewHolder.setIcons( 282 unreadEnabledIconResourceId, unreadDisabledIconResourceId); 283 unreadViewHolder.setName(unreadName); 284 unreadViewHolder.setSharedPrefId(unreadSharedPrefId); 285 break; 286 287 case TYPE_BACKGROUND_COMPLICATION_IMAGE_CONFIG: 288 BackgroundComplicationViewHolder backgroundComplicationViewHolder = 289 (BackgroundComplicationViewHolder) viewHolder; 290 291 BackgroundComplicationConfigItem backgroundComplicationConfigItem = 292 (BackgroundComplicationConfigItem) configItemType; 293 294 int backgroundIconResourceId = backgroundComplicationConfigItem.getIconResourceId(); 295 String backgroundName = backgroundComplicationConfigItem.getName(); 296 297 backgroundComplicationViewHolder.setIcon(backgroundIconResourceId); 298 backgroundComplicationViewHolder.setName(backgroundName); 299 break; 300 } 301 } 302 303 @Override getItemViewType(int position)304 public int getItemViewType(int position) { 305 ConfigItemType configItemType = mSettingsDataSet.get(position); 306 return configItemType.getConfigType(); 307 } 308 309 @Override getItemCount()310 public int getItemCount() { 311 return mSettingsDataSet.size(); 312 } 313 314 /** Updates the selected complication id saved earlier with the new information. */ updateSelectedComplication(ComplicationProviderInfo complicationProviderInfo)315 public void updateSelectedComplication(ComplicationProviderInfo complicationProviderInfo) { 316 317 Log.d(TAG, "updateSelectedComplication: " + mPreviewAndComplicationsViewHolder); 318 319 // Checks if view is inflated and complication id is valid. 320 if (mPreviewAndComplicationsViewHolder != null && mSelectedComplicationId >= 0) { 321 mPreviewAndComplicationsViewHolder.updateComplicationViews( 322 mSelectedComplicationId, complicationProviderInfo); 323 } 324 } 325 326 @Override onDetachedFromRecyclerView(RecyclerView recyclerView)327 public void onDetachedFromRecyclerView(RecyclerView recyclerView) { 328 super.onDetachedFromRecyclerView(recyclerView); 329 // Required to release retriever for active complication data on detach. 330 mProviderInfoRetriever.release(); 331 } 332 updatePreviewColors()333 public void updatePreviewColors() { 334 Log.d(TAG, "updatePreviewColors(): " + mPreviewAndComplicationsViewHolder); 335 336 if (mPreviewAndComplicationsViewHolder != null) { 337 mPreviewAndComplicationsViewHolder.updateWatchFaceColors(); 338 } 339 } 340 341 /** 342 * Displays watch face preview along with complication locations. Allows user to tap on the 343 * complication they want to change and preview updates dynamically. 344 */ 345 public class PreviewAndComplicationsViewHolder extends RecyclerView.ViewHolder 346 implements OnClickListener { 347 348 private View mWatchFaceArmsAndTicksView; 349 private View mWatchFaceHighlightPreviewView; 350 private ImageView mWatchFaceBackgroundPreviewImageView; 351 352 private ImageView mLeftComplicationBackground; 353 private ImageView mRightComplicationBackground; 354 355 private ImageButton mLeftComplication; 356 private ImageButton mRightComplication; 357 358 private Drawable mDefaultComplicationDrawable; 359 360 private boolean mBackgroundComplicationEnabled; 361 PreviewAndComplicationsViewHolder(final View view)362 public PreviewAndComplicationsViewHolder(final View view) { 363 super(view); 364 365 mWatchFaceBackgroundPreviewImageView = 366 (ImageView) view.findViewById(R.id.watch_face_background); 367 mWatchFaceArmsAndTicksView = view.findViewById(R.id.watch_face_arms_and_ticks); 368 369 // In our case, just the second arm. 370 mWatchFaceHighlightPreviewView = view.findViewById(R.id.watch_face_highlight); 371 372 // Sets up left complication preview. 373 mLeftComplicationBackground = 374 (ImageView) view.findViewById(R.id.left_complication_background); 375 mLeftComplication = (ImageButton) view.findViewById(R.id.left_complication); 376 mLeftComplication.setOnClickListener(this); 377 378 // Sets up right complication preview. 379 mRightComplicationBackground = 380 (ImageView) view.findViewById(R.id.right_complication_background); 381 mRightComplication = (ImageButton) view.findViewById(R.id.right_complication); 382 mRightComplication.setOnClickListener(this); 383 } 384 385 @Override onClick(View view)386 public void onClick(View view) { 387 if (view.equals(mLeftComplication)) { 388 Log.d(TAG, "Left Complication click()"); 389 390 Activity currentActivity = (Activity) view.getContext(); 391 launchComplicationHelperActivity(currentActivity, ComplicationLocation.LEFT); 392 393 } else if (view.equals(mRightComplication)) { 394 Log.d(TAG, "Right Complication click()"); 395 396 Activity currentActivity = (Activity) view.getContext(); 397 launchComplicationHelperActivity(currentActivity, ComplicationLocation.RIGHT); 398 } 399 } 400 updateWatchFaceColors()401 public void updateWatchFaceColors() { 402 403 // Only update background colors for preview if background complications are disabled. 404 if (!mBackgroundComplicationEnabled) { 405 // Updates background color. 406 String backgroundSharedPrefString = 407 mContext.getString(R.string.saved_background_color); 408 int currentBackgroundColor = 409 mSharedPref.getInt(backgroundSharedPrefString, Color.BLACK); 410 411 PorterDuffColorFilter backgroundColorFilter = 412 new PorterDuffColorFilter(currentBackgroundColor, PorterDuff.Mode.SRC_ATOP); 413 414 mWatchFaceBackgroundPreviewImageView 415 .getBackground() 416 .setColorFilter(backgroundColorFilter); 417 418 } else { 419 // Inform user that they need to disable background image for color to work. 420 CharSequence text = "Selected image overrides background color."; 421 int duration = Toast.LENGTH_SHORT; 422 Toast toast = Toast.makeText(mContext, text, duration); 423 toast.setGravity(Gravity.CENTER, 0, 0); 424 toast.show(); 425 } 426 427 // Updates highlight color (just second arm). 428 String highlightSharedPrefString = mContext.getString(R.string.saved_marker_color); 429 int currentHighlightColor = mSharedPref.getInt(highlightSharedPrefString, Color.RED); 430 431 PorterDuffColorFilter highlightColorFilter = 432 new PorterDuffColorFilter(currentHighlightColor, PorterDuff.Mode.SRC_ATOP); 433 434 mWatchFaceHighlightPreviewView.getBackground().setColorFilter(highlightColorFilter); 435 } 436 437 // Verifies the watch face supports the complication location, then launches the helper 438 // class, so user can choose their complication data provider. launchComplicationHelperActivity( Activity currentActivity, ComplicationLocation complicationLocation)439 private void launchComplicationHelperActivity( 440 Activity currentActivity, ComplicationLocation complicationLocation) { 441 442 mSelectedComplicationId = 443 AnalogComplicationWatchFaceService.getComplicationId(complicationLocation); 444 445 mBackgroundComplicationEnabled = false; 446 447 if (mSelectedComplicationId >= 0) { 448 449 int[] supportedTypes = 450 AnalogComplicationWatchFaceService.getSupportedComplicationTypes( 451 complicationLocation); 452 453 ComponentName watchFace = 454 new ComponentName( 455 currentActivity, AnalogComplicationWatchFaceService.class); 456 457 currentActivity.startActivityForResult( 458 ComplicationHelperActivity.createProviderChooserHelperIntent( 459 currentActivity, 460 watchFace, 461 mSelectedComplicationId, 462 supportedTypes), 463 AnalogComplicationConfigActivity.COMPLICATION_CONFIG_REQUEST_CODE); 464 465 } else { 466 Log.d(TAG, "Complication not supported by watch face."); 467 } 468 } 469 setDefaultComplicationDrawable(int resourceId)470 public void setDefaultComplicationDrawable(int resourceId) { 471 Context context = mWatchFaceArmsAndTicksView.getContext(); 472 mDefaultComplicationDrawable = context.getDrawable(resourceId); 473 474 mLeftComplication.setImageDrawable(mDefaultComplicationDrawable); 475 mLeftComplicationBackground.setVisibility(View.INVISIBLE); 476 477 mRightComplication.setImageDrawable(mDefaultComplicationDrawable); 478 mRightComplicationBackground.setVisibility(View.INVISIBLE); 479 } 480 updateComplicationViews( int watchFaceComplicationId, ComplicationProviderInfo complicationProviderInfo)481 public void updateComplicationViews( 482 int watchFaceComplicationId, ComplicationProviderInfo complicationProviderInfo) { 483 Log.d(TAG, "updateComplicationViews(): id: " + watchFaceComplicationId); 484 Log.d(TAG, "\tinfo: " + complicationProviderInfo); 485 486 if (watchFaceComplicationId == mBackgroundComplicationId) { 487 if (complicationProviderInfo != null) { 488 mBackgroundComplicationEnabled = true; 489 490 // Since we can't get the background complication image outside of the 491 // watch face, we set the icon for that provider instead with a gray background. 492 PorterDuffColorFilter backgroundColorFilter = 493 new PorterDuffColorFilter(Color.GRAY, PorterDuff.Mode.SRC_ATOP); 494 495 mWatchFaceBackgroundPreviewImageView 496 .getBackground() 497 .setColorFilter(backgroundColorFilter); 498 mWatchFaceBackgroundPreviewImageView.setImageIcon( 499 complicationProviderInfo.providerIcon); 500 501 } else { 502 mBackgroundComplicationEnabled = false; 503 504 // Clears icon for background if it was present before. 505 mWatchFaceBackgroundPreviewImageView.setImageResource( 506 android.R.color.transparent); 507 String backgroundSharedPrefString = 508 mContext.getString(R.string.saved_background_color); 509 int currentBackgroundColor = 510 mSharedPref.getInt(backgroundSharedPrefString, Color.BLACK); 511 512 PorterDuffColorFilter backgroundColorFilter = 513 new PorterDuffColorFilter( 514 currentBackgroundColor, PorterDuff.Mode.SRC_ATOP); 515 516 mWatchFaceBackgroundPreviewImageView 517 .getBackground() 518 .setColorFilter(backgroundColorFilter); 519 } 520 521 } else if (watchFaceComplicationId == mLeftComplicationId) { 522 updateComplicationView(complicationProviderInfo, mLeftComplication, 523 mLeftComplicationBackground); 524 525 } else if (watchFaceComplicationId == mRightComplicationId) { 526 updateComplicationView(complicationProviderInfo, mRightComplication, 527 mRightComplicationBackground); 528 } 529 } 530 updateComplicationView(ComplicationProviderInfo complicationProviderInfo, ImageButton button, ImageView background)531 private void updateComplicationView(ComplicationProviderInfo complicationProviderInfo, 532 ImageButton button, ImageView background) { 533 if (complicationProviderInfo != null) { 534 button.setImageIcon(complicationProviderInfo.providerIcon); 535 button.setContentDescription( 536 mContext.getString(R.string.edit_complication, 537 complicationProviderInfo.appName + " " + 538 complicationProviderInfo.providerName)); 539 background.setVisibility(View.VISIBLE); 540 } else { 541 button.setImageDrawable(mDefaultComplicationDrawable); 542 button.setContentDescription(mContext.getString(R.string.add_complication)); 543 background.setVisibility(View.INVISIBLE); 544 } 545 } 546 initializesColorsAndComplications()547 public void initializesColorsAndComplications() { 548 549 // Initializes highlight color (just second arm and part of complications). 550 String highlightSharedPrefString = mContext.getString(R.string.saved_marker_color); 551 int currentHighlightColor = mSharedPref.getInt(highlightSharedPrefString, Color.RED); 552 553 PorterDuffColorFilter highlightColorFilter = 554 new PorterDuffColorFilter(currentHighlightColor, PorterDuff.Mode.SRC_ATOP); 555 556 mWatchFaceHighlightPreviewView.getBackground().setColorFilter(highlightColorFilter); 557 558 // Initializes background color to gray (updates to color or complication icon based 559 // on whether the background complication is live or not. 560 PorterDuffColorFilter backgroundColorFilter = 561 new PorterDuffColorFilter(Color.GRAY, PorterDuff.Mode.SRC_ATOP); 562 563 mWatchFaceBackgroundPreviewImageView 564 .getBackground() 565 .setColorFilter(backgroundColorFilter); 566 567 final int[] complicationIds = AnalogComplicationWatchFaceService.getComplicationIds(); 568 569 mProviderInfoRetriever.retrieveProviderInfo( 570 new OnProviderInfoReceivedCallback() { 571 @Override 572 public void onProviderInfoReceived( 573 int watchFaceComplicationId, 574 @Nullable ComplicationProviderInfo complicationProviderInfo) { 575 576 Log.d(TAG, "onProviderInfoReceived: " + complicationProviderInfo); 577 578 updateComplicationViews( 579 watchFaceComplicationId, complicationProviderInfo); 580 } 581 }, 582 mWatchFaceComponentName, 583 complicationIds); 584 } 585 } 586 587 /** Displays icon to indicate there are more options below the fold. */ 588 public class MoreOptionsViewHolder extends RecyclerView.ViewHolder { 589 590 private ImageView mMoreOptionsImageView; 591 MoreOptionsViewHolder(View view)592 public MoreOptionsViewHolder(View view) { 593 super(view); 594 mMoreOptionsImageView = (ImageView) view.findViewById(R.id.more_options_image_view); 595 } 596 setIcon(int resourceId)597 public void setIcon(int resourceId) { 598 Context context = mMoreOptionsImageView.getContext(); 599 mMoreOptionsImageView.setImageDrawable(context.getDrawable(resourceId)); 600 } 601 } 602 603 /** 604 * Displays color options for the an item on the watch face. These could include marker color, 605 * background color, etc. 606 */ 607 public class ColorPickerViewHolder extends RecyclerView.ViewHolder implements OnClickListener { 608 609 private Button mAppearanceButton; 610 611 private String mSharedPrefResourceString; 612 613 private Class<ColorSelectionActivity> mLaunchActivityToSelectColor; 614 ColorPickerViewHolder(View view)615 public ColorPickerViewHolder(View view) { 616 super(view); 617 618 mAppearanceButton = (Button) view.findViewById(R.id.color_picker_button); 619 view.setOnClickListener(this); 620 } 621 setName(String name)622 public void setName(String name) { 623 mAppearanceButton.setText(name); 624 } 625 setIcon(int resourceId)626 public void setIcon(int resourceId) { 627 Context context = mAppearanceButton.getContext(); 628 mAppearanceButton.setCompoundDrawablesWithIntrinsicBounds( 629 context.getDrawable(resourceId), null, null, null); 630 } 631 setSharedPrefString(String sharedPrefString)632 public void setSharedPrefString(String sharedPrefString) { 633 mSharedPrefResourceString = sharedPrefString; 634 } 635 setLaunchActivityToSelectColor(Class<ColorSelectionActivity> activity)636 public void setLaunchActivityToSelectColor(Class<ColorSelectionActivity> activity) { 637 mLaunchActivityToSelectColor = activity; 638 } 639 640 @Override onClick(View view)641 public void onClick(View view) { 642 int position = getAdapterPosition(); 643 Log.d(TAG, "Complication onClick() position: " + position); 644 645 if (mLaunchActivityToSelectColor != null) { 646 Intent launchIntent = new Intent(view.getContext(), mLaunchActivityToSelectColor); 647 648 // Pass shared preference name to save color value to. 649 launchIntent.putExtra(EXTRA_SHARED_PREF, mSharedPrefResourceString); 650 651 Activity activity = (Activity) view.getContext(); 652 activity.startActivityForResult( 653 launchIntent, 654 AnalogComplicationConfigActivity.UPDATE_COLORS_CONFIG_REQUEST_CODE); 655 } 656 } 657 } 658 659 /** 660 * Displays switch to indicate whether or not icon appears for unread notifications. User can 661 * toggle on/off. 662 */ 663 public class UnreadNotificationViewHolder extends RecyclerView.ViewHolder 664 implements OnClickListener { 665 666 private Switch mUnreadNotificationSwitch; 667 668 private int mEnabledIconResourceId; 669 private int mDisabledIconResourceId; 670 671 private int mSharedPrefResourceId; 672 UnreadNotificationViewHolder(View view)673 public UnreadNotificationViewHolder(View view) { 674 super(view); 675 676 mUnreadNotificationSwitch = (Switch) view.findViewById(R.id.unread_notification_switch); 677 view.setOnClickListener(this); 678 } 679 setName(String name)680 public void setName(String name) { 681 mUnreadNotificationSwitch.setText(name); 682 } 683 setIcons(int enabledIconResourceId, int disabledIconResourceId)684 public void setIcons(int enabledIconResourceId, int disabledIconResourceId) { 685 686 mEnabledIconResourceId = enabledIconResourceId; 687 mDisabledIconResourceId = disabledIconResourceId; 688 689 Context context = mUnreadNotificationSwitch.getContext(); 690 691 // Set default to enabled. 692 mUnreadNotificationSwitch.setCompoundDrawablesWithIntrinsicBounds( 693 context.getDrawable(mEnabledIconResourceId), null, null, null); 694 } 695 setSharedPrefId(int sharedPrefId)696 public void setSharedPrefId(int sharedPrefId) { 697 mSharedPrefResourceId = sharedPrefId; 698 699 if (mUnreadNotificationSwitch != null) { 700 701 Context context = mUnreadNotificationSwitch.getContext(); 702 String sharedPreferenceString = context.getString(mSharedPrefResourceId); 703 Boolean currentState = mSharedPref.getBoolean(sharedPreferenceString, true); 704 705 updateIcon(context, currentState); 706 } 707 } 708 updateIcon(Context context, Boolean currentState)709 private void updateIcon(Context context, Boolean currentState) { 710 int currentIconResourceId; 711 712 if (currentState) { 713 currentIconResourceId = mEnabledIconResourceId; 714 } else { 715 currentIconResourceId = mDisabledIconResourceId; 716 } 717 718 mUnreadNotificationSwitch.setChecked(currentState); 719 mUnreadNotificationSwitch.setCompoundDrawablesWithIntrinsicBounds( 720 context.getDrawable(currentIconResourceId), null, null, null); 721 } 722 723 @Override onClick(View view)724 public void onClick(View view) { 725 int position = getAdapterPosition(); 726 Log.d(TAG, "Complication onClick() position: " + position); 727 728 Context context = view.getContext(); 729 String sharedPreferenceString = context.getString(mSharedPrefResourceId); 730 731 // Since user clicked on a switch, new state should be opposite of current state. 732 Boolean newState = !mSharedPref.getBoolean(sharedPreferenceString, true); 733 734 SharedPreferences.Editor editor = mSharedPref.edit(); 735 editor.putBoolean(sharedPreferenceString, newState); 736 editor.apply(); 737 738 updateIcon(context, newState); 739 } 740 } 741 742 /** Displays button to trigger background image complication selector. */ 743 public class BackgroundComplicationViewHolder extends RecyclerView.ViewHolder 744 implements OnClickListener { 745 746 private Button mBackgroundComplicationButton; 747 BackgroundComplicationViewHolder(View view)748 public BackgroundComplicationViewHolder(View view) { 749 super(view); 750 751 mBackgroundComplicationButton = 752 (Button) view.findViewById(R.id.background_complication_button); 753 view.setOnClickListener(this); 754 } 755 setName(String name)756 public void setName(String name) { 757 mBackgroundComplicationButton.setText(name); 758 } 759 setIcon(int resourceId)760 public void setIcon(int resourceId) { 761 Context context = mBackgroundComplicationButton.getContext(); 762 mBackgroundComplicationButton.setCompoundDrawablesWithIntrinsicBounds( 763 context.getDrawable(resourceId), null, null, null); 764 } 765 766 @Override onClick(View view)767 public void onClick(View view) { 768 int position = getAdapterPosition(); 769 Log.d(TAG, "Background Complication onClick() position: " + position); 770 771 Activity currentActivity = (Activity) view.getContext(); 772 773 mSelectedComplicationId = 774 AnalogComplicationWatchFaceService.getComplicationId( 775 ComplicationLocation.BACKGROUND); 776 777 if (mSelectedComplicationId >= 0) { 778 779 int[] supportedTypes = 780 AnalogComplicationWatchFaceService.getSupportedComplicationTypes( 781 ComplicationLocation.BACKGROUND); 782 783 ComponentName watchFace = 784 new ComponentName( 785 currentActivity, AnalogComplicationWatchFaceService.class); 786 787 currentActivity.startActivityForResult( 788 ComplicationHelperActivity.createProviderChooserHelperIntent( 789 currentActivity, 790 watchFace, 791 mSelectedComplicationId, 792 supportedTypes), 793 AnalogComplicationConfigActivity.COMPLICATION_CONFIG_REQUEST_CODE); 794 795 } else { 796 Log.d(TAG, "Complication not supported by watch face."); 797 } 798 } 799 } 800 } 801