KeyguardWidgetPager.java revision f70239a4313010bf0dd3e1ff37f58a806857baa4
1/* 2 * Copyright (C) 2012 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 */ 16package com.android.internal.policy.impl.keyguard; 17 18import android.animation.Animator; 19import android.animation.AnimatorListenerAdapter; 20import android.animation.AnimatorSet; 21import android.animation.ObjectAnimator; 22import android.animation.PropertyValuesHolder; 23import android.animation.TimeInterpolator; 24import android.appwidget.AppWidgetHostView; 25import android.appwidget.AppWidgetProviderInfo; 26import android.content.Context; 27import android.content.res.Resources; 28import android.os.Handler; 29import android.os.HandlerThread; 30import android.util.AttributeSet; 31import android.util.Slog; 32import android.view.Gravity; 33import android.view.MotionEvent; 34import android.view.View; 35import android.view.View.OnLongClickListener; 36import android.view.ViewGroup; 37import android.view.accessibility.AccessibilityEvent; 38import android.view.accessibility.AccessibilityManager; 39import android.widget.FrameLayout; 40 41import com.android.internal.R; 42import com.android.internal.widget.LockPatternUtils; 43 44import java.util.ArrayList; 45 46public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwitchListener, 47 OnLongClickListener { 48 49 ZInterpolator mZInterpolator = new ZInterpolator(0.5f); 50 private static float CAMERA_DISTANCE = 10000; 51 protected static float OVERSCROLL_MAX_ROTATION = 30; 52 private static final boolean PERFORM_OVERSCROLL_ROTATION = true; 53 54 protected KeyguardViewStateManager mViewStateManager; 55 private LockPatternUtils mLockPatternUtils; 56 57 // Related to the fading in / out background outlines 58 public static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375; 59 public static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 100; 60 protected AnimatorSet mChildrenOutlineFadeAnimation; 61 protected int mScreenCenter; 62 private boolean mHasMeasure = false; 63 boolean showHintsAfterLayout = false; 64 65 private static final long CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT = 30000; 66 private static final String TAG = "KeyguardWidgetPager"; 67 68 private int mPage = 0; 69 private Callbacks mCallbacks; 70 71 private boolean mCameraWidgetEnabled; 72 73 private KeyguardWidgetFrame mWidgetToResetAfterFadeOut; 74 75 // Background threads to deal with persistence 76 private HandlerThread mBgPersistenceWorkerThread; 77 private Handler mBgPersistenceWorkerHandler; 78 79 public KeyguardWidgetPager(Context context, AttributeSet attrs) { 80 this(context, attrs, 0); 81 } 82 83 public KeyguardWidgetPager(Context context) { 84 this(null, null, 0); 85 } 86 87 public KeyguardWidgetPager(Context context, AttributeSet attrs, int defStyle) { 88 super(context, attrs, defStyle); 89 if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 90 setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); 91 } 92 93 setPageSwitchListener(this); 94 95 Resources r = getResources(); 96 mCameraWidgetEnabled = r.getBoolean(R.bool.kg_enable_camera_default_widget); 97 mBgPersistenceWorkerThread = new HandlerThread("KeyguardWidgetPager Persistence"); 98 mBgPersistenceWorkerThread.start(); 99 mBgPersistenceWorkerHandler = new Handler(mBgPersistenceWorkerThread.getLooper()); 100 } 101 102 @Override 103 protected void onDetachedFromWindow() { 104 super.onDetachedFromWindow(); 105 106 // Clean up the persistence worker thread 107 if (mBgPersistenceWorkerThread != null) { 108 mBgPersistenceWorkerThread.quit(); 109 } 110 } 111 112 public void setViewStateManager(KeyguardViewStateManager viewStateManager) { 113 mViewStateManager = viewStateManager; 114 } 115 116 public void setLockPatternUtils(LockPatternUtils l) { 117 mLockPatternUtils = l; 118 } 119 120 @Override 121 public void onPageSwitching(View newPage, int newPageIndex) { 122 if (mViewStateManager != null) { 123 mViewStateManager.onPageSwitching(newPage, newPageIndex); 124 } 125 } 126 127 @Override 128 public void onPageSwitched(View newPage, int newPageIndex) { 129 boolean showingStatusWidget = false; 130 if (newPage instanceof ViewGroup) { 131 ViewGroup vg = (ViewGroup) newPage; 132 if (vg.getChildAt(0) instanceof KeyguardStatusView) { 133 showingStatusWidget = true; 134 } 135 } 136 137 // Disable the status bar clock if we're showing the default status widget 138 if (showingStatusWidget) { 139 setSystemUiVisibility(getSystemUiVisibility() | View.STATUS_BAR_DISABLE_CLOCK); 140 } else { 141 setSystemUiVisibility(getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_CLOCK); 142 } 143 144 // Extend the display timeout if the user switches pages 145 if (mPage != newPageIndex) { 146 int oldPageIndex = mPage; 147 mPage = newPageIndex; 148 userActivity(); 149 KeyguardWidgetFrame oldWidgetPage = getWidgetPageAt(oldPageIndex); 150 if (oldWidgetPage != null) { 151 oldWidgetPage.onActive(false); 152 } 153 KeyguardWidgetFrame newWidgetPage = getWidgetPageAt(newPageIndex); 154 if (newWidgetPage != null) { 155 newWidgetPage.onActive(true); 156 newWidgetPage.requestAccessibilityFocus(); 157 } 158 if (mParent != null && AccessibilityManager.getInstance(mContext).isEnabled()) { 159 AccessibilityEvent event = AccessibilityEvent.obtain( 160 AccessibilityEvent.TYPE_VIEW_SCROLLED); 161 onInitializeAccessibilityEvent(event); 162 onPopulateAccessibilityEvent(event); 163 mParent.requestSendAccessibilityEvent(this, event); 164 } 165 } 166 if (mViewStateManager != null) { 167 mViewStateManager.onPageSwitched(newPage, newPageIndex); 168 } 169 } 170 171 @Override 172 public void sendAccessibilityEvent(int eventType) { 173 if (eventType != AccessibilityEvent.TYPE_VIEW_SCROLLED || isPageMoving()) { 174 super.sendAccessibilityEvent(eventType); 175 } 176 } 177 178 private void userActivity() { 179 if (mCallbacks != null) { 180 mCallbacks.onUserActivityTimeoutChanged(); 181 mCallbacks.userActivity(); 182 } 183 } 184 185 @Override 186 public boolean onTouchEvent(MotionEvent ev) { 187 return captureUserInteraction(ev) || super.onTouchEvent(ev); 188 } 189 190 @Override 191 public boolean onInterceptTouchEvent(MotionEvent ev) { 192 return captureUserInteraction(ev) || super.onInterceptTouchEvent(ev); 193 } 194 195 private boolean captureUserInteraction(MotionEvent ev) { 196 KeyguardWidgetFrame currentWidgetPage = getWidgetPageAt(getCurrentPage()); 197 return currentWidgetPage != null && currentWidgetPage.onUserInteraction(ev); 198 } 199 200 public void showPagingFeedback() { 201 // Nothing yet. 202 } 203 204 public long getUserActivityTimeout() { 205 View page = getPageAt(mPage); 206 if (page instanceof ViewGroup) { 207 ViewGroup vg = (ViewGroup) page; 208 View view = vg.getChildAt(0); 209 if (!(view instanceof KeyguardStatusView) 210 && !(view instanceof KeyguardMultiUserSelectorView)) { 211 return CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT; 212 } 213 } 214 return -1; 215 } 216 217 public void setCallbacks(Callbacks callbacks) { 218 mCallbacks = callbacks; 219 } 220 221 public interface Callbacks { 222 public void userActivity(); 223 public void onUserActivityTimeoutChanged(); 224 } 225 226 public void addWidget(View widget) { 227 addWidget(widget, -1); 228 } 229 230 231 public void onRemoveView(View v) { 232 final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId(); 233 mBgPersistenceWorkerHandler.post(new Runnable() { 234 @Override 235 public void run() { 236 mLockPatternUtils.removeAppWidget(appWidgetId); 237 } 238 }); 239 } 240 241 public void onAddView(View v, final int index) { 242 final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId(); 243 final int[] pagesRange = new int[mTempVisiblePagesRange.length]; 244 getVisiblePages(pagesRange); 245 boundByReorderablePages(true, pagesRange); 246 // Subtract from the index to take into account pages before the reorderable 247 // pages (e.g. the "add widget" page) 248 mBgPersistenceWorkerHandler.post(new Runnable() { 249 @Override 250 public void run() { 251 mLockPatternUtils.addAppWidget(appWidgetId, index - pagesRange[0]); 252 } 253 }); 254 } 255 256 /* 257 * We wrap widgets in a special frame which handles drawing the over scroll foreground. 258 */ 259 public void addWidget(View widget, int pageIndex) { 260 KeyguardWidgetFrame frame; 261 // All views contained herein should be wrapped in a KeyguardWidgetFrame 262 if (!(widget instanceof KeyguardWidgetFrame)) { 263 frame = new KeyguardWidgetFrame(getContext()); 264 FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, 265 LayoutParams.MATCH_PARENT); 266 lp.gravity = Gravity.TOP; 267 268 // The framework adds a default padding to AppWidgetHostView. We don't need this padding 269 // for the Keyguard, so we override it to be 0. 270 widget.setPadding(0, 0, 0, 0); 271 frame.addView(widget, lp); 272 273 // We set whether or not this widget supports vertical resizing. 274 if (widget instanceof AppWidgetHostView) { 275 AppWidgetHostView awhv = (AppWidgetHostView) widget; 276 AppWidgetProviderInfo info = awhv.getAppWidgetInfo(); 277 if ((info.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0) { 278 frame.setWidgetLockedSmall(false); 279 } else { 280 // Lock the widget to be small. 281 frame.setWidgetLockedSmall(true); 282 } 283 } 284 } else { 285 frame = (KeyguardWidgetFrame) widget; 286 } 287 288 ViewGroup.LayoutParams pageLp = new ViewGroup.LayoutParams( 289 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 290 frame.setOnLongClickListener(this); 291 292 if (pageIndex == -1) { 293 addView(frame, pageLp); 294 } else { 295 addView(frame, pageIndex, pageLp); 296 } 297 298 // Update the frame content description. 299 View content = (widget == frame) ? frame.getContent() : widget; 300 if (content != null) { 301 String contentDescription = mContext.getString( 302 com.android.internal.R.string.keyguard_accessibility_widget, 303 content.getContentDescription()); 304 frame.setContentDescription(contentDescription); 305 } 306 } 307 308 /** 309 * Use addWidget() instead. 310 * @deprecated 311 */ 312 @Override 313 public void addView(View child, int index) { 314 enforceKeyguardWidgetFrame(child); 315 super.addView(child, index); 316 } 317 318 /** 319 * Use addWidget() instead. 320 * @deprecated 321 */ 322 @Override 323 public void addView(View child, int width, int height) { 324 enforceKeyguardWidgetFrame(child); 325 super.addView(child, width, height); 326 } 327 328 /** 329 * Use addWidget() instead. 330 * @deprecated 331 */ 332 @Override 333 public void addView(View child, LayoutParams params) { 334 enforceKeyguardWidgetFrame(child); 335 super.addView(child, params); 336 } 337 338 /** 339 * Use addWidget() instead. 340 * @deprecated 341 */ 342 @Override 343 public void addView(View child, int index, LayoutParams params) { 344 enforceKeyguardWidgetFrame(child); 345 super.addView(child, index, params); 346 } 347 348 private void enforceKeyguardWidgetFrame(View child) { 349 if (!(child instanceof KeyguardWidgetFrame)) { 350 throw new IllegalArgumentException( 351 "KeyguardWidgetPager children must be KeyguardWidgetFrames"); 352 } 353 } 354 355 public KeyguardWidgetFrame getWidgetPageAt(int index) { 356 // This is always a valid cast as we've guarded the ability to 357 return (KeyguardWidgetFrame) getChildAt(index); 358 } 359 360 protected void onUnhandledTap(MotionEvent ev) { 361 showPagingFeedback(); 362 } 363 364 @Override 365 protected void onPageBeginMoving() { 366 if (mViewStateManager != null) { 367 mViewStateManager.onPageBeginMoving(); 368 } 369 if (!isReordering(false)) { 370 showOutlinesAndSidePages(); 371 } 372 userActivity(); 373 } 374 375 @Override 376 protected void onPageEndMoving() { 377 if (mViewStateManager != null) { 378 mViewStateManager.onPageEndMoving(); 379 } 380 381 // In the reordering case, the pages will be faded appropriately on completion 382 // of the zoom in animation. 383 if (!isReordering(false)) { 384 hideOutlinesAndSidePages(); 385 } 386 } 387 388 protected void enablePageContentLayers() { 389 int children = getChildCount(); 390 for (int i = 0; i < children; i++) { 391 getWidgetPageAt(i).enableHardwareLayersForContent(); 392 } 393 } 394 395 protected void disablePageContentLayers() { 396 int children = getChildCount(); 397 for (int i = 0; i < children; i++) { 398 getWidgetPageAt(i).disableHardwareLayersForContent(); 399 } 400 } 401 402 /* 403 * This interpolator emulates the rate at which the perceived scale of an object changes 404 * as its distance from a camera increases. When this interpolator is applied to a scale 405 * animation on a view, it evokes the sense that the object is shrinking due to moving away 406 * from the camera. 407 */ 408 static class ZInterpolator implements TimeInterpolator { 409 private float focalLength; 410 411 public ZInterpolator(float foc) { 412 focalLength = foc; 413 } 414 415 public float getInterpolation(float input) { 416 return (1.0f - focalLength / (focalLength + input)) / 417 (1.0f - focalLength / (focalLength + 1.0f)); 418 } 419 } 420 421 @Override 422 protected void overScroll(float amount) { 423 acceleratedOverScroll(amount); 424 } 425 426 float backgroundAlphaInterpolator(float r) { 427 return Math.min(1f, r); 428 } 429 430 private void updatePageAlphaValues(int screenCenter) { 431 } 432 433 public float getAlphaForPage(int screenCenter, int index) { 434 return 1f; 435 } 436 437 public float getOutlineAlphaForPage(int screenCenter, int index) { 438 return getAlphaForPage(screenCenter, index) * KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER; 439 } 440 441 protected boolean isOverScrollChild(int index, float scrollProgress) { 442 boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX; 443 return (isInOverscroll && (index == 0 && scrollProgress < 0 || 444 index == getChildCount() - 1 && scrollProgress > 0)); 445 } 446 447 @Override 448 protected void screenScrolled(int screenCenter) { 449 mScreenCenter = screenCenter; 450 updatePageAlphaValues(screenCenter); 451 for (int i = 0; i < getChildCount(); i++) { 452 KeyguardWidgetFrame v = getWidgetPageAt(i); 453 if (v == mDragView) continue; 454 if (v != null) { 455 float scrollProgress = getScrollProgress(screenCenter, v, i); 456 457 v.setCameraDistance(mDensity * CAMERA_DISTANCE); 458 459 if (isOverScrollChild(i, scrollProgress) && PERFORM_OVERSCROLL_ROTATION) { 460 v.setRotationY(- OVERSCROLL_MAX_ROTATION * scrollProgress); 461 v.setOverScrollAmount(Math.abs(scrollProgress), scrollProgress < 0); 462 } else { 463 v.setRotationY(0f); 464 v.setOverScrollAmount(0, false); 465 } 466 467 float alpha = v.getAlpha(); 468 // If the view has 0 alpha, we set it to be invisible so as to prevent 469 // it from accepting touches 470 if (alpha == 0) { 471 v.setVisibility(INVISIBLE); 472 } else if (v.getVisibility() != VISIBLE) { 473 v.setVisibility(VISIBLE); 474 } 475 } 476 } 477 } 478 479 @Override 480 void boundByReorderablePages(boolean isReordering, int[] range) { 481 if (isReordering) { 482 if (isAddWidgetPageVisible()) { 483 range[0]++; 484 } 485 if (isMusicWidgetVisible()) { 486 range[1]--; 487 } 488 if (isCameraWidgetVisible()) { 489 range[1]--; 490 } 491 } 492 } 493 494 /* 495 * Special widgets 496 */ 497 boolean isAddWidgetPageVisible() { 498 // TODO: Make proper test once we decide whether the add-page is always showing 499 return true; 500 } 501 boolean isMusicWidgetVisible() { 502 return mViewStateManager.getTransportState() != KeyguardViewStateManager.TRANSPORT_GONE; 503 } 504 boolean isCameraWidgetVisible() { 505 return mCameraWidgetEnabled; 506 } 507 508 protected void reorderStarting() { 509 showOutlinesAndSidePages(); 510 } 511 512 @Override 513 protected void onStartReordering() { 514 super.onStartReordering(); 515 enablePageContentLayers(); 516 reorderStarting(); 517 } 518 519 @Override 520 protected void onEndReordering() { 521 super.onEndReordering(); 522 hideOutlinesAndSidePages(); 523 } 524 525 void showOutlinesAndSidePages() { 526 animateOutlinesAndSidePages(true); 527 } 528 529 void hideOutlinesAndSidePages() { 530 animateOutlinesAndSidePages(false); 531 } 532 533 public void showInitialPageHints() { 534 int count = getChildCount(); 535 for (int i = 0; i < count; i++) { 536 KeyguardWidgetFrame child = getWidgetPageAt(i); 537 if (i != mCurrentPage) { 538 child.fadeFrame(this, true, KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER, 539 CHILDREN_OUTLINE_FADE_IN_DURATION); 540 child.setContentAlpha(0f); 541 } else { 542 child.setBackgroundAlpha(0f); 543 child.setContentAlpha(1f); 544 } 545 } 546 } 547 548 public void showSidePageHints() { 549 animateOutlinesAndSidePages(true, -1); 550 } 551 552 @Override 553 public void onAttachedToWindow() { 554 super.onAttachedToWindow(); 555 mHasMeasure = false; 556 } 557 558 @Override 559 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 560 super.onLayout(changed, left, top, right, bottom); 561 } 562 563 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 564 int maxChallengeTop = -1; 565 View parent = (View) getParent(); 566 boolean challengeShowing = false; 567 // Widget pages need to know where the top of the sliding challenge is so that they 568 // now how big the widget should be when the challenge is up. We compute it here and 569 // then propagate it to each of our children. 570 if (parent.getParent() instanceof SlidingChallengeLayout) { 571 SlidingChallengeLayout scl = (SlidingChallengeLayout) parent.getParent(); 572 int top = scl.getMaxChallengeTop(); 573 574 // This is a bit evil, but we need to map a coordinate relative to the SCL into a 575 // coordinate relative to our children, hence we subtract the top padding.s 576 maxChallengeTop = top - getPaddingTop(); 577 challengeShowing = scl.isChallengeShowing(); 578 579 int count = getChildCount(); 580 for (int i = 0; i < count; i++) { 581 KeyguardWidgetFrame frame = getWidgetPageAt(i); 582 frame.setMaxChallengeTop(maxChallengeTop); 583 // On the very first measure pass, if the challenge is showing, we need to make sure 584 // that the widget on the current page is small. 585 if (challengeShowing && i == mCurrentPage && !mHasMeasure) { 586 frame.shrinkWidget(); 587 } 588 } 589 } 590 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 591 mHasMeasure = true; 592 } 593 594 void animateOutlinesAndSidePages(final boolean show) { 595 animateOutlinesAndSidePages(show, -1); 596 } 597 598 public void resetWidgetSizeOnPagesFaded(KeyguardWidgetFrame widget) { 599 mWidgetToResetAfterFadeOut = widget; 600 } 601 602 void animateOutlinesAndSidePages(final boolean show, int duration) { 603 if (mChildrenOutlineFadeAnimation != null) { 604 mChildrenOutlineFadeAnimation.cancel(); 605 mChildrenOutlineFadeAnimation = null; 606 } 607 int count = getChildCount(); 608 PropertyValuesHolder alpha; 609 ArrayList<Animator> anims = new ArrayList<Animator>(); 610 611 if (duration == -1) { 612 duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION : 613 CHILDREN_OUTLINE_FADE_OUT_DURATION; 614 } 615 616 int curPage = getNextPage(); 617 for (int i = 0; i < count; i++) { 618 float finalContentAlpha; 619 if (show) { 620 finalContentAlpha = getAlphaForPage(mScreenCenter, i); 621 } else if (!show && i == curPage) { 622 finalContentAlpha = 1f; 623 } else { 624 finalContentAlpha = 0f; 625 } 626 KeyguardWidgetFrame child = getWidgetPageAt(i); 627 628 alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalContentAlpha); 629 ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha); 630 anims.add(a); 631 632 float finalOutlineAlpha = show ? getOutlineAlphaForPage(mScreenCenter, i) : 0f; 633 child.fadeFrame(this, show, finalOutlineAlpha, duration); 634 } 635 636 mChildrenOutlineFadeAnimation = new AnimatorSet(); 637 mChildrenOutlineFadeAnimation.playTogether(anims); 638 639 mChildrenOutlineFadeAnimation.setDuration(duration); 640 mChildrenOutlineFadeAnimation.addListener(new AnimatorListenerAdapter() { 641 @Override 642 public void onAnimationStart(Animator animation) { 643 if (show) { 644 enablePageContentLayers(); 645 } 646 } 647 648 @Override 649 public void onAnimationEnd(Animator animation) { 650 if (!show) { 651 disablePageContentLayers(); 652 if (mWidgetToResetAfterFadeOut != null) { 653 if (!(getWidgetPageAt(mCurrentPage) == mWidgetToResetAfterFadeOut && 654 mViewStateManager.isChallengeShowing())) { 655 mWidgetToResetAfterFadeOut.resetSize(); 656 } 657 mWidgetToResetAfterFadeOut = null; 658 } 659 } 660 } 661 }); 662 mChildrenOutlineFadeAnimation.start(); 663 } 664 665 @Override 666 public boolean onLongClick(View v) { 667 // Disallow long pressing to reorder if the challenge is showing 668 boolean isChallengeOverlapping = mViewStateManager.isChallengeShowing() && 669 mViewStateManager.isChallengeOverlapping(); 670 if (!isChallengeOverlapping && startReordering()) { 671 return true; 672 } 673 return false; 674 } 675 676 public void removeWidget(View view) { 677 if (view instanceof KeyguardWidgetFrame) { 678 removeView(view); 679 } else { 680 // Assume view was wrapped by a KeyguardWidgetFrame in KeyguardWidgetPager#addWidget(). 681 // This supports legacy hard-coded "widgets" like KeyguardTransportControlView. 682 int pos = getWidgetPageIndex(view); 683 if (pos != -1) { 684 KeyguardWidgetFrame frame = (KeyguardWidgetFrame) getChildAt(pos); 685 frame.removeView(view); 686 removeView(frame); 687 } else { 688 Slog.w(TAG, "removeWidget() can't find:" + view); 689 } 690 } 691 } 692 693 public int getWidgetPageIndex(View view) { 694 if (view instanceof KeyguardWidgetFrame) { 695 return indexOfChild(view); 696 } else { 697 // View was wrapped by a KeyguardWidgetFrame by KeyguardWidgetPager#addWidget() 698 return indexOfChild((KeyguardWidgetFrame)view.getParent()); 699 } 700 } 701 702 @Override 703 protected void setPageHoveringOverDeleteDropTarget(int viewIndex, boolean isHovering) { 704 KeyguardWidgetFrame child = getWidgetPageAt(viewIndex); 705 child.setIsHoveringOverDeleteDropTarget(isHovering); 706 } 707} 708