1 /* 2 * Copyright (C) 2015 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.deskclock.alarms.dataadapter; 18 19 import android.animation.Animator; 20 import android.animation.AnimatorListenerAdapter; 21 import android.animation.AnimatorSet; 22 import android.animation.ObjectAnimator; 23 import android.animation.PropertyValuesHolder; 24 import android.content.Context; 25 import android.graphics.Color; 26 import android.graphics.Rect; 27 import android.graphics.drawable.Drawable; 28 import android.graphics.drawable.LayerDrawable; 29 import android.os.Vibrator; 30 import android.support.v4.content.ContextCompat; 31 import android.support.v7.widget.RecyclerView.ViewHolder; 32 import android.view.LayoutInflater; 33 import android.view.View; 34 import android.view.ViewGroup; 35 import android.widget.CheckBox; 36 import android.widget.CompoundButton; 37 import android.widget.LinearLayout; 38 import android.widget.TextView; 39 40 import com.android.deskclock.AnimatorUtils; 41 import com.android.deskclock.ItemAdapter; 42 import com.android.deskclock.R; 43 import com.android.deskclock.ThemeUtils; 44 import com.android.deskclock.Utils; 45 import com.android.deskclock.alarms.AlarmTimeClickHandler; 46 import com.android.deskclock.data.DataModel; 47 import com.android.deskclock.events.Events; 48 import com.android.deskclock.provider.Alarm; 49 import com.android.deskclock.provider.AlarmInstance; 50 import com.android.deskclock.uidata.UiDataModel; 51 52 import java.util.List; 53 54 import static android.content.Context.VIBRATOR_SERVICE; 55 import static android.view.View.TRANSLATION_Y; 56 57 /** 58 * A ViewHolder containing views for an alarm item in expanded state. 59 */ 60 public final class ExpandedAlarmViewHolder extends AlarmItemViewHolder { 61 public static final int VIEW_TYPE = R.layout.alarm_time_expanded; 62 63 public final CheckBox repeat; 64 private final TextView editLabel; 65 public final LinearLayout repeatDays; 66 private final CompoundButton[] dayButtons = new CompoundButton[7]; 67 public final CheckBox vibrate; 68 public final TextView ringtone; 69 public final TextView delete; 70 private final View hairLine; 71 72 private final boolean mHasVibrator; 73 74 private ExpandedAlarmViewHolder(View itemView, boolean hasVibrator) { 75 super(itemView); 76 77 mHasVibrator = hasVibrator; 78 79 delete = (TextView) itemView.findViewById(R.id.delete); 80 repeat = (CheckBox) itemView.findViewById(R.id.repeat_onoff); 81 vibrate = (CheckBox) itemView.findViewById(R.id.vibrate_onoff); 82 ringtone = (TextView) itemView.findViewById(R.id.choose_ringtone); 83 editLabel = (TextView) itemView.findViewById(R.id.edit_label); 84 repeatDays = (LinearLayout) itemView.findViewById(R.id.repeat_days); 85 hairLine = itemView.findViewById(R.id.hairline); 86 87 final Context context = itemView.getContext(); 88 itemView.setBackground(new LayerDrawable(new Drawable[] { 89 ContextCompat.getDrawable(context, R.drawable.alarm_background_expanded), 90 ThemeUtils.resolveDrawable(context, R.attr.selectableItemBackground) 91 })); 92 93 // Build button for each day. 94 final LayoutInflater inflater = LayoutInflater.from(context); 95 final List<Integer> weekdays = DataModel.getDataModel().getWeekdayOrder().getCalendarDays(); 96 for (int i = 0; i < 7; i++) { 97 final View dayButtonFrame = inflater.inflate(R.layout.day_button, repeatDays, 98 false /* attachToRoot */); 99 final CompoundButton dayButton = 100 (CompoundButton) dayButtonFrame.findViewById(R.id.day_button_box); 101 final int weekday = weekdays.get(i); 102 dayButton.setText(UiDataModel.getUiDataModel().getShortWeekday(weekday)); 103 dayButton.setContentDescription(UiDataModel.getUiDataModel().getLongWeekday(weekday)); 104 repeatDays.addView(dayButtonFrame); 105 dayButtons[i] = dayButton; 106 } 107 108 // Cannot set in xml since we need compat functionality for API < 21 109 final Drawable labelIcon = Utils.getVectorDrawable(context, R.drawable.ic_label); 110 editLabel.setCompoundDrawablesRelativeWithIntrinsicBounds(labelIcon, null, null, null); 111 final Drawable deleteIcon = Utils.getVectorDrawable(context, R.drawable.ic_delete_small); 112 delete.setCompoundDrawablesRelativeWithIntrinsicBounds(deleteIcon, null, null, null); 113 114 // Collapse handler 115 itemView.setOnClickListener(new View.OnClickListener() { 116 @Override 117 public void onClick(View v) { 118 Events.sendAlarmEvent(R.string.action_collapse_implied, R.string.label_deskclock); 119 getItemHolder().collapse(); 120 } 121 }); 122 arrow.setOnClickListener(new View.OnClickListener() { 123 @Override 124 public void onClick(View v) { 125 Events.sendAlarmEvent(R.string.action_collapse, R.string.label_deskclock); 126 getItemHolder().collapse(); 127 } 128 }); 129 // Edit time handler 130 clock.setOnClickListener(new View.OnClickListener() { 131 @Override 132 public void onClick(View v) { 133 getAlarmTimeClickHandler().onClockClicked(getItemHolder().item); 134 } 135 }); 136 // Edit label handler 137 editLabel.setOnClickListener(new View.OnClickListener() { 138 @Override 139 public void onClick(View view) { 140 getAlarmTimeClickHandler().onEditLabelClicked(getItemHolder().item); 141 } 142 }); 143 // Vibrator checkbox handler 144 vibrate.setOnClickListener(new View.OnClickListener() { 145 @Override 146 public void onClick(View v) { 147 getAlarmTimeClickHandler().setAlarmVibrationEnabled(getItemHolder().item, 148 ((CheckBox) v).isChecked()); 149 } 150 }); 151 // Ringtone editor handler 152 ringtone.setOnClickListener(new View.OnClickListener() { 153 @Override 154 public void onClick(View view) { 155 getAlarmTimeClickHandler().onRingtoneClicked(context, getItemHolder().item); 156 } 157 }); 158 // Delete alarm handler 159 delete.setOnClickListener(new View.OnClickListener() { 160 @Override 161 public void onClick(View v) { 162 getAlarmTimeClickHandler().onDeleteClicked(getItemHolder()); 163 v.announceForAccessibility(context.getString(R.string.alarm_deleted)); 164 } 165 }); 166 // Repeat checkbox handler 167 repeat.setOnClickListener(new View.OnClickListener() { 168 @Override 169 public void onClick(View view) { 170 final boolean checked = ((CheckBox) view).isChecked(); 171 getAlarmTimeClickHandler().setAlarmRepeatEnabled(getItemHolder().item, checked); 172 getItemHolder().notifyItemChanged(ANIMATE_REPEAT_DAYS); 173 } 174 }); 175 // Day buttons handler 176 for (int i = 0; i < dayButtons.length; i++) { 177 final int buttonIndex = i; 178 dayButtons[i].setOnClickListener(new View.OnClickListener() { 179 @Override 180 public void onClick(View view) { 181 final boolean isChecked = ((CompoundButton) view).isChecked(); 182 getAlarmTimeClickHandler().setDayOfWeekEnabled(getItemHolder().item, 183 isChecked, buttonIndex); 184 } 185 }); 186 } 187 188 itemView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); 189 } 190 191 @Override 192 protected void onBindItemView(final AlarmItemHolder itemHolder) { 193 super.onBindItemView(itemHolder); 194 195 final Alarm alarm = itemHolder.item; 196 final AlarmInstance alarmInstance = itemHolder.getAlarmInstance(); 197 final Context context = itemView.getContext(); 198 bindEditLabel(context, alarm); 199 bindDaysOfWeekButtons(alarm, context); 200 bindVibrator(alarm); 201 bindRingtone(context, alarm); 202 bindPreemptiveDismissButton(context, alarm, alarmInstance); 203 } 204 205 private void bindRingtone(Context context, Alarm alarm) { 206 final String title = DataModel.getDataModel().getRingtoneTitle(alarm.alert); 207 ringtone.setText(title); 208 209 final String description = context.getString(R.string.ringtone_description); 210 ringtone.setContentDescription(description + " " + title); 211 212 final boolean silent = Utils.RINGTONE_SILENT.equals(alarm.alert); 213 final Drawable icon = Utils.getVectorDrawable(context, 214 silent ? R.drawable.ic_ringtone_silent : R.drawable.ic_ringtone); 215 ringtone.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null); 216 } 217 218 private void bindDaysOfWeekButtons(Alarm alarm, Context context) { 219 final List<Integer> weekdays = DataModel.getDataModel().getWeekdayOrder().getCalendarDays(); 220 for (int i = 0; i < weekdays.size(); i++) { 221 final CompoundButton dayButton = dayButtons[i]; 222 if (alarm.daysOfWeek.isBitOn(weekdays.get(i))) { 223 dayButton.setChecked(true); 224 dayButton.setTextColor(ThemeUtils.resolveColor(context, 225 android.R.attr.windowBackground)); 226 } else { 227 dayButton.setChecked(false); 228 dayButton.setTextColor(Color.WHITE); 229 } 230 } 231 if (alarm.daysOfWeek.isRepeating()) { 232 repeat.setChecked(true); 233 repeatDays.setVisibility(View.VISIBLE); 234 } else { 235 repeat.setChecked(false); 236 repeatDays.setVisibility(View.GONE); 237 } 238 } 239 240 private void bindEditLabel(Context context, Alarm alarm) { 241 editLabel.setText(alarm.label); 242 editLabel.setContentDescription(alarm.label != null && alarm.label.length() > 0 243 ? context.getString(R.string.label_description) + " " + alarm.label 244 : context.getString(R.string.no_label_specified)); 245 } 246 247 private void bindVibrator(Alarm alarm) { 248 if (!mHasVibrator) { 249 vibrate.setVisibility(View.INVISIBLE); 250 } else { 251 vibrate.setVisibility(View.VISIBLE); 252 vibrate.setChecked(alarm.vibrate); 253 } 254 } 255 256 private AlarmTimeClickHandler getAlarmTimeClickHandler() { 257 return getItemHolder().getAlarmTimeClickHandler(); 258 } 259 260 @Override 261 public Animator onAnimateChange(List<Object> payloads, int fromLeft, int fromTop, int fromRight, 262 int fromBottom, long duration) { 263 if (payloads == null || payloads.isEmpty() || !payloads.contains(ANIMATE_REPEAT_DAYS)) { 264 return null; 265 } 266 267 final boolean isExpansion = repeatDays.getVisibility() == View.VISIBLE; 268 final int height = repeatDays.getHeight(); 269 setTranslationY(isExpansion ? -height : 0f, isExpansion ? -height : height); 270 repeatDays.setVisibility(View.VISIBLE); 271 repeatDays.setAlpha(isExpansion ? 0f : 1f); 272 273 final AnimatorSet animatorSet = new AnimatorSet(); 274 animatorSet.playTogether(AnimatorUtils.getBoundsAnimator(itemView, 275 fromLeft, fromTop, fromRight, fromBottom, 276 itemView.getLeft(), itemView.getTop(), itemView.getRight(), itemView.getBottom()), 277 ObjectAnimator.ofFloat(repeatDays, View.ALPHA, isExpansion ? 1f : 0f), 278 ObjectAnimator.ofFloat(repeatDays, TRANSLATION_Y, isExpansion ? 0f : -height), 279 ObjectAnimator.ofFloat(ringtone, TRANSLATION_Y, 0f), 280 ObjectAnimator.ofFloat(vibrate, TRANSLATION_Y, 0f), 281 ObjectAnimator.ofFloat(editLabel, TRANSLATION_Y, 0f), 282 ObjectAnimator.ofFloat(preemptiveDismissButton, TRANSLATION_Y, 0f), 283 ObjectAnimator.ofFloat(hairLine, TRANSLATION_Y, 0f), 284 ObjectAnimator.ofFloat(delete, TRANSLATION_Y, 0f), 285 ObjectAnimator.ofFloat(arrow, TRANSLATION_Y, 0f)); 286 animatorSet.addListener(new AnimatorListenerAdapter() { 287 @Override 288 public void onAnimationEnd(Animator animator) { 289 setTranslationY(0f, 0f); 290 repeatDays.setAlpha(1f); 291 repeatDays.setVisibility(isExpansion ? View.VISIBLE : View.GONE); 292 itemView.requestLayout(); 293 } 294 }); 295 animatorSet.setDuration(duration); 296 animatorSet.setInterpolator(AnimatorUtils.INTERPOLATOR_FAST_OUT_SLOW_IN); 297 298 return animatorSet; 299 } 300 301 private void setTranslationY(float repeatDaysTranslationY, float translationY) { 302 repeatDays.setTranslationY(repeatDaysTranslationY); 303 ringtone.setTranslationY(translationY); 304 vibrate.setTranslationY(translationY); 305 editLabel.setTranslationY(translationY); 306 preemptiveDismissButton.setTranslationY(translationY); 307 hairLine.setTranslationY(translationY); 308 delete.setTranslationY(translationY); 309 arrow.setTranslationY(translationY); 310 } 311 312 @Override 313 public Animator onAnimateChange(final ViewHolder oldHolder, ViewHolder newHolder, 314 long duration) { 315 if (!(oldHolder instanceof AlarmItemViewHolder) 316 || !(newHolder instanceof AlarmItemViewHolder)) { 317 return null; 318 } 319 320 final boolean isExpanding = this == newHolder; 321 AnimatorUtils.setBackgroundAlpha(itemView, isExpanding ? 0 : 255); 322 setChangingViewsAlpha(isExpanding ? 0f : 1f); 323 324 final Animator changeAnimatorSet = isExpanding 325 ? createExpandingAnimator((AlarmItemViewHolder) oldHolder, duration) 326 : createCollapsingAnimator((AlarmItemViewHolder) newHolder, duration); 327 changeAnimatorSet.addListener(new AnimatorListenerAdapter() { 328 @Override 329 public void onAnimationEnd(Animator animator) { 330 AnimatorUtils.setBackgroundAlpha(itemView, 255); 331 clock.setVisibility(View.VISIBLE); 332 onOff.setVisibility(View.VISIBLE); 333 arrow.setVisibility(View.VISIBLE); 334 arrow.setTranslationY(0f); 335 setChangingViewsAlpha(1f); 336 arrow.jumpDrawablesToCurrentState(); 337 } 338 }); 339 return changeAnimatorSet; 340 } 341 342 private Animator createCollapsingAnimator(AlarmItemViewHolder newHolder, long duration) { 343 arrow.setVisibility(View.INVISIBLE); 344 clock.setVisibility(View.INVISIBLE); 345 onOff.setVisibility(View.INVISIBLE); 346 347 final boolean daysVisible = repeatDays.getVisibility() == View.VISIBLE; 348 final int numberOfItems = countNumberOfItems(); 349 350 final View oldView = itemView; 351 final View newView = newHolder.itemView; 352 353 final Animator backgroundAnimator = ObjectAnimator.ofPropertyValuesHolder(oldView, 354 PropertyValuesHolder.ofInt(AnimatorUtils.BACKGROUND_ALPHA, 255, 0)); 355 backgroundAnimator.setDuration(duration); 356 357 final Animator boundsAnimator = AnimatorUtils.getBoundsAnimator(oldView, oldView, newView); 358 boundsAnimator.setDuration(duration); 359 boundsAnimator.setInterpolator(AnimatorUtils.INTERPOLATOR_FAST_OUT_SLOW_IN); 360 361 final long shortDuration = (long) (duration * ANIM_SHORT_DURATION_MULTIPLIER); 362 final Animator repeatAnimation = ObjectAnimator.ofFloat(repeat, View.ALPHA, 0f) 363 .setDuration(shortDuration); 364 final Animator editLabelAnimation = ObjectAnimator.ofFloat(editLabel, View.ALPHA, 0f) 365 .setDuration(shortDuration); 366 final Animator repeatDaysAnimation = ObjectAnimator.ofFloat(repeatDays, View.ALPHA, 0f) 367 .setDuration(shortDuration); 368 final Animator vibrateAnimation = ObjectAnimator.ofFloat(vibrate, View.ALPHA, 0f) 369 .setDuration(shortDuration); 370 final Animator ringtoneAnimation = ObjectAnimator.ofFloat(ringtone, View.ALPHA, 0f) 371 .setDuration(shortDuration); 372 final Animator dismissAnimation = ObjectAnimator.ofFloat(preemptiveDismissButton, 373 View.ALPHA, 0f).setDuration(shortDuration); 374 final Animator deleteAnimation = ObjectAnimator.ofFloat(delete, View.ALPHA, 0f) 375 .setDuration(shortDuration); 376 final Animator hairLineAnimation = ObjectAnimator.ofFloat(hairLine, View.ALPHA, 0f) 377 .setDuration(shortDuration); 378 379 // Set the staggered delays; use the first portion (duration * (1 - 1/4 - 1/6)) of the time, 380 // so that the final animation, with a duration of 1/4 the total duration, finishes exactly 381 // before the collapsed holder begins expanding. 382 long startDelay = 0L; 383 final long delayIncrement = (long) (duration * ANIM_LONG_DELAY_INCREMENT_MULTIPLIER) 384 / (numberOfItems - 1); 385 deleteAnimation.setStartDelay(startDelay); 386 if (preemptiveDismissButton.getVisibility() == View.VISIBLE) { 387 startDelay += delayIncrement; 388 dismissAnimation.setStartDelay(startDelay); 389 } 390 hairLineAnimation.setStartDelay(startDelay); 391 startDelay += delayIncrement; 392 editLabelAnimation.setStartDelay(startDelay); 393 startDelay += delayIncrement; 394 vibrateAnimation.setStartDelay(startDelay); 395 ringtoneAnimation.setStartDelay(startDelay); 396 startDelay += delayIncrement; 397 if (daysVisible) { 398 repeatDaysAnimation.setStartDelay(startDelay); 399 startDelay += delayIncrement; 400 } 401 repeatAnimation.setStartDelay(startDelay); 402 403 final AnimatorSet animatorSet = new AnimatorSet(); 404 animatorSet.playTogether(backgroundAnimator, boundsAnimator, repeatAnimation, 405 repeatDaysAnimation, vibrateAnimation, ringtoneAnimation, editLabelAnimation, 406 deleteAnimation, hairLineAnimation, dismissAnimation); 407 return animatorSet; 408 } 409 410 private Animator createExpandingAnimator(AlarmItemViewHolder oldHolder, long duration) { 411 final View oldView = oldHolder.itemView; 412 final View newView = itemView; 413 final Animator boundsAnimator = AnimatorUtils.getBoundsAnimator(newView, oldView, newView); 414 boundsAnimator.setDuration(duration); 415 boundsAnimator.setInterpolator(AnimatorUtils.INTERPOLATOR_FAST_OUT_SLOW_IN); 416 417 final Animator backgroundAnimator = ObjectAnimator.ofPropertyValuesHolder(newView, 418 PropertyValuesHolder.ofInt(AnimatorUtils.BACKGROUND_ALPHA, 0, 255)); 419 backgroundAnimator.setDuration(duration); 420 421 final View oldArrow = oldHolder.arrow; 422 final Rect oldArrowRect = new Rect(0, 0, oldArrow.getWidth(), oldArrow.getHeight()); 423 final Rect newArrowRect = new Rect(0, 0, arrow.getWidth(), arrow.getHeight()); 424 ((ViewGroup) newView).offsetDescendantRectToMyCoords(arrow, newArrowRect); 425 ((ViewGroup) oldView).offsetDescendantRectToMyCoords(oldArrow, oldArrowRect); 426 final float arrowTranslationY = oldArrowRect.bottom - newArrowRect.bottom; 427 428 arrow.setTranslationY(arrowTranslationY); 429 arrow.setVisibility(View.VISIBLE); 430 clock.setVisibility(View.VISIBLE); 431 onOff.setVisibility(View.VISIBLE); 432 433 final long longDuration = (long) (duration * ANIM_LONG_DURATION_MULTIPLIER); 434 final Animator repeatAnimation = ObjectAnimator.ofFloat(repeat, View.ALPHA, 1f) 435 .setDuration(longDuration); 436 final Animator repeatDaysAnimation = ObjectAnimator.ofFloat(repeatDays, View.ALPHA, 1f) 437 .setDuration(longDuration); 438 final Animator ringtoneAnimation = ObjectAnimator.ofFloat(ringtone, View.ALPHA, 1f) 439 .setDuration(longDuration); 440 final Animator dismissAnimation = ObjectAnimator.ofFloat(preemptiveDismissButton, 441 View.ALPHA, 1f).setDuration(longDuration); 442 final Animator vibrateAnimation = ObjectAnimator.ofFloat(vibrate, View.ALPHA, 1f) 443 .setDuration(longDuration); 444 final Animator editLabelAnimation = ObjectAnimator.ofFloat(editLabel, View.ALPHA, 1f) 445 .setDuration(longDuration); 446 final Animator hairLineAnimation = ObjectAnimator.ofFloat(hairLine, View.ALPHA, 1f) 447 .setDuration(longDuration); 448 final Animator deleteAnimation = ObjectAnimator.ofFloat(delete, View.ALPHA, 1f) 449 .setDuration(longDuration); 450 final Animator arrowAnimation = ObjectAnimator.ofFloat(arrow, View.TRANSLATION_Y, 0f) 451 .setDuration(duration); 452 arrowAnimation.setInterpolator(AnimatorUtils.INTERPOLATOR_FAST_OUT_SLOW_IN); 453 454 // Set the stagger delays; delay the first by the amount of time it takes for the collapse 455 // to complete, then stagger the expansion with the remaining time. 456 long startDelay = (long) (duration * ANIM_STANDARD_DELAY_MULTIPLIER); 457 final int numberOfItems = countNumberOfItems(); 458 final long delayIncrement = (long) (duration * ANIM_SHORT_DELAY_INCREMENT_MULTIPLIER) 459 / (numberOfItems - 1); 460 repeatAnimation.setStartDelay(startDelay); 461 startDelay += delayIncrement; 462 final boolean daysVisible = repeatDays.getVisibility() == View.VISIBLE; 463 if (daysVisible) { 464 repeatDaysAnimation.setStartDelay(startDelay); 465 startDelay += delayIncrement; 466 } 467 ringtoneAnimation.setStartDelay(startDelay); 468 vibrateAnimation.setStartDelay(startDelay); 469 startDelay += delayIncrement; 470 editLabelAnimation.setStartDelay(startDelay); 471 startDelay += delayIncrement; 472 hairLineAnimation.setStartDelay(startDelay); 473 if (preemptiveDismissButton.getVisibility() == View.VISIBLE) { 474 dismissAnimation.setStartDelay(startDelay); 475 startDelay += delayIncrement; 476 } 477 deleteAnimation.setStartDelay(startDelay); 478 479 final AnimatorSet animatorSet = new AnimatorSet(); 480 animatorSet.playTogether(backgroundAnimator, repeatAnimation, boundsAnimator, 481 repeatDaysAnimation, vibrateAnimation, ringtoneAnimation, editLabelAnimation, 482 deleteAnimation, hairLineAnimation, dismissAnimation, arrowAnimation); 483 animatorSet.addListener(new AnimatorListenerAdapter() { 484 @Override 485 public void onAnimationStart(Animator animator) { 486 AnimatorUtils.startDrawableAnimation(arrow); 487 } 488 }); 489 return animatorSet; 490 } 491 492 private int countNumberOfItems() { 493 // Always between 4 and 6 items. 494 int numberOfItems = 4; 495 if (preemptiveDismissButton.getVisibility() == View.VISIBLE) { 496 numberOfItems++; 497 } 498 if (repeatDays.getVisibility() == View.VISIBLE) { 499 numberOfItems++; 500 } 501 return numberOfItems; 502 } 503 504 private void setChangingViewsAlpha(float alpha) { 505 repeat.setAlpha(alpha); 506 editLabel.setAlpha(alpha); 507 repeatDays.setAlpha(alpha); 508 vibrate.setAlpha(alpha); 509 ringtone.setAlpha(alpha); 510 hairLine.setAlpha(alpha); 511 delete.setAlpha(alpha); 512 preemptiveDismissButton.setAlpha(alpha); 513 } 514 515 public static class Factory implements ItemAdapter.ItemViewHolder.Factory { 516 517 private final LayoutInflater mLayoutInflater; 518 private final boolean mHasVibrator; 519 520 public Factory(Context context) { 521 mLayoutInflater = LayoutInflater.from(context); 522 mHasVibrator = ((Vibrator) context.getSystemService(VIBRATOR_SERVICE)).hasVibrator(); 523 } 524 525 @Override 526 public ItemAdapter.ItemViewHolder<?> createViewHolder(ViewGroup parent, int viewType) { 527 final View itemView = mLayoutInflater.inflate(viewType, parent, false); 528 return new ExpandedAlarmViewHolder(itemView, mHasVibrator); 529 } 530 } 531 } 532