DragLayer.java revision 432609a246819f3cf887a80c2ae56b61fc5ca25a
131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/* 231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License. 631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at 731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and 1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License. 1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3; 1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 19716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.Animator; 20716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.AnimatorListenerAdapter; 21716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.TimeInterpolator; 22716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.ValueAnimator; 23716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.ValueAnimator.AnimatorUpdateListener; 2431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context; 25716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.content.res.Resources; 26360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chungimport android.graphics.Canvas; 276788269814a678af976dfc7d6135993e172ce586Adam Cohenimport android.graphics.Rect; 28360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chungimport android.graphics.drawable.Drawable; 2931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet; 3026279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.KeyEvent; 3126279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.MotionEvent; 3226279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.View; 3326279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.ViewGroup; 343371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityEvent; 353371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityManager; 36716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.view.animation.DecelerateInterpolator; 373e8f811f31a2275e778244427271f77f4116c08bAdam Cohenimport android.view.animation.Interpolator; 3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.widget.FrameLayout; 39ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohenimport android.widget.TextView; 4031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 411d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohenimport java.util.ArrayList; 426788269814a678af976dfc7d6135993e172ce586Adam Cohen 4331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/** 440e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka * A ViewGroup that coordinates dragging across its descendants 4531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 468b805b17158886035b38261eb611d8641701ae43Michael Jurkapublic class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChangeListener { 47120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen private DragController mDragController; 48120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen private int[] mTmpXY = new int[2]; 4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 50716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen private int mXDown, mYDown; 51716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen private Launcher mLauncher; 52716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 536788269814a678af976dfc7d6135993e172ce586Adam Cohen // Variables relating to resizing widgets 546788269814a678af976dfc7d6135993e172ce586Adam Cohen private final ArrayList<AppWidgetResizeFrame> mResizeFrames = 556788269814a678af976dfc7d6135993e172ce586Adam Cohen new ArrayList<AppWidgetResizeFrame>(); 566788269814a678af976dfc7d6135993e172ce586Adam Cohen private AppWidgetResizeFrame mCurrentResizeFrame; 57716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 58716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen // Variables relating to animation of views after drop 59716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen private ValueAnimator mDropAnim = null; 608dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen private ValueAnimator mFadeOutAnim = null; 618dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen private TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f); 627bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung private DragView mDropView = null; 636441de0ec2a71862798dd51180d0811b42edd514Adam Cohen private int mAnchorViewInitialScrollX = 0; 646441de0ec2a71862798dd51180d0811b42edd514Adam Cohen private View mAnchorView = null; 658dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen 663371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen private boolean mHoverPointClosesFolder = false; 673371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen private Rect mHitRect = new Rect(); 68ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen public static final int ANIMATION_END_DISAPPEAR = 0; 69ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen public static final int ANIMATION_END_FADE_OUT = 1; 70ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen public static final int ANIMATION_END_REMAIN_VISIBLE = 2; 716788269814a678af976dfc7d6135993e172ce586Adam Cohen 72b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen private TouchCompleteListener mTouchCompleteListener; 73b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen 7477e1f47520958edd7ec04e203db65b932537bd1cJohn Spurlock private final Rect mInsets = new Rect(); 7577e1f47520958edd7ec04e203db65b932537bd1cJohn Spurlock 76432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen private View mOverlayView; 77432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen private int mTopViewIndex; 7855bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi 7931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 8031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Used to create a new DragLayer from XML. 8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 8231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param context The application's context. 830e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka * @param attrs The attributes set containing the Workspace's customization values. 8431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 8531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public DragLayer(Context context, AttributeSet attrs) { 8631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super(context, attrs); 87be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung 88be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung // Disable multitouch across the workspace/all apps/customize tray 89be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung setMotionEventSplittingEnabled(false); 9021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen setChildrenDrawingOrderEnabled(true); 918b805b17158886035b38261eb611d8641701ae43Michael Jurka setOnHierarchyChangeListener(this); 92360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 93360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung mLeftHoverDrawable = getResources().getDrawable(R.drawable.page_hover_left_holo); 94360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung mRightHoverDrawable = getResources().getDrawable(R.drawable.page_hover_right_holo); 9531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 9631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 974c98d9235d164680186180974719f551cf935d08Winson Chung public void setup(Launcher launcher, DragController controller) { 984c98d9235d164680186180974719f551cf935d08Winson Chung mLauncher = launcher; 9900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mDragController = controller; 10031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 10176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 10231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 10331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public boolean dispatchKeyEvent(KeyEvent event) { 10400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event); 10531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 10631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 10777e1f47520958edd7ec04e203db65b932537bd1cJohn Spurlock @Override 10877e1f47520958edd7ec04e203db65b932537bd1cJohn Spurlock protected boolean fitSystemWindows(Rect insets) { 10977e1f47520958edd7ec04e203db65b932537bd1cJohn Spurlock final int n = getChildCount(); 11077e1f47520958edd7ec04e203db65b932537bd1cJohn Spurlock for (int i = 0; i < n; i++) { 11177e1f47520958edd7ec04e203db65b932537bd1cJohn Spurlock final View child = getChildAt(i); 11226279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey setInsets(child, insets, mInsets); 11377e1f47520958edd7ec04e203db65b932537bd1cJohn Spurlock } 11477e1f47520958edd7ec04e203db65b932537bd1cJohn Spurlock mInsets.set(insets); 11577e1f47520958edd7ec04e203db65b932537bd1cJohn Spurlock return true; // I'll take it from here 11677e1f47520958edd7ec04e203db65b932537bd1cJohn Spurlock } 11777e1f47520958edd7ec04e203db65b932537bd1cJohn Spurlock 11826279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey @Override 11926279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) { 12026279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey super.addView(child, index, params); 12126279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey setInsets(child, mInsets, new Rect()); 12226279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey } 12326279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey 124432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen public void showOverlayView(View introScreen) { 125432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 126432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen mOverlayView = introScreen; 127432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen addView(introScreen, lp); 128432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen } 129432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen 130432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen public void dismissOverlayView() { 131432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen removeView(mOverlayView); 132432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen } 133432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen 13426279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey private void setInsets(View child, Rect newInsets, Rect oldInsets) { 13526279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams(); 13626279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey if (child instanceof Insettable) { 13726279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey ((Insettable) child).setInsets(newInsets); 13826279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey } else { 13926279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey flp.topMargin += (newInsets.top - oldInsets.top); 14026279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey flp.leftMargin += (newInsets.left - oldInsets.left); 14126279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey flp.rightMargin += (newInsets.right - oldInsets.right); 14226279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey flp.bottomMargin += (newInsets.bottom - oldInsets.bottom); 14326279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey } 14426279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey child.setLayoutParams(flp); 14526279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey } 14626279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkey 1473371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) { 1483371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect); 1493371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) { 1503371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return true; 1513371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 1523371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return false; 1533371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 1543371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 1553371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen private boolean isEventOverFolder(Folder folder, MotionEvent ev) { 1563371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen getDescendantRectRelativeToSelf(folder, mHitRect); 1573371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) { 1583371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return true; 1593371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 1603371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return false; 1613371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 1623371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 16376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private boolean handleTouchDown(MotionEvent ev, boolean intercept) { 1646788269814a678af976dfc7d6135993e172ce586Adam Cohen Rect hitRect = new Rect(); 1656788269814a678af976dfc7d6135993e172ce586Adam Cohen int x = (int) ev.getX(); 1666788269814a678af976dfc7d6135993e172ce586Adam Cohen int y = (int) ev.getY(); 1676788269814a678af976dfc7d6135993e172ce586Adam Cohen 1686788269814a678af976dfc7d6135993e172ce586Adam Cohen for (AppWidgetResizeFrame child: mResizeFrames) { 1696788269814a678af976dfc7d6135993e172ce586Adam Cohen child.getHitRect(hitRect); 1706788269814a678af976dfc7d6135993e172ce586Adam Cohen if (hitRect.contains(x, y)) { 1716788269814a678af976dfc7d6135993e172ce586Adam Cohen if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) { 1726788269814a678af976dfc7d6135993e172ce586Adam Cohen mCurrentResizeFrame = child; 1736788269814a678af976dfc7d6135993e172ce586Adam Cohen mXDown = x; 1746788269814a678af976dfc7d6135993e172ce586Adam Cohen mYDown = y; 1756788269814a678af976dfc7d6135993e172ce586Adam Cohen requestDisallowInterceptTouchEvent(true); 1766788269814a678af976dfc7d6135993e172ce586Adam Cohen return true; 1776788269814a678af976dfc7d6135993e172ce586Adam Cohen } 1786788269814a678af976dfc7d6135993e172ce586Adam Cohen } 1796788269814a678af976dfc7d6135993e172ce586Adam Cohen } 18076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 1811d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen Folder currentFolder = mLauncher.getWorkspace().getOpenFolder(); 182a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung if (currentFolder != null && !mLauncher.getLauncherClings().isFolderClingVisible() && 183a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung intercept) { 1841d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen if (currentFolder.isEditingName()) { 1853371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (!isEventOverFolderTextRegion(currentFolder, ev)) { 1861d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen currentFolder.dismissEditingName(); 18776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return true; 1882801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 1892801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 19076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 1911d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen getDescendantRectRelativeToSelf(currentFolder, hitRect); 1923371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (!isEventOverFolder(currentFolder, ev)) { 19376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mLauncher.closeFolder(); 19476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return true; 19576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 1962801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 1976788269814a678af976dfc7d6135993e172ce586Adam Cohen return false; 1986788269814a678af976dfc7d6135993e172ce586Adam Cohen } 1996788269814a678af976dfc7d6135993e172ce586Adam Cohen 20031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 20131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public boolean onInterceptTouchEvent(MotionEvent ev) { 202b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen int action = ev.getAction(); 203b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen 204b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen if (action == MotionEvent.ACTION_DOWN) { 20576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen if (handleTouchDown(ev, true)) { 2066788269814a678af976dfc7d6135993e172ce586Adam Cohen return true; 207d1837cc69eb222371afdd30890f7215d117510f2Patrick Dubroy } 208b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 209b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen if (mTouchCompleteListener != null) { 210b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen mTouchCompleteListener.onTouchComplete(); 211b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen } 212b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen mTouchCompleteListener = null; 2131b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen } 2146788269814a678af976dfc7d6135993e172ce586Adam Cohen clearAllResizeFrames(); 2154db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato return mDragController.onInterceptTouchEvent(ev); 21631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 21731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 21831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 2193371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen public boolean onInterceptHoverEvent(MotionEvent ev) { 220023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka if (mLauncher == null || mLauncher.getWorkspace() == null) { 221023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka return false; 222023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka } 2233371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen Folder currentFolder = mLauncher.getWorkspace().getOpenFolder(); 2243371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (currentFolder == null) { 2253371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return false; 2263371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } else { 2278b805b17158886035b38261eb611d8641701ae43Michael Jurka AccessibilityManager accessibilityManager = (AccessibilityManager) 2288b805b17158886035b38261eb611d8641701ae43Michael Jurka getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); 2298b805b17158886035b38261eb611d8641701ae43Michael Jurka if (accessibilityManager.isTouchExplorationEnabled()) { 2303371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen final int action = ev.getAction(); 2313371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen boolean isOverFolder; 2323371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen switch (action) { 2333371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen case MotionEvent.ACTION_HOVER_ENTER: 2343371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen isOverFolder = isEventOverFolder(currentFolder, ev); 2353371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (!isOverFolder) { 2363371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName()); 2373371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen mHoverPointClosesFolder = true; 2383371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return true; 2393371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 240693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu mHoverPointClosesFolder = false; 241693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu break; 2423371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen case MotionEvent.ACTION_HOVER_MOVE: 2433371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen isOverFolder = isEventOverFolder(currentFolder, ev); 2443371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (!isOverFolder && !mHoverPointClosesFolder) { 2453371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName()); 2463371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen mHoverPointClosesFolder = true; 2473371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return true; 248693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu } else if (!isOverFolder) { 2493371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return true; 2503371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 251693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu mHoverPointClosesFolder = false; 2523371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 2533371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 2543371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 2553371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return false; 2563371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 2573371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 2583371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen private void sendTapOutsideFolderAccessibilityEvent(boolean isEditingName) { 2598b805b17158886035b38261eb611d8641701ae43Michael Jurka AccessibilityManager accessibilityManager = (AccessibilityManager) 2608b805b17158886035b38261eb611d8641701ae43Michael Jurka getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); 2618b805b17158886035b38261eb611d8641701ae43Michael Jurka if (accessibilityManager.isEnabled()) { 2623371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen int stringId = isEditingName ? R.string.folder_tap_to_rename : R.string.folder_tap_to_close; 2633371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen AccessibilityEvent event = AccessibilityEvent.obtain( 2643371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen AccessibilityEvent.TYPE_VIEW_FOCUSED); 2653371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen onInitializeAccessibilityEvent(event); 2668b805b17158886035b38261eb611d8641701ae43Michael Jurka event.getText().add(getContext().getString(stringId)); 2678b805b17158886035b38261eb611d8641701ae43Michael Jurka accessibilityManager.sendAccessibilityEvent(event); 2683371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 26983ca480941b3dd635b62347008fc8d7859d82002Winson Chung } 27083ca480941b3dd635b62347008fc8d7859d82002Winson Chung 27183ca480941b3dd635b62347008fc8d7859d82002Winson Chung @Override 27283ca480941b3dd635b62347008fc8d7859d82002Winson Chung public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { 27383ca480941b3dd635b62347008fc8d7859d82002Winson Chung Folder currentFolder = mLauncher.getWorkspace().getOpenFolder(); 27483ca480941b3dd635b62347008fc8d7859d82002Winson Chung if (currentFolder != null) { 27583ca480941b3dd635b62347008fc8d7859d82002Winson Chung if (child == currentFolder) { 27683ca480941b3dd635b62347008fc8d7859d82002Winson Chung return super.onRequestSendAccessibilityEvent(child, event); 27783ca480941b3dd635b62347008fc8d7859d82002Winson Chung } 27883ca480941b3dd635b62347008fc8d7859d82002Winson Chung // Skip propagating onRequestSendAccessibilityEvent all for other children 27983ca480941b3dd635b62347008fc8d7859d82002Winson Chung // when a folder is open 28083ca480941b3dd635b62347008fc8d7859d82002Winson Chung return false; 28183ca480941b3dd635b62347008fc8d7859d82002Winson Chung } 28283ca480941b3dd635b62347008fc8d7859d82002Winson Chung return super.onRequestSendAccessibilityEvent(child, event); 28383ca480941b3dd635b62347008fc8d7859d82002Winson Chung } 28483ca480941b3dd635b62347008fc8d7859d82002Winson Chung 28583ca480941b3dd635b62347008fc8d7859d82002Winson Chung @Override 28683ca480941b3dd635b62347008fc8d7859d82002Winson Chung public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) { 28783ca480941b3dd635b62347008fc8d7859d82002Winson Chung Folder currentFolder = mLauncher.getWorkspace().getOpenFolder(); 28883ca480941b3dd635b62347008fc8d7859d82002Winson Chung if (currentFolder != null) { 28983ca480941b3dd635b62347008fc8d7859d82002Winson Chung // Only add the folder as a child for accessibility when it is open 29083ca480941b3dd635b62347008fc8d7859d82002Winson Chung childrenForAccessibility.add(currentFolder); 29183ca480941b3dd635b62347008fc8d7859d82002Winson Chung } else { 29283ca480941b3dd635b62347008fc8d7859d82002Winson Chung super.addChildrenForAccessibility(childrenForAccessibility); 29383ca480941b3dd635b62347008fc8d7859d82002Winson Chung } 2943371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 2953371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 2963371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen @Override 2973371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen public boolean onHoverEvent(MotionEvent ev) { 2983371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen // If we've received this, we've already done the necessary handling 2993371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen // in onInterceptHoverEvent. Return true to consume the event. 3003371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return false; 3013371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 3023371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 3033371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen @Override 30431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public boolean onTouchEvent(MotionEvent ev) { 3056788269814a678af976dfc7d6135993e172ce586Adam Cohen boolean handled = false; 3066788269814a678af976dfc7d6135993e172ce586Adam Cohen int action = ev.getAction(); 3076788269814a678af976dfc7d6135993e172ce586Adam Cohen 3086788269814a678af976dfc7d6135993e172ce586Adam Cohen int x = (int) ev.getX(); 3096788269814a678af976dfc7d6135993e172ce586Adam Cohen int y = (int) ev.getY(); 3106788269814a678af976dfc7d6135993e172ce586Adam Cohen 311b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen if (action == MotionEvent.ACTION_DOWN) { 312b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen if (handleTouchDown(ev, false)) { 313b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen return true; 314b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen } 315b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 316b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen if (mTouchCompleteListener != null) { 317b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen mTouchCompleteListener.onTouchComplete(); 3186788269814a678af976dfc7d6135993e172ce586Adam Cohen } 319b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen mTouchCompleteListener = null; 3206788269814a678af976dfc7d6135993e172ce586Adam Cohen } 3216788269814a678af976dfc7d6135993e172ce586Adam Cohen 3226788269814a678af976dfc7d6135993e172ce586Adam Cohen if (mCurrentResizeFrame != null) { 3236788269814a678af976dfc7d6135993e172ce586Adam Cohen handled = true; 3246788269814a678af976dfc7d6135993e172ce586Adam Cohen switch (action) { 3256788269814a678af976dfc7d6135993e172ce586Adam Cohen case MotionEvent.ACTION_MOVE: 3266788269814a678af976dfc7d6135993e172ce586Adam Cohen mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown); 3276788269814a678af976dfc7d6135993e172ce586Adam Cohen break; 3286788269814a678af976dfc7d6135993e172ce586Adam Cohen case MotionEvent.ACTION_CANCEL: 3296788269814a678af976dfc7d6135993e172ce586Adam Cohen case MotionEvent.ACTION_UP: 330bebf042666cffe52039b875a549a582abd78a431Adam Cohen mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown); 331bebf042666cffe52039b875a549a582abd78a431Adam Cohen mCurrentResizeFrame.onTouchUp(); 3326788269814a678af976dfc7d6135993e172ce586Adam Cohen mCurrentResizeFrame = null; 3336788269814a678af976dfc7d6135993e172ce586Adam Cohen } 3346788269814a678af976dfc7d6135993e172ce586Adam Cohen } 3356788269814a678af976dfc7d6135993e172ce586Adam Cohen if (handled) return true; 3364db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato return mDragController.onTouchEvent(ev); 33791a9c9636f10f1e12cd1f660b2e330634fbdc7dcRomain Guy } 338ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy 33935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen /** 34035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * Determine the rect of the descendant in this DragLayer's coordinates 34135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * 34235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * @param descendant The descendant whose coordinates we want to find. 34335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * @param r The rect into which to place the results. 34435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * @return The factor by which this descendant is scaled relative to this DragLayer. 34535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen */ 346ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen public float getDescendantRectRelativeToSelf(View descendant, Rect r) { 347716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen mTmpXY[0] = 0; 348716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen mTmpXY[1] = 0; 349ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY); 3507d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen 3518dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen r.set(mTmpXY[0], mTmpXY[1], 3527d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen (int) (mTmpXY[0] + scale * descendant.getMeasuredWidth()), 3537d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen (int) (mTmpXY[1] + scale * descendant.getMeasuredHeight())); 354ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen return scale; 355716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen } 35676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 357307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen public float getLocationInDragLayer(View child, int[] loc) { 35835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen loc[0] = 0; 35935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen loc[1] = 0; 360307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen return getDescendantCoordRelativeToSelf(child, loc); 36135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen } 36235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen 3637d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) { 3647d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen return getDescendantCoordRelativeToSelf(descendant, coord, false); 3657d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen } 3667d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen 36735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen /** 36835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * Given a coordinate relative to the descendant, find the coordinate in this DragLayer's 36935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * coordinates. 37035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * 37135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * @param descendant The descendant to which the passed coordinate is relative. 37235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * @param coord The coordinate that we want mapped. 3737d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen * @param includeRootScroll Whether or not to account for the scroll of the root descendant: 3747d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen * sometimes this is relevant as in a child's coordinates within the root descendant. 375307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen * @return The factor by which this descendant is scaled relative to this DragLayer. Caution 376307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen * this scale factor is assumed to be equal in X and Y, and so if at any point this 377307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen * assumption fails, we will need to return a pair of scale factors. 37835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen */ 3797d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen public float getDescendantCoordRelativeToSelf(View descendant, int[] coord, 3807d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen boolean includeRootScroll) { 381c763c4e4d28c256d1368be3fc1c4526c8b9bd232Winson Chung return Utilities.getDescendantCoordRelativeToParent(descendant, this, 382c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung coord, includeRootScroll); 383c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung } 384c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung 3857d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen /** 3867d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen * Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}. 3877d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen */ 3887d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen public float mapCoordInSelfToDescendent(View descendant, int[] coord) { 389c763c4e4d28c256d1368be3fc1c4526c8b9bd232Winson Chung return Utilities.mapCoordInSelfToDescendent(descendant, this, coord); 39076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 39176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 3923e8f811f31a2275e778244427271f77f4116c08bAdam Cohen public void getViewRectRelativeToSelf(View v, Rect r) { 3933e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int[] loc = new int[2]; 3948dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen getLocationInWindow(loc); 3953e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int x = loc[0]; 3963e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int y = loc[1]; 397716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 3988dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen v.getLocationInWindow(loc); 3993e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int vX = loc[0]; 4003e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int vY = loc[1]; 401716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 4023e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int left = vX - x; 4033e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int top = vY - y; 4043e8f811f31a2275e778244427271f77f4116c08bAdam Cohen r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight()); 405716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen } 406716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 407ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy @Override 408ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy public boolean dispatchUnhandledMove(View focused, int direction) { 409ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy return mDragController.dispatchUnhandledMove(focused, direction); 410ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy } 411120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen 4126788269814a678af976dfc7d6135993e172ce586Adam Cohen public static class LayoutParams extends FrameLayout.LayoutParams { 4136788269814a678af976dfc7d6135993e172ce586Adam Cohen public int x, y; 4146788269814a678af976dfc7d6135993e172ce586Adam Cohen public boolean customPosition = false; 4156788269814a678af976dfc7d6135993e172ce586Adam Cohen 4166788269814a678af976dfc7d6135993e172ce586Adam Cohen /** 4176788269814a678af976dfc7d6135993e172ce586Adam Cohen * {@inheritDoc} 4186788269814a678af976dfc7d6135993e172ce586Adam Cohen */ 4196788269814a678af976dfc7d6135993e172ce586Adam Cohen public LayoutParams(int width, int height) { 4206788269814a678af976dfc7d6135993e172ce586Adam Cohen super(width, height); 4216788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4226788269814a678af976dfc7d6135993e172ce586Adam Cohen 4236788269814a678af976dfc7d6135993e172ce586Adam Cohen public void setWidth(int width) { 4246788269814a678af976dfc7d6135993e172ce586Adam Cohen this.width = width; 4256788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4266788269814a678af976dfc7d6135993e172ce586Adam Cohen 4276788269814a678af976dfc7d6135993e172ce586Adam Cohen public int getWidth() { 4286788269814a678af976dfc7d6135993e172ce586Adam Cohen return width; 4296788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4306788269814a678af976dfc7d6135993e172ce586Adam Cohen 4316788269814a678af976dfc7d6135993e172ce586Adam Cohen public void setHeight(int height) { 4326788269814a678af976dfc7d6135993e172ce586Adam Cohen this.height = height; 4336788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4346788269814a678af976dfc7d6135993e172ce586Adam Cohen 4356788269814a678af976dfc7d6135993e172ce586Adam Cohen public int getHeight() { 4366788269814a678af976dfc7d6135993e172ce586Adam Cohen return height; 4376788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4386788269814a678af976dfc7d6135993e172ce586Adam Cohen 4396788269814a678af976dfc7d6135993e172ce586Adam Cohen public void setX(int x) { 4406788269814a678af976dfc7d6135993e172ce586Adam Cohen this.x = x; 4416788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4426788269814a678af976dfc7d6135993e172ce586Adam Cohen 4436788269814a678af976dfc7d6135993e172ce586Adam Cohen public int getX() { 4446788269814a678af976dfc7d6135993e172ce586Adam Cohen return x; 4456788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4466788269814a678af976dfc7d6135993e172ce586Adam Cohen 4476788269814a678af976dfc7d6135993e172ce586Adam Cohen public void setY(int y) { 4486788269814a678af976dfc7d6135993e172ce586Adam Cohen this.y = y; 4496788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4506788269814a678af976dfc7d6135993e172ce586Adam Cohen 4516788269814a678af976dfc7d6135993e172ce586Adam Cohen public int getY() { 4526788269814a678af976dfc7d6135993e172ce586Adam Cohen return y; 4536788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4546788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4556788269814a678af976dfc7d6135993e172ce586Adam Cohen 4566788269814a678af976dfc7d6135993e172ce586Adam Cohen protected void onLayout(boolean changed, int l, int t, int r, int b) { 4576788269814a678af976dfc7d6135993e172ce586Adam Cohen super.onLayout(changed, l, t, r, b); 4586788269814a678af976dfc7d6135993e172ce586Adam Cohen int count = getChildCount(); 4596788269814a678af976dfc7d6135993e172ce586Adam Cohen for (int i = 0; i < count; i++) { 4606788269814a678af976dfc7d6135993e172ce586Adam Cohen View child = getChildAt(i); 4616788269814a678af976dfc7d6135993e172ce586Adam Cohen final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams(); 4626788269814a678af976dfc7d6135993e172ce586Adam Cohen if (flp instanceof LayoutParams) { 4636788269814a678af976dfc7d6135993e172ce586Adam Cohen final LayoutParams lp = (LayoutParams) flp; 4646788269814a678af976dfc7d6135993e172ce586Adam Cohen if (lp.customPosition) { 4656788269814a678af976dfc7d6135993e172ce586Adam Cohen child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height); 4666788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4676788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4686788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4696788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4706788269814a678af976dfc7d6135993e172ce586Adam Cohen 4716788269814a678af976dfc7d6135993e172ce586Adam Cohen public void clearAllResizeFrames() { 4726788269814a678af976dfc7d6135993e172ce586Adam Cohen if (mResizeFrames.size() > 0) { 4736788269814a678af976dfc7d6135993e172ce586Adam Cohen for (AppWidgetResizeFrame frame: mResizeFrames) { 474bebf042666cffe52039b875a549a582abd78a431Adam Cohen frame.commitResize(); 4756788269814a678af976dfc7d6135993e172ce586Adam Cohen removeView(frame); 4766788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4776788269814a678af976dfc7d6135993e172ce586Adam Cohen mResizeFrames.clear(); 4786788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4796788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4806788269814a678af976dfc7d6135993e172ce586Adam Cohen 4816788269814a678af976dfc7d6135993e172ce586Adam Cohen public boolean hasResizeFrames() { 4826788269814a678af976dfc7d6135993e172ce586Adam Cohen return mResizeFrames.size() > 0; 4836788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4846788269814a678af976dfc7d6135993e172ce586Adam Cohen 4856788269814a678af976dfc7d6135993e172ce586Adam Cohen public boolean isWidgetBeingResized() { 4866788269814a678af976dfc7d6135993e172ce586Adam Cohen return mCurrentResizeFrame != null; 4876788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4886788269814a678af976dfc7d6135993e172ce586Adam Cohen 4896788269814a678af976dfc7d6135993e172ce586Adam Cohen public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget, 4906788269814a678af976dfc7d6135993e172ce586Adam Cohen CellLayout cellLayout) { 4916788269814a678af976dfc7d6135993e172ce586Adam Cohen AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(), 4923a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka widget, cellLayout, this); 4936788269814a678af976dfc7d6135993e172ce586Adam Cohen 4946788269814a678af976dfc7d6135993e172ce586Adam Cohen LayoutParams lp = new LayoutParams(-1, -1); 4956788269814a678af976dfc7d6135993e172ce586Adam Cohen lp.customPosition = true; 4966788269814a678af976dfc7d6135993e172ce586Adam Cohen 4976788269814a678af976dfc7d6135993e172ce586Adam Cohen addView(resizeFrame, lp); 4986788269814a678af976dfc7d6135993e172ce586Adam Cohen mResizeFrames.add(resizeFrame); 4996788269814a678af976dfc7d6135993e172ce586Adam Cohen 5006788269814a678af976dfc7d6135993e172ce586Adam Cohen resizeFrame.snapToWidget(false); 5016788269814a678af976dfc7d6135993e172ce586Adam Cohen } 502716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 503716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen public void animateViewIntoPosition(DragView dragView, final View child) { 50428f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen animateViewIntoPosition(dragView, child, null, null); 505557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung } 506ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen 5077bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha, 5087bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable, 5097bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung int duration) { 510b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen Rect r = new Rect(); 511b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen getViewRectRelativeToSelf(dragView, r); 512b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen final int fromX = r.left; 513b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen final int fromY = r.top; 514b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen 5157bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung animateViewIntoPosition(dragView, fromX, fromY, pos[0], pos[1], alpha, 1, 1, scaleX, scaleY, 516ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen onFinishRunnable, animationEndStyle, duration, null); 517ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 518ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 519557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung public void animateViewIntoPosition(DragView dragView, final View child, 52028f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen final Runnable onFinishAnimationRunnable, View anchorView) { 52128f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, anchorView); 522ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen } 523ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen 524ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen public void animateViewIntoPosition(DragView dragView, final View child, int duration, 5256441de0ec2a71862798dd51180d0811b42edd514Adam Cohen final Runnable onFinishAnimationRunnable, View anchorView) { 526a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka ShortcutAndWidgetContainer parentChildren = (ShortcutAndWidgetContainer) child.getParent(); 527716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 528eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung parentChildren.measureChild(child); 529716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 5303e8f811f31a2275e778244427271f77f4116c08bAdam Cohen Rect r = new Rect(); 5313e8f811f31a2275e778244427271f77f4116c08bAdam Cohen getViewRectRelativeToSelf(dragView, r); 532716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 533716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen int coord[] = new int[2]; 534307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen float childScale = child.getScaleX(); 535307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen coord[0] = lp.x + (int) (child.getMeasuredWidth() * (1 - childScale) / 2); 536307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen coord[1] = lp.y + (int) (child.getMeasuredHeight() * (1 - childScale) / 2); 537eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung 5388dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen // Since the child hasn't necessarily been laid out, we force the lp to be updated with 539ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen // the correct coordinates (above) and use these to determine the final location 540557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord); 541307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen // We need to account for the scale of the child itself, as the above only accounts for 542307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen // for the scale in parents. 543307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen scale *= childScale; 544ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen int toX = coord[0]; 545ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen int toY = coord[1]; 546eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung float toScale = scale; 5474497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn if (child instanceof TextView) { 5484497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn TextView tv = (TextView) child; 549eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung // Account for the source scale of the icon (ie. from AllApps to Workspace, in which 550eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung // the workspace may have smaller icon bounds). 551eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung toScale = scale / dragView.getIntrinsicIconScaleFactor(); 5524497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn 5534497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn // The child may be scaled (always about the center of the view) so to account for it, 5544497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn // we have to offset the position by the scaled size. Once we do that, we can center 5554497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn // the drag view about the scaled child view. 556eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung toY += Math.round(toScale * tv.getPaddingTop()); 557eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung toY -= dragView.getMeasuredHeight() * (1 - toScale) / 2; 5584497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2; 5594497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn } else if (child instanceof FolderIcon) { 560ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung // Account for holographic blur padding on the drag view 5615f8afe6280eae34620067696173e71943e1a30a3Winson Chung toY += Math.round(scale * (child.getPaddingTop() - dragView.getDragRegionTop())); 562307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen toY -= scale * Workspace.DRAG_BITMAP_PADDING / 2; 563307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen toY -= (1 - scale) * dragView.getMeasuredHeight() / 2; 564ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung // Center in the x coordinate about the target's drawable 565ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2; 566ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen } else { 567ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen toY -= (Math.round(scale * (dragView.getHeight() - child.getMeasuredHeight()))) / 2; 568ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen toX -= (Math.round(scale * (dragView.getMeasuredWidth() 569ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen - child.getMeasuredWidth()))) / 2; 570ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen } 571716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 572ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen final int fromX = r.left; 573ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen final int fromY = r.top; 574716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen child.setVisibility(INVISIBLE); 5758dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen Runnable onCompleteRunnable = new Runnable() { 5768dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen public void run() { 5778dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen child.setVisibility(VISIBLE); 578d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen if (onFinishAnimationRunnable != null) { 579d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen onFinishAnimationRunnable.run(); 580d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen } 5818dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen } 5828dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen }; 583eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, toScale, toScale, 584d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView); 585557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung } 586557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung 587d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen public void animateViewIntoPosition(final DragView view, final int fromX, final int fromY, 588ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen final int toX, final int toY, float finalAlpha, float initScaleX, float initScaleY, 589ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen float finalScaleX, float finalScaleY, Runnable onCompleteRunnable, 590ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen int animationEndStyle, int duration, View anchorView) { 5918dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen Rect from = new Rect(fromX, fromY, fromX + 5928dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen view.getMeasuredWidth(), fromY + view.getMeasuredHeight()); 5933e8f811f31a2275e778244427271f77f4116c08bAdam Cohen Rect to = new Rect(toX, toY, toX + view.getMeasuredWidth(), toY + view.getMeasuredHeight()); 594ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen animateView(view, from, to, finalAlpha, initScaleX, initScaleY, finalScaleX, finalScaleY, duration, 595ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen null, null, onCompleteRunnable, animationEndStyle, anchorView); 5963e8f811f31a2275e778244427271f77f4116c08bAdam Cohen } 5973e8f811f31a2275e778244427271f77f4116c08bAdam Cohen 598b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen /** 599b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * This method animates a view at the end of a drag and drop animation. 600b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * 601b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param view The view to be animated. This view is drawn directly into DragLayer, and so 602b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * doesn't need to be a child of DragLayer. 603b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param from The initial location of the view. Only the left and top parameters are used. 604b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param to The final location of the view. Only the left and top parameters are used. This 605b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * location doesn't account for scaling, and so should be centered about the desired 606b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * final location (including scaling). 607b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param finalAlpha The final alpha of the view, in case we want it to fade as it animates. 608b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param finalScale The final scale of the view. The view is scaled about its center. 609b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param duration The duration of the animation. 610b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param motionInterpolator The interpolator to use for the location of the view. 611b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param alphaInterpolator The interpolator to use for the alpha of the view. 612b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param onCompleteRunnable Optional runnable to run on animation completion. 613b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param fadeOut Whether or not to fade out the view once the animation completes. If true, 614b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * the runnable will execute after the view is faded out. 6156441de0ec2a71862798dd51180d0811b42edd514Adam Cohen * @param anchorView If not null, this represents the view which the animated view stays 6166441de0ec2a71862798dd51180d0811b42edd514Adam Cohen * anchored to in case scrolling is currently taking place. Note: currently this is 6176441de0ec2a71862798dd51180d0811b42edd514Adam Cohen * only used for the X dimension for the case of the workspace. 618b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen */ 6197bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung public void animateView(final DragView view, final Rect from, final Rect to, 6207bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final float finalAlpha, final float initScaleX, final float initScaleY, 6217bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final float finalScaleX, final float finalScaleY, int duration, 6227bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final Interpolator motionInterpolator, final Interpolator alphaInterpolator, 6237bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final Runnable onCompleteRunnable, final int animationEndStyle, View anchorView) { 6247bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung 625716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen // Calculate the duration of the animation based on the object's distance 6263e8f811f31a2275e778244427271f77f4116c08bAdam Cohen final float dist = (float) Math.sqrt(Math.pow(to.left - from.left, 2) + 6273e8f811f31a2275e778244427271f77f4116c08bAdam Cohen Math.pow(to.top - from.top, 2)); 628716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen final Resources res = getResources(); 629716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist); 6303e8f811f31a2275e778244427271f77f4116c08bAdam Cohen 6313e8f811f31a2275e778244427271f77f4116c08bAdam Cohen // If duration < 0, this is a cue to compute the duration based on the distance 6323e8f811f31a2275e778244427271f77f4116c08bAdam Cohen if (duration < 0) { 6333e8f811f31a2275e778244427271f77f4116c08bAdam Cohen duration = res.getInteger(R.integer.config_dropAnimMaxDuration); 6343e8f811f31a2275e778244427271f77f4116c08bAdam Cohen if (dist < maxDist) { 6358dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen duration *= mCubicEaseOutInterpolator.getInterpolation(dist / maxDist); 6363e8f811f31a2275e778244427271f77f4116c08bAdam Cohen } 63761b0c69d3fe331d3de338322396d5de691d58613Winson Chung duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration)); 638716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen } 639716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 640043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Fall back to cubic ease out interpolator for the animation if none is specified 641043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung TimeInterpolator interpolator = null; 6423e8f811f31a2275e778244427271f77f4116c08bAdam Cohen if (alphaInterpolator == null || motionInterpolator == null) { 643043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung interpolator = mCubicEaseOutInterpolator; 6443e8f811f31a2275e778244427271f77f4116c08bAdam Cohen } 645716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 646043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Animate the view 6477bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final float initAlpha = view.getAlpha(); 648043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float dropViewScale = view.getScaleX(); 649043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung AnimatorUpdateListener updateCb = new AnimatorUpdateListener() { 650043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung @Override 651716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen public void onAnimationUpdate(ValueAnimator animation) { 652716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen final float percent = (Float) animation.getAnimatedValue(); 6537bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final int width = view.getMeasuredWidth(); 6547bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final int height = view.getMeasuredHeight(); 655716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 6563e8f811f31a2275e778244427271f77f4116c08bAdam Cohen float alphaPercent = alphaInterpolator == null ? percent : 6573e8f811f31a2275e778244427271f77f4116c08bAdam Cohen alphaInterpolator.getInterpolation(percent); 6583e8f811f31a2275e778244427271f77f4116c08bAdam Cohen float motionPercent = motionInterpolator == null ? percent : 6593e8f811f31a2275e778244427271f77f4116c08bAdam Cohen motionInterpolator.getInterpolation(percent); 660a1cdab039292f3d809528c0e2e38580b37864d8dWinson Chung 6617bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float initialScaleX = initScaleX * dropViewScale; 6627bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float initialScaleY = initScaleY * dropViewScale; 6637bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float scaleX = finalScaleX * percent + initialScaleX * (1 - percent); 6647bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float scaleY = finalScaleY * percent + initialScaleY * (1 - percent); 6657bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float alpha = finalAlpha * alphaPercent + initAlpha * (1 - alphaPercent); 6667bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung 6677bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float fromLeft = from.left + (initialScaleX - 1f) * width / 2; 6687bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float fromTop = from.top + (initialScaleY - 1f) * height / 2; 6697bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung 6707bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung int x = (int) (fromLeft + Math.round(((to.left - fromLeft) * motionPercent))); 6717bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung int y = (int) (fromTop + Math.round(((to.top - fromTop) * motionPercent))); 6727bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung 67328f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen int anchorAdjust = mAnchorView == null ? 0 : (int) (mAnchorView.getScaleX() * 67428f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen (mAnchorViewInitialScrollX - mAnchorView.getScrollX())); 67528f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen 67628f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen int xPos = x - mDropView.getScrollX() + anchorAdjust; 6777bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung int yPos = y - mDropView.getScrollY(); 6787bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung 6797bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropView.setTranslationX(xPos); 6807bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropView.setTranslationY(yPos); 6817bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropView.setScaleX(scaleX); 6827bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropView.setScaleY(scaleY); 6837bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropView.setAlpha(alpha); 684716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen } 685043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung }; 686043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung animateView(view, updateCb, duration, interpolator, onCompleteRunnable, animationEndStyle, 687043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung anchorView); 688043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 689043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 690043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public void animateView(final DragView view, AnimatorUpdateListener updateCb, int duration, 691043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung TimeInterpolator interpolator, final Runnable onCompleteRunnable, 692043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final int animationEndStyle, View anchorView) { 693043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Clean up the previous animations 694043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mDropAnim != null) mDropAnim.cancel(); 695043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mFadeOutAnim != null) mFadeOutAnim.cancel(); 696043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 697043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Show the drop view if it was previously hidden 698043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropView = view; 699043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropView.cancelAnimation(); 700043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropView.resetLayoutParams(); 701043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 702043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Set the anchor view if the page is scrolling 703043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (anchorView != null) { 704043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mAnchorViewInitialScrollX = anchorView.getScrollX(); 705043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 706043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mAnchorView = anchorView; 707043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 708043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Create and start the animation 709043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropAnim = new ValueAnimator(); 710043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropAnim.setInterpolator(interpolator); 711043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropAnim.setDuration(duration); 712043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropAnim.setFloatValues(0f, 1f); 713043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropAnim.addUpdateListener(updateCb); 7143e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mDropAnim.addListener(new AnimatorListenerAdapter() { 7153e8f811f31a2275e778244427271f77f4116c08bAdam Cohen public void onAnimationEnd(Animator animation) { 7168dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen if (onCompleteRunnable != null) { 7178dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen onCompleteRunnable.run(); 7188dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen } 719ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen switch (animationEndStyle) { 720ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen case ANIMATION_END_DISAPPEAR: 721ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen clearAnimatedView(); 722ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen break; 723ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen case ANIMATION_END_FADE_OUT: 7248dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen fadeOutDragView(); 725ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen break; 726ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen case ANIMATION_END_REMAIN_VISIBLE: 727ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen break; 7283e8f811f31a2275e778244427271f77f4116c08bAdam Cohen } 7293e8f811f31a2275e778244427271f77f4116c08bAdam Cohen } 7303e8f811f31a2275e778244427271f77f4116c08bAdam Cohen }); 731716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen mDropAnim.start(); 732716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen } 733716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 734ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen public void clearAnimatedView() { 7357bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung if (mDropAnim != null) { 7367bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropAnim.cancel(); 7377bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung } 7387bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung if (mDropView != null) { 739043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDragController.onDeferredEndDrag(mDropView); 7407bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung } 741ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen mDropView = null; 742ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen invalidate(); 743ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 744ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 745ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen public View getAnimatedView() { 746ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen return mDropView; 747ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 748ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 7498dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen private void fadeOutDragView() { 7508dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim = new ValueAnimator(); 7518dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim.setDuration(150); 7528dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim.setFloatValues(0f, 1f); 7538dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim.removeAllUpdateListeners(); 7548dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim.addUpdateListener(new AnimatorUpdateListener() { 7558dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen public void onAnimationUpdate(ValueAnimator animation) { 7568dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen final float percent = (Float) animation.getAnimatedValue(); 7577bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung 7587bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float alpha = 1 - percent; 7597bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropView.setAlpha(alpha); 7608dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen } 7618dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen }); 7628dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim.addListener(new AnimatorListenerAdapter() { 7638dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen public void onAnimationEnd(Animator animation) { 7647bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung if (mDropView != null) { 765043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDragController.onDeferredEndDrag(mDropView); 7667bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung } 7678dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mDropView = null; 768ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen invalidate(); 7698dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen } 7708dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen }); 7718dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim.start(); 7728dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen } 7738dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen 774716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen @Override 7758b805b17158886035b38261eb611d8641701ae43Michael Jurka public void onChildViewAdded(View parent, View child) { 77621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen updateChildIndices(); 77721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen } 77821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen 77921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen @Override 7808b805b17158886035b38261eb611d8641701ae43Michael Jurka public void onChildViewRemoved(View parent, View child) { 78121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen updateChildIndices(); 78221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen } 78321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen 784432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen @Override 785432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen public void bringChildToFront(View child) { 786432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen super.bringChildToFront(child); 787432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen updateChildIndices(); 788432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen } 789432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen 79021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen private void updateChildIndices() { 791432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen mTopViewIndex = -1; 79255bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi int childCount = getChildCount(); 79355bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi for (int i = 0; i < childCount; i++) { 794432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen if (getChildAt(i) instanceof DragView || 795432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen getChildAt(i) == mOverlayView) { 796432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen mTopViewIndex = i; 79755bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi } 79821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen } 79921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen } 80021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen 80121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen @Override 80221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen protected int getChildDrawingOrder(int childCount, int i) { 803432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen // i represents the current draw iteration 804432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen if (mTopViewIndex == -1) { 805432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen // in general we do nothing 80621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen return i; 807432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen } else if (i == childCount - 1) { 808432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen // if we have a top index, we return it when drawing last item (highest z-order) 809432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen return mTopViewIndex; 810432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen } else if (i < mTopViewIndex) { 81121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen return i; 81255bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi } else { 813432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen // for indexes greater than the top index, we fetch one item above to shift for the 814432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen // displacement of the top index 815432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen return i + 1; 81621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen } 81721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen } 818360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 819360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung private boolean mInScrollArea; 820360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung private Drawable mLeftHoverDrawable; 821360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung private Drawable mRightHoverDrawable; 822360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 823360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung void onEnterScrollArea(int direction) { 824360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung mInScrollArea = true; 825360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung invalidate(); 826360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung } 827360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 828360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung void onExitScrollArea() { 829360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung mInScrollArea = false; 830360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung invalidate(); 831360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung } 832360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 833fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung /** 834fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung * Note: this is a reimplementation of View.isLayoutRtl() since that is currently hidden api. 835fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung */ 836fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung private boolean isLayoutRtl() { 837fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); 838fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung } 839fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung 840360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung @Override 841360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung protected void dispatchDraw(Canvas canvas) { 842360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung super.dispatchDraw(canvas); 843360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 844e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler if (mInScrollArea && !LauncherAppState.getInstance().isScreenLarge()) { 845360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung Workspace workspace = mLauncher.getWorkspace(); 84661a9a5c359e3e14cb1beaf43dbdb54e00911fe80Adam Cohen int width = getMeasuredWidth(); 847360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung Rect childRect = new Rect(); 848360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung getDescendantRectRelativeToSelf(workspace.getChildAt(0), childRect); 849360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 850360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung int page = workspace.getNextPage(); 851fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung final boolean isRtl = isLayoutRtl(); 852fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung CellLayout leftPage = (CellLayout) workspace.getChildAt(isRtl ? page + 1 : page - 1); 853fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung CellLayout rightPage = (CellLayout) workspace.getChildAt(isRtl ? page - 1 : page + 1); 854360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 855360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung if (leftPage != null && leftPage.getIsDragOverlapping()) { 856360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung mLeftHoverDrawable.setBounds(0, childRect.top, 857360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung mLeftHoverDrawable.getIntrinsicWidth(), childRect.bottom); 858360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung mLeftHoverDrawable.draw(canvas); 859360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung } else if (rightPage != null && rightPage.getIsDragOverlapping()) { 860360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung mRightHoverDrawable.setBounds(width - mRightHoverDrawable.getIntrinsicWidth(), 861360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung childRect.top, width, childRect.bottom); 862360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung mRightHoverDrawable.draw(canvas); 863360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung } 864360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung } 865360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung } 866b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen 867b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen public void setTouchCompleteListener(TouchCompleteListener listener) { 868b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen mTouchCompleteListener = listener; 869b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen } 870b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen 871b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen public interface TouchCompleteListener { 872b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen public void onTouchComplete(); 873b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen } 87431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project} 875