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 41bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohenimport com.android.launcher3.InsettableFrameLayout.LayoutParams; 42bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen 431d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohenimport java.util.ArrayList; 446788269814a678af976dfc7d6135993e172ce586Adam Cohen 4531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/** 460e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka * A ViewGroup that coordinates dragging across its descendants 4731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 48a6d0492e5f0dd4e1b43d4034a770241dc65f8f8cAdam Cohenpublic class DragLayer extends InsettableFrameLayout { 49120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen private DragController mDragController; 50120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen private int[] mTmpXY = new int[2]; 5131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 52716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen private int mXDown, mYDown; 53716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen private Launcher mLauncher; 54716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 556788269814a678af976dfc7d6135993e172ce586Adam Cohen // Variables relating to resizing widgets 566788269814a678af976dfc7d6135993e172ce586Adam Cohen private final ArrayList<AppWidgetResizeFrame> mResizeFrames = 576788269814a678af976dfc7d6135993e172ce586Adam Cohen new ArrayList<AppWidgetResizeFrame>(); 586788269814a678af976dfc7d6135993e172ce586Adam Cohen private AppWidgetResizeFrame mCurrentResizeFrame; 59716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 60716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen // Variables relating to animation of views after drop 61716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen private ValueAnimator mDropAnim = null; 628dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen private ValueAnimator mFadeOutAnim = null; 638dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen private TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f); 647bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung private DragView mDropView = null; 656441de0ec2a71862798dd51180d0811b42edd514Adam Cohen private int mAnchorViewInitialScrollX = 0; 666441de0ec2a71862798dd51180d0811b42edd514Adam Cohen private View mAnchorView = null; 678dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen 683371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen private boolean mHoverPointClosesFolder = false; 693371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen private Rect mHitRect = new Rect(); 70ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen public static final int ANIMATION_END_DISAPPEAR = 0; 71ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen public static final int ANIMATION_END_FADE_OUT = 1; 72ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen public static final int ANIMATION_END_REMAIN_VISIBLE = 2; 736788269814a678af976dfc7d6135993e172ce586Adam Cohen 74b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen private TouchCompleteListener mTouchCompleteListener; 75b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen 76432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen private View mOverlayView; 77432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen private int mTopViewIndex; 782d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen private int mChildCountOnLastUpdate = -1; 7955bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi 806c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen // Darkening scrim 816c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen private Drawable mBackground; 826c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen private float mBackgroundAlpha = 0; 836c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen 848cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen // Related to adjacent page hints 858cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen private boolean mInScrollArea; 868cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen private boolean mShowPageHints; 878cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen private Drawable mLeftHoverDrawable; 888cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen private Drawable mRightHoverDrawable; 898cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen private Drawable mLeftHoverDrawableActive; 908cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen private Drawable mRightHoverDrawableActive; 918cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen 92c2d6e897dbcb96b7b629e42002966368fbda2f95Adam Cohen private boolean mBlockTouches = false; 93c2d6e897dbcb96b7b629e42002966368fbda2f95Adam Cohen 9431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 9531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Used to create a new DragLayer from XML. 9631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 9731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param context The application's context. 980e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka * @param attrs The attributes set containing the Workspace's customization values. 9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 10031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public DragLayer(Context context, AttributeSet attrs) { 10131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super(context, attrs); 102be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung 103be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung // Disable multitouch across the workspace/all apps/customize tray 104be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung setMotionEventSplittingEnabled(false); 10521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen setChildrenDrawingOrderEnabled(true); 106360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 1076c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen final Resources res = getResources(); 108c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen mLeftHoverDrawable = res.getDrawable(R.drawable.page_hover_left); 109c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen mRightHoverDrawable = res.getDrawable(R.drawable.page_hover_right); 110c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen mLeftHoverDrawableActive = res.getDrawable(R.drawable.page_hover_left_active); 111c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen mRightHoverDrawableActive = res.getDrawable(R.drawable.page_hover_right_active); 1126c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen mBackground = res.getDrawable(R.drawable.apps_customize_bg); 11331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 11431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 1154c98d9235d164680186180974719f551cf935d08Winson Chung public void setup(Launcher launcher, DragController controller) { 1164c98d9235d164680186180974719f551cf935d08Winson Chung mLauncher = launcher; 11700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mDragController = controller; 11831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 11976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 12031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public boolean dispatchKeyEvent(KeyEvent event) { 12200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event); 12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 125b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen public void showOverlayView(View overlayView) { 126432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 127b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen mOverlayView = overlayView; 128b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen addView(overlayView, lp); 129b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen 130b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen // ensure that the overlay view stays on top. we can't use drawing order for this 131b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen // because in API level 16 touch dispatch doesn't respect drawing order. 132b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen mOverlayView.bringToFront(); 133432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen } 134432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen 135432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen public void dismissOverlayView() { 136432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen removeView(mOverlayView); 137432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen } 138432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen 1393371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) { 1403371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect); 1413371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) { 1423371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return true; 1433371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 1443371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return false; 1453371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 1463371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 1473371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen private boolean isEventOverFolder(Folder folder, MotionEvent ev) { 1483371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen getDescendantRectRelativeToSelf(folder, 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 155c2d6e897dbcb96b7b629e42002966368fbda2f95Adam Cohen public void setBlockTouch(boolean block) { 156c2d6e897dbcb96b7b629e42002966368fbda2f95Adam Cohen mBlockTouches = block; 157c2d6e897dbcb96b7b629e42002966368fbda2f95Adam Cohen } 158c2d6e897dbcb96b7b629e42002966368fbda2f95Adam Cohen 15976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private boolean handleTouchDown(MotionEvent ev, boolean intercept) { 1606788269814a678af976dfc7d6135993e172ce586Adam Cohen Rect hitRect = new Rect(); 1616788269814a678af976dfc7d6135993e172ce586Adam Cohen int x = (int) ev.getX(); 1626788269814a678af976dfc7d6135993e172ce586Adam Cohen int y = (int) ev.getY(); 1636788269814a678af976dfc7d6135993e172ce586Adam Cohen 164c2d6e897dbcb96b7b629e42002966368fbda2f95Adam Cohen if (mBlockTouches) { 165c2d6e897dbcb96b7b629e42002966368fbda2f95Adam Cohen return true; 166c2d6e897dbcb96b7b629e42002966368fbda2f95Adam Cohen } 167c2d6e897dbcb96b7b629e42002966368fbda2f95Adam 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(); 182424418bb50ccf5d9270650b70cc51f423da51a65Sunny Goyal if (currentFolder != null && intercept) { 1831d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen if (currentFolder.isEditingName()) { 1843371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (!isEventOverFolderTextRegion(currentFolder, ev)) { 1851d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen currentFolder.dismissEditingName(); 18676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return true; 1872801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 1882801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 18976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 1901d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen getDescendantRectRelativeToSelf(currentFolder, hitRect); 1913371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (!isEventOverFolder(currentFolder, ev)) { 19276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mLauncher.closeFolder(); 19376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return true; 19476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 1952801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 1966788269814a678af976dfc7d6135993e172ce586Adam Cohen return false; 1976788269814a678af976dfc7d6135993e172ce586Adam Cohen } 1986788269814a678af976dfc7d6135993e172ce586Adam Cohen 19931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 20031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public boolean onInterceptTouchEvent(MotionEvent ev) { 201b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen int action = ev.getAction(); 202b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen 203b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen if (action == MotionEvent.ACTION_DOWN) { 20476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen if (handleTouchDown(ev, true)) { 2056788269814a678af976dfc7d6135993e172ce586Adam Cohen return true; 206d1837cc69eb222371afdd30890f7215d117510f2Patrick Dubroy } 207b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 208b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen if (mTouchCompleteListener != null) { 209b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen mTouchCompleteListener.onTouchComplete(); 210b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen } 211b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen mTouchCompleteListener = null; 2121b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen } 2136788269814a678af976dfc7d6135993e172ce586Adam Cohen clearAllResizeFrames(); 2144db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato return mDragController.onInterceptTouchEvent(ev); 21531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 21631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 21731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 2183371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen public boolean onInterceptHoverEvent(MotionEvent ev) { 219023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka if (mLauncher == null || mLauncher.getWorkspace() == null) { 220023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka return false; 221023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka } 2223371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen Folder currentFolder = mLauncher.getWorkspace().getOpenFolder(); 2233371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (currentFolder == null) { 2243371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return false; 2253371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } else { 2268b805b17158886035b38261eb611d8641701ae43Michael Jurka AccessibilityManager accessibilityManager = (AccessibilityManager) 2278b805b17158886035b38261eb611d8641701ae43Michael Jurka getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); 2288b805b17158886035b38261eb611d8641701ae43Michael Jurka if (accessibilityManager.isTouchExplorationEnabled()) { 2293371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen final int action = ev.getAction(); 2303371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen boolean isOverFolder; 2313371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen switch (action) { 2323371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen case MotionEvent.ACTION_HOVER_ENTER: 2333371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen isOverFolder = isEventOverFolder(currentFolder, ev); 2343371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (!isOverFolder) { 2353371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName()); 2363371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen mHoverPointClosesFolder = true; 2373371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return true; 2383371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 239693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu mHoverPointClosesFolder = false; 240693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu break; 2413371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen case MotionEvent.ACTION_HOVER_MOVE: 2423371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen isOverFolder = isEventOverFolder(currentFolder, ev); 2433371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (!isOverFolder && !mHoverPointClosesFolder) { 2443371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName()); 2453371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen mHoverPointClosesFolder = true; 2463371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return true; 247693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu } else if (!isOverFolder) { 2483371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return true; 2493371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 250693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu mHoverPointClosesFolder = false; 2513371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 2523371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 2533371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 2543371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return false; 2553371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 2563371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 2573371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen private void sendTapOutsideFolderAccessibilityEvent(boolean isEditingName) { 2588b805b17158886035b38261eb611d8641701ae43Michael Jurka AccessibilityManager accessibilityManager = (AccessibilityManager) 2598b805b17158886035b38261eb611d8641701ae43Michael Jurka getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); 2608b805b17158886035b38261eb611d8641701ae43Michael Jurka if (accessibilityManager.isEnabled()) { 2613371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen int stringId = isEditingName ? R.string.folder_tap_to_rename : R.string.folder_tap_to_close; 2623371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen AccessibilityEvent event = AccessibilityEvent.obtain( 2633371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen AccessibilityEvent.TYPE_VIEW_FOCUSED); 2643371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen onInitializeAccessibilityEvent(event); 2658b805b17158886035b38261eb611d8641701ae43Michael Jurka event.getText().add(getContext().getString(stringId)); 2668b805b17158886035b38261eb611d8641701ae43Michael Jurka accessibilityManager.sendAccessibilityEvent(event); 2673371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 26883ca480941b3dd635b62347008fc8d7859d82002Winson Chung } 26983ca480941b3dd635b62347008fc8d7859d82002Winson Chung 27083ca480941b3dd635b62347008fc8d7859d82002Winson Chung @Override 27183ca480941b3dd635b62347008fc8d7859d82002Winson Chung public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { 27283ca480941b3dd635b62347008fc8d7859d82002Winson Chung Folder currentFolder = mLauncher.getWorkspace().getOpenFolder(); 27383ca480941b3dd635b62347008fc8d7859d82002Winson Chung if (currentFolder != null) { 27483ca480941b3dd635b62347008fc8d7859d82002Winson Chung if (child == currentFolder) { 27583ca480941b3dd635b62347008fc8d7859d82002Winson Chung return super.onRequestSendAccessibilityEvent(child, event); 27683ca480941b3dd635b62347008fc8d7859d82002Winson Chung } 27783ca480941b3dd635b62347008fc8d7859d82002Winson Chung // Skip propagating onRequestSendAccessibilityEvent all for other children 27883ca480941b3dd635b62347008fc8d7859d82002Winson Chung // when a folder is open 27983ca480941b3dd635b62347008fc8d7859d82002Winson Chung return false; 28083ca480941b3dd635b62347008fc8d7859d82002Winson Chung } 28183ca480941b3dd635b62347008fc8d7859d82002Winson Chung return super.onRequestSendAccessibilityEvent(child, event); 28283ca480941b3dd635b62347008fc8d7859d82002Winson Chung } 28383ca480941b3dd635b62347008fc8d7859d82002Winson Chung 28483ca480941b3dd635b62347008fc8d7859d82002Winson Chung @Override 28583ca480941b3dd635b62347008fc8d7859d82002Winson Chung public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) { 28683ca480941b3dd635b62347008fc8d7859d82002Winson Chung Folder currentFolder = mLauncher.getWorkspace().getOpenFolder(); 28783ca480941b3dd635b62347008fc8d7859d82002Winson Chung if (currentFolder != null) { 28883ca480941b3dd635b62347008fc8d7859d82002Winson Chung // Only add the folder as a child for accessibility when it is open 28983ca480941b3dd635b62347008fc8d7859d82002Winson Chung childrenForAccessibility.add(currentFolder); 29083ca480941b3dd635b62347008fc8d7859d82002Winson Chung } else { 29183ca480941b3dd635b62347008fc8d7859d82002Winson Chung super.addChildrenForAccessibility(childrenForAccessibility); 29283ca480941b3dd635b62347008fc8d7859d82002Winson Chung } 2933371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 2943371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 2953371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen @Override 2963371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen public boolean onHoverEvent(MotionEvent ev) { 2973371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen // If we've received this, we've already done the necessary handling 2983371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen // in onInterceptHoverEvent. Return true to consume the event. 2993371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return false; 3003371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 3013371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 3023371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen @Override 30331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public boolean onTouchEvent(MotionEvent ev) { 3046788269814a678af976dfc7d6135993e172ce586Adam Cohen boolean handled = false; 3056788269814a678af976dfc7d6135993e172ce586Adam Cohen int action = ev.getAction(); 3066788269814a678af976dfc7d6135993e172ce586Adam Cohen 3076788269814a678af976dfc7d6135993e172ce586Adam Cohen int x = (int) ev.getX(); 3086788269814a678af976dfc7d6135993e172ce586Adam Cohen int y = (int) ev.getY(); 3096788269814a678af976dfc7d6135993e172ce586Adam Cohen 310c2d6e897dbcb96b7b629e42002966368fbda2f95Adam Cohen if (mBlockTouches) { 311c2d6e897dbcb96b7b629e42002966368fbda2f95Adam Cohen return true; 312c2d6e897dbcb96b7b629e42002966368fbda2f95Adam Cohen } 313c2d6e897dbcb96b7b629e42002966368fbda2f95Adam Cohen 314b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen if (action == MotionEvent.ACTION_DOWN) { 315b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen if (handleTouchDown(ev, false)) { 316b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen return true; 317b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen } 318b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 319b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen if (mTouchCompleteListener != null) { 320b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen mTouchCompleteListener.onTouchComplete(); 3216788269814a678af976dfc7d6135993e172ce586Adam Cohen } 322b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen mTouchCompleteListener = null; 3236788269814a678af976dfc7d6135993e172ce586Adam Cohen } 3246788269814a678af976dfc7d6135993e172ce586Adam Cohen 3256788269814a678af976dfc7d6135993e172ce586Adam Cohen if (mCurrentResizeFrame != null) { 3266788269814a678af976dfc7d6135993e172ce586Adam Cohen handled = true; 3276788269814a678af976dfc7d6135993e172ce586Adam Cohen switch (action) { 3286788269814a678af976dfc7d6135993e172ce586Adam Cohen case MotionEvent.ACTION_MOVE: 3296788269814a678af976dfc7d6135993e172ce586Adam Cohen mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown); 3306788269814a678af976dfc7d6135993e172ce586Adam Cohen break; 3316788269814a678af976dfc7d6135993e172ce586Adam Cohen case MotionEvent.ACTION_CANCEL: 3326788269814a678af976dfc7d6135993e172ce586Adam Cohen case MotionEvent.ACTION_UP: 333bebf042666cffe52039b875a549a582abd78a431Adam Cohen mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown); 334bebf042666cffe52039b875a549a582abd78a431Adam Cohen mCurrentResizeFrame.onTouchUp(); 3356788269814a678af976dfc7d6135993e172ce586Adam Cohen mCurrentResizeFrame = null; 3366788269814a678af976dfc7d6135993e172ce586Adam Cohen } 3376788269814a678af976dfc7d6135993e172ce586Adam Cohen } 3386788269814a678af976dfc7d6135993e172ce586Adam Cohen if (handled) return true; 3394db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato return mDragController.onTouchEvent(ev); 34091a9c9636f10f1e12cd1f660b2e330634fbdc7dcRomain Guy } 341ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy 34235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen /** 34335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * Determine the rect of the descendant in this DragLayer's coordinates 34435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * 34535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * @param descendant The descendant whose coordinates we want to find. 34635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * @param r The rect into which to place the results. 34735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * @return The factor by which this descendant is scaled relative to this DragLayer. 34835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen */ 349ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen public float getDescendantRectRelativeToSelf(View descendant, Rect r) { 350716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen mTmpXY[0] = 0; 351716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen mTmpXY[1] = 0; 352ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY); 3537d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen 3548dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen r.set(mTmpXY[0], mTmpXY[1], 3557d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen (int) (mTmpXY[0] + scale * descendant.getMeasuredWidth()), 3567d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen (int) (mTmpXY[1] + scale * descendant.getMeasuredHeight())); 357ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen return scale; 358716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen } 35976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 360307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen public float getLocationInDragLayer(View child, int[] loc) { 36135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen loc[0] = 0; 36235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen loc[1] = 0; 363307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen return getDescendantCoordRelativeToSelf(child, loc); 36435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen } 36535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen 3667d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) { 3677d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen return getDescendantCoordRelativeToSelf(descendant, coord, false); 3687d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen } 3697d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen 37035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen /** 37135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * Given a coordinate relative to the descendant, find the coordinate in this DragLayer's 37235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * coordinates. 37335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * 37435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * @param descendant The descendant to which the passed coordinate is relative. 37535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen * @param coord The coordinate that we want mapped. 3767d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen * @param includeRootScroll Whether or not to account for the scroll of the root descendant: 3777d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen * sometimes this is relevant as in a child's coordinates within the root descendant. 378307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen * @return The factor by which this descendant is scaled relative to this DragLayer. Caution 379307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen * this scale factor is assumed to be equal in X and Y, and so if at any point this 380307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen * assumption fails, we will need to return a pair of scale factors. 38135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen */ 3827d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen public float getDescendantCoordRelativeToSelf(View descendant, int[] coord, 3837d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen boolean includeRootScroll) { 384c763c4e4d28c256d1368be3fc1c4526c8b9bd232Winson Chung return Utilities.getDescendantCoordRelativeToParent(descendant, this, 385c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung coord, includeRootScroll); 386c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung } 387c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung 3887d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen /** 3897d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen * Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}. 3907d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen */ 3917d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen public float mapCoordInSelfToDescendent(View descendant, int[] coord) { 392c763c4e4d28c256d1368be3fc1c4526c8b9bd232Winson Chung return Utilities.mapCoordInSelfToDescendent(descendant, this, coord); 39376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 39476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 3953e8f811f31a2275e778244427271f77f4116c08bAdam Cohen public void getViewRectRelativeToSelf(View v, Rect r) { 3963e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int[] loc = new int[2]; 3978dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen getLocationInWindow(loc); 3983e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int x = loc[0]; 3993e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int y = loc[1]; 400716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 4018dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen v.getLocationInWindow(loc); 4023e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int vX = loc[0]; 4033e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int vY = loc[1]; 404716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 4053e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int left = vX - x; 4063e8f811f31a2275e778244427271f77f4116c08bAdam Cohen int top = vY - y; 4073e8f811f31a2275e778244427271f77f4116c08bAdam Cohen r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight()); 408716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen } 409716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 410ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy @Override 411ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy public boolean dispatchUnhandledMove(View focused, int direction) { 412ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy return mDragController.dispatchUnhandledMove(focused, direction); 413ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy } 414120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen 415bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen @Override 416bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen public LayoutParams generateLayoutParams(AttributeSet attrs) { 417bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen return new LayoutParams(getContext(), attrs); 418bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen } 419bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen 420bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen @Override 421bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen protected LayoutParams generateDefaultLayoutParams() { 422bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 423bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen } 424bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen 425bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen // Override to allow type-checking of LayoutParams. 426bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen @Override 427bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 428bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen return p instanceof LayoutParams; 429bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen } 430bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen 431bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen @Override 432bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 433bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen return new LayoutParams(p); 434bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen } 435bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen 436bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen public static class LayoutParams extends InsettableFrameLayout.LayoutParams { 4376788269814a678af976dfc7d6135993e172ce586Adam Cohen public int x, y; 4386788269814a678af976dfc7d6135993e172ce586Adam Cohen public boolean customPosition = false; 4396788269814a678af976dfc7d6135993e172ce586Adam Cohen 440bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen public LayoutParams(Context c, AttributeSet attrs) { 441bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen super(c, attrs); 442bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen } 443bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen 4446788269814a678af976dfc7d6135993e172ce586Adam Cohen public LayoutParams(int width, int height) { 4456788269814a678af976dfc7d6135993e172ce586Adam Cohen super(width, height); 4466788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4476788269814a678af976dfc7d6135993e172ce586Adam Cohen 448bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen public LayoutParams(ViewGroup.LayoutParams lp) { 449bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen super(lp); 450bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen } 451bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen 4526788269814a678af976dfc7d6135993e172ce586Adam Cohen public void setWidth(int width) { 4536788269814a678af976dfc7d6135993e172ce586Adam Cohen this.width = width; 4546788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4556788269814a678af976dfc7d6135993e172ce586Adam Cohen 4566788269814a678af976dfc7d6135993e172ce586Adam Cohen public int getWidth() { 4576788269814a678af976dfc7d6135993e172ce586Adam Cohen return width; 4586788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4596788269814a678af976dfc7d6135993e172ce586Adam Cohen 4606788269814a678af976dfc7d6135993e172ce586Adam Cohen public void setHeight(int height) { 4616788269814a678af976dfc7d6135993e172ce586Adam Cohen this.height = height; 4626788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4636788269814a678af976dfc7d6135993e172ce586Adam Cohen 4646788269814a678af976dfc7d6135993e172ce586Adam Cohen public int getHeight() { 4656788269814a678af976dfc7d6135993e172ce586Adam Cohen return height; 4666788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4676788269814a678af976dfc7d6135993e172ce586Adam Cohen 4686788269814a678af976dfc7d6135993e172ce586Adam Cohen public void setX(int x) { 4696788269814a678af976dfc7d6135993e172ce586Adam Cohen this.x = x; 4706788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4716788269814a678af976dfc7d6135993e172ce586Adam Cohen 4726788269814a678af976dfc7d6135993e172ce586Adam Cohen public int getX() { 4736788269814a678af976dfc7d6135993e172ce586Adam Cohen return x; 4746788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4756788269814a678af976dfc7d6135993e172ce586Adam Cohen 4766788269814a678af976dfc7d6135993e172ce586Adam Cohen public void setY(int y) { 4776788269814a678af976dfc7d6135993e172ce586Adam Cohen this.y = y; 4786788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4796788269814a678af976dfc7d6135993e172ce586Adam Cohen 4806788269814a678af976dfc7d6135993e172ce586Adam Cohen public int getY() { 4816788269814a678af976dfc7d6135993e172ce586Adam Cohen return y; 4826788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4836788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4846788269814a678af976dfc7d6135993e172ce586Adam Cohen 4856788269814a678af976dfc7d6135993e172ce586Adam Cohen protected void onLayout(boolean changed, int l, int t, int r, int b) { 4866788269814a678af976dfc7d6135993e172ce586Adam Cohen super.onLayout(changed, l, t, r, b); 4876788269814a678af976dfc7d6135993e172ce586Adam Cohen int count = getChildCount(); 4886788269814a678af976dfc7d6135993e172ce586Adam Cohen for (int i = 0; i < count; i++) { 4896788269814a678af976dfc7d6135993e172ce586Adam Cohen View child = getChildAt(i); 4906788269814a678af976dfc7d6135993e172ce586Adam Cohen final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams(); 4916788269814a678af976dfc7d6135993e172ce586Adam Cohen if (flp instanceof LayoutParams) { 4926788269814a678af976dfc7d6135993e172ce586Adam Cohen final LayoutParams lp = (LayoutParams) flp; 4936788269814a678af976dfc7d6135993e172ce586Adam Cohen if (lp.customPosition) { 4946788269814a678af976dfc7d6135993e172ce586Adam Cohen child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height); 4956788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4966788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4976788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4986788269814a678af976dfc7d6135993e172ce586Adam Cohen } 4996788269814a678af976dfc7d6135993e172ce586Adam Cohen 5006788269814a678af976dfc7d6135993e172ce586Adam Cohen public void clearAllResizeFrames() { 5016788269814a678af976dfc7d6135993e172ce586Adam Cohen if (mResizeFrames.size() > 0) { 5026788269814a678af976dfc7d6135993e172ce586Adam Cohen for (AppWidgetResizeFrame frame: mResizeFrames) { 503bebf042666cffe52039b875a549a582abd78a431Adam Cohen frame.commitResize(); 5046788269814a678af976dfc7d6135993e172ce586Adam Cohen removeView(frame); 5056788269814a678af976dfc7d6135993e172ce586Adam Cohen } 5066788269814a678af976dfc7d6135993e172ce586Adam Cohen mResizeFrames.clear(); 5076788269814a678af976dfc7d6135993e172ce586Adam Cohen } 5086788269814a678af976dfc7d6135993e172ce586Adam Cohen } 5096788269814a678af976dfc7d6135993e172ce586Adam Cohen 5106788269814a678af976dfc7d6135993e172ce586Adam Cohen public boolean hasResizeFrames() { 5116788269814a678af976dfc7d6135993e172ce586Adam Cohen return mResizeFrames.size() > 0; 5126788269814a678af976dfc7d6135993e172ce586Adam Cohen } 5136788269814a678af976dfc7d6135993e172ce586Adam Cohen 5146788269814a678af976dfc7d6135993e172ce586Adam Cohen public boolean isWidgetBeingResized() { 5156788269814a678af976dfc7d6135993e172ce586Adam Cohen return mCurrentResizeFrame != null; 5166788269814a678af976dfc7d6135993e172ce586Adam Cohen } 5176788269814a678af976dfc7d6135993e172ce586Adam Cohen 5186788269814a678af976dfc7d6135993e172ce586Adam Cohen public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget, 5196788269814a678af976dfc7d6135993e172ce586Adam Cohen CellLayout cellLayout) { 5206788269814a678af976dfc7d6135993e172ce586Adam Cohen AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(), 5213a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka widget, cellLayout, this); 5226788269814a678af976dfc7d6135993e172ce586Adam Cohen 5236788269814a678af976dfc7d6135993e172ce586Adam Cohen LayoutParams lp = new LayoutParams(-1, -1); 5246788269814a678af976dfc7d6135993e172ce586Adam Cohen lp.customPosition = true; 5256788269814a678af976dfc7d6135993e172ce586Adam Cohen 5266788269814a678af976dfc7d6135993e172ce586Adam Cohen addView(resizeFrame, lp); 5276788269814a678af976dfc7d6135993e172ce586Adam Cohen mResizeFrames.add(resizeFrame); 5286788269814a678af976dfc7d6135993e172ce586Adam Cohen 5296788269814a678af976dfc7d6135993e172ce586Adam Cohen resizeFrame.snapToWidget(false); 5306788269814a678af976dfc7d6135993e172ce586Adam Cohen } 531716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 532716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen public void animateViewIntoPosition(DragView dragView, final View child) { 53328f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen animateViewIntoPosition(dragView, child, null, null); 534557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung } 535ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen 5367bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha, 5377bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable, 5387bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung int duration) { 539b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen Rect r = new Rect(); 540b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen getViewRectRelativeToSelf(dragView, r); 541b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen final int fromX = r.left; 542b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen final int fromY = r.top; 543b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen 5447bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung animateViewIntoPosition(dragView, fromX, fromY, pos[0], pos[1], alpha, 1, 1, scaleX, scaleY, 545ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen onFinishRunnable, animationEndStyle, duration, null); 546ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 547ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 548557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung public void animateViewIntoPosition(DragView dragView, final View child, 54928f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen final Runnable onFinishAnimationRunnable, View anchorView) { 55028f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, anchorView); 551ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen } 552ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen 553ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen public void animateViewIntoPosition(DragView dragView, final View child, int duration, 5546441de0ec2a71862798dd51180d0811b42edd514Adam Cohen final Runnable onFinishAnimationRunnable, View anchorView) { 555a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka ShortcutAndWidgetContainer parentChildren = (ShortcutAndWidgetContainer) child.getParent(); 556716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); 557eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung parentChildren.measureChild(child); 558716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 5593e8f811f31a2275e778244427271f77f4116c08bAdam Cohen Rect r = new Rect(); 5603e8f811f31a2275e778244427271f77f4116c08bAdam Cohen getViewRectRelativeToSelf(dragView, r); 561716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 562716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen int coord[] = new int[2]; 563307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen float childScale = child.getScaleX(); 564307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen coord[0] = lp.x + (int) (child.getMeasuredWidth() * (1 - childScale) / 2); 565307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen coord[1] = lp.y + (int) (child.getMeasuredHeight() * (1 - childScale) / 2); 566eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung 5678dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen // Since the child hasn't necessarily been laid out, we force the lp to be updated with 568ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen // the correct coordinates (above) and use these to determine the final location 569557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord); 570307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen // We need to account for the scale of the child itself, as the above only accounts for 571307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen // for the scale in parents. 572307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen scale *= childScale; 573ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen int toX = coord[0]; 574ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen int toY = coord[1]; 575eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung float toScale = scale; 5764497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn if (child instanceof TextView) { 5774497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn TextView tv = (TextView) child; 578eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung // Account for the source scale of the icon (ie. from AllApps to Workspace, in which 579eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung // the workspace may have smaller icon bounds). 580eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung toScale = scale / dragView.getIntrinsicIconScaleFactor(); 5814497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn 5824497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn // The child may be scaled (always about the center of the view) so to account for it, 5834497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn // we have to offset the position by the scaled size. Once we do that, we can center 5844497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn // the drag view about the scaled child view. 585eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung toY += Math.round(toScale * tv.getPaddingTop()); 586eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung toY -= dragView.getMeasuredHeight() * (1 - toScale) / 2; 58795abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal if (dragView.getDragVisualizeOffset() != null) { 58895abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal toY -= Math.round(toScale * dragView.getDragVisualizeOffset().y); 58995abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal } 59095abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal 5914497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2; 5924497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn } else if (child instanceof FolderIcon) { 593ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung // Account for holographic blur padding on the drag view 5945f8afe6280eae34620067696173e71943e1a30a3Winson Chung toY += Math.round(scale * (child.getPaddingTop() - dragView.getDragRegionTop())); 595307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen toY -= scale * Workspace.DRAG_BITMAP_PADDING / 2; 596307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen toY -= (1 - scale) * dragView.getMeasuredHeight() / 2; 597ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung // Center in the x coordinate about the target's drawable 598ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2; 599ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen } else { 600ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen toY -= (Math.round(scale * (dragView.getHeight() - child.getMeasuredHeight()))) / 2; 601ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen toX -= (Math.round(scale * (dragView.getMeasuredWidth() 602ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen - child.getMeasuredWidth()))) / 2; 603ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen } 604716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 605ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen final int fromX = r.left; 606ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen final int fromY = r.top; 607716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen child.setVisibility(INVISIBLE); 6088dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen Runnable onCompleteRunnable = new Runnable() { 6098dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen public void run() { 6108dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen child.setVisibility(VISIBLE); 611d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen if (onFinishAnimationRunnable != null) { 612d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen onFinishAnimationRunnable.run(); 613d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen } 6148dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen } 6158dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen }; 616eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, toScale, toScale, 617d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView); 618557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung } 619557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung 620d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen public void animateViewIntoPosition(final DragView view, final int fromX, final int fromY, 621ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen final int toX, final int toY, float finalAlpha, float initScaleX, float initScaleY, 622ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen float finalScaleX, float finalScaleY, Runnable onCompleteRunnable, 623ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen int animationEndStyle, int duration, View anchorView) { 6248dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen Rect from = new Rect(fromX, fromY, fromX + 6258dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen view.getMeasuredWidth(), fromY + view.getMeasuredHeight()); 6263e8f811f31a2275e778244427271f77f4116c08bAdam Cohen Rect to = new Rect(toX, toY, toX + view.getMeasuredWidth(), toY + view.getMeasuredHeight()); 627ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen animateView(view, from, to, finalAlpha, initScaleX, initScaleY, finalScaleX, finalScaleY, duration, 628ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen null, null, onCompleteRunnable, animationEndStyle, anchorView); 6293e8f811f31a2275e778244427271f77f4116c08bAdam Cohen } 6303e8f811f31a2275e778244427271f77f4116c08bAdam Cohen 631b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen /** 632b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * This method animates a view at the end of a drag and drop animation. 633b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * 634b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param view The view to be animated. This view is drawn directly into DragLayer, and so 635b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * doesn't need to be a child of DragLayer. 636b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param from The initial location of the view. Only the left and top parameters are used. 637b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param to The final location of the view. Only the left and top parameters are used. This 638b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * location doesn't account for scaling, and so should be centered about the desired 639b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * final location (including scaling). 640b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param finalAlpha The final alpha of the view, in case we want it to fade as it animates. 641b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param finalScale The final scale of the view. The view is scaled about its center. 642b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param duration The duration of the animation. 643b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param motionInterpolator The interpolator to use for the location of the view. 644b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param alphaInterpolator The interpolator to use for the alpha of the view. 645b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param onCompleteRunnable Optional runnable to run on animation completion. 646b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * @param fadeOut Whether or not to fade out the view once the animation completes. If true, 647b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen * the runnable will execute after the view is faded out. 6486441de0ec2a71862798dd51180d0811b42edd514Adam Cohen * @param anchorView If not null, this represents the view which the animated view stays 6496441de0ec2a71862798dd51180d0811b42edd514Adam Cohen * anchored to in case scrolling is currently taking place. Note: currently this is 6506441de0ec2a71862798dd51180d0811b42edd514Adam Cohen * only used for the X dimension for the case of the workspace. 651b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen */ 6527bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung public void animateView(final DragView view, final Rect from, final Rect to, 6537bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final float finalAlpha, final float initScaleX, final float initScaleY, 6547bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final float finalScaleX, final float finalScaleY, int duration, 6557bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final Interpolator motionInterpolator, final Interpolator alphaInterpolator, 6567bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final Runnable onCompleteRunnable, final int animationEndStyle, View anchorView) { 6577bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung 658716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen // Calculate the duration of the animation based on the object's distance 6593e8f811f31a2275e778244427271f77f4116c08bAdam Cohen final float dist = (float) Math.sqrt(Math.pow(to.left - from.left, 2) + 6603e8f811f31a2275e778244427271f77f4116c08bAdam Cohen Math.pow(to.top - from.top, 2)); 661716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen final Resources res = getResources(); 662716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist); 6633e8f811f31a2275e778244427271f77f4116c08bAdam Cohen 6643e8f811f31a2275e778244427271f77f4116c08bAdam Cohen // If duration < 0, this is a cue to compute the duration based on the distance 6653e8f811f31a2275e778244427271f77f4116c08bAdam Cohen if (duration < 0) { 6663e8f811f31a2275e778244427271f77f4116c08bAdam Cohen duration = res.getInteger(R.integer.config_dropAnimMaxDuration); 6673e8f811f31a2275e778244427271f77f4116c08bAdam Cohen if (dist < maxDist) { 6688dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen duration *= mCubicEaseOutInterpolator.getInterpolation(dist / maxDist); 6693e8f811f31a2275e778244427271f77f4116c08bAdam Cohen } 67061b0c69d3fe331d3de338322396d5de691d58613Winson Chung duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration)); 671716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen } 672716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 673043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Fall back to cubic ease out interpolator for the animation if none is specified 674043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung TimeInterpolator interpolator = null; 6753e8f811f31a2275e778244427271f77f4116c08bAdam Cohen if (alphaInterpolator == null || motionInterpolator == null) { 676043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung interpolator = mCubicEaseOutInterpolator; 6773e8f811f31a2275e778244427271f77f4116c08bAdam Cohen } 678716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 679043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Animate the view 6807bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final float initAlpha = view.getAlpha(); 681043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float dropViewScale = view.getScaleX(); 682043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung AnimatorUpdateListener updateCb = new AnimatorUpdateListener() { 683043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung @Override 684716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen public void onAnimationUpdate(ValueAnimator animation) { 685716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen final float percent = (Float) animation.getAnimatedValue(); 6867bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final int width = view.getMeasuredWidth(); 6877bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung final int height = view.getMeasuredHeight(); 688716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 6893e8f811f31a2275e778244427271f77f4116c08bAdam Cohen float alphaPercent = alphaInterpolator == null ? percent : 6903e8f811f31a2275e778244427271f77f4116c08bAdam Cohen alphaInterpolator.getInterpolation(percent); 6913e8f811f31a2275e778244427271f77f4116c08bAdam Cohen float motionPercent = motionInterpolator == null ? percent : 6923e8f811f31a2275e778244427271f77f4116c08bAdam Cohen motionInterpolator.getInterpolation(percent); 693a1cdab039292f3d809528c0e2e38580b37864d8dWinson Chung 6947bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float initialScaleX = initScaleX * dropViewScale; 6957bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float initialScaleY = initScaleY * dropViewScale; 6967bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float scaleX = finalScaleX * percent + initialScaleX * (1 - percent); 6977bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float scaleY = finalScaleY * percent + initialScaleY * (1 - percent); 6987bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float alpha = finalAlpha * alphaPercent + initAlpha * (1 - alphaPercent); 6997bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung 7007bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float fromLeft = from.left + (initialScaleX - 1f) * width / 2; 7017bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float fromTop = from.top + (initialScaleY - 1f) * height / 2; 7027bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung 7037bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung int x = (int) (fromLeft + Math.round(((to.left - fromLeft) * motionPercent))); 7047bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung int y = (int) (fromTop + Math.round(((to.top - fromTop) * motionPercent))); 7057bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung 70628f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen int anchorAdjust = mAnchorView == null ? 0 : (int) (mAnchorView.getScaleX() * 70728f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen (mAnchorViewInitialScrollX - mAnchorView.getScrollX())); 70828f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen 70928f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen int xPos = x - mDropView.getScrollX() + anchorAdjust; 7107bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung int yPos = y - mDropView.getScrollY(); 7117bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung 7127bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropView.setTranslationX(xPos); 7137bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropView.setTranslationY(yPos); 7147bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropView.setScaleX(scaleX); 7157bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropView.setScaleY(scaleY); 7167bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropView.setAlpha(alpha); 717716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen } 718043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung }; 719043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung animateView(view, updateCb, duration, interpolator, onCompleteRunnable, animationEndStyle, 720043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung anchorView); 721043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 722043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 723043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public void animateView(final DragView view, AnimatorUpdateListener updateCb, int duration, 724043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung TimeInterpolator interpolator, final Runnable onCompleteRunnable, 725043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final int animationEndStyle, View anchorView) { 726043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Clean up the previous animations 727043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mDropAnim != null) mDropAnim.cancel(); 728043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mFadeOutAnim != null) mFadeOutAnim.cancel(); 729043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 730043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Show the drop view if it was previously hidden 731043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropView = view; 732043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropView.cancelAnimation(); 733043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropView.resetLayoutParams(); 734043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 735043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Set the anchor view if the page is scrolling 736043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (anchorView != null) { 737043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mAnchorViewInitialScrollX = anchorView.getScrollX(); 738043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 739043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mAnchorView = anchorView; 740043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 741043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Create and start the animation 742043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropAnim = new ValueAnimator(); 743043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropAnim.setInterpolator(interpolator); 744043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropAnim.setDuration(duration); 745043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropAnim.setFloatValues(0f, 1f); 746043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDropAnim.addUpdateListener(updateCb); 7473e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mDropAnim.addListener(new AnimatorListenerAdapter() { 7483e8f811f31a2275e778244427271f77f4116c08bAdam Cohen public void onAnimationEnd(Animator animation) { 7498dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen if (onCompleteRunnable != null) { 7508dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen onCompleteRunnable.run(); 7518dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen } 752ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen switch (animationEndStyle) { 753ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen case ANIMATION_END_DISAPPEAR: 754ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen clearAnimatedView(); 755ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen break; 756ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen case ANIMATION_END_FADE_OUT: 7578dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen fadeOutDragView(); 758ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen break; 759ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen case ANIMATION_END_REMAIN_VISIBLE: 760ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen break; 7613e8f811f31a2275e778244427271f77f4116c08bAdam Cohen } 7623e8f811f31a2275e778244427271f77f4116c08bAdam Cohen } 7633e8f811f31a2275e778244427271f77f4116c08bAdam Cohen }); 764716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen mDropAnim.start(); 765716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen } 766716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen 767ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen public void clearAnimatedView() { 7687bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung if (mDropAnim != null) { 7697bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropAnim.cancel(); 7707bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung } 7717bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung if (mDropView != null) { 7722d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen mDragController.onDeferredEndDrag(mDropView); 7737bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung } 774ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen mDropView = null; 775ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen invalidate(); 776ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 777ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 778ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen public View getAnimatedView() { 779ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen return mDropView; 780ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 781ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 7828dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen private void fadeOutDragView() { 7838dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim = new ValueAnimator(); 7848dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim.setDuration(150); 7858dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim.setFloatValues(0f, 1f); 7868dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim.removeAllUpdateListeners(); 7878dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim.addUpdateListener(new AnimatorUpdateListener() { 7888dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen public void onAnimationUpdate(ValueAnimator animation) { 7898dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen final float percent = (Float) animation.getAnimatedValue(); 7907bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung 7917bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung float alpha = 1 - percent; 7927bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung mDropView.setAlpha(alpha); 7938dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen } 7948dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen }); 7958dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim.addListener(new AnimatorListenerAdapter() { 7968dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen public void onAnimationEnd(Animator animation) { 7977bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung if (mDropView != null) { 798043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDragController.onDeferredEndDrag(mDropView); 7997bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung } 8008dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mDropView = null; 801ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen invalidate(); 8028dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen } 8038dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen }); 8048dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mFadeOutAnim.start(); 8058dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen } 8068dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen 807716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen @Override 8088b805b17158886035b38261eb611d8641701ae43Michael Jurka public void onChildViewAdded(View parent, View child) { 809a6d0492e5f0dd4e1b43d4034a770241dc65f8f8cAdam Cohen super.onChildViewAdded(parent, child); 810b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen if (mOverlayView != null) { 811b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen // ensure that the overlay view stays on top. we can't use drawing order for this 812b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen // because in API level 16 touch dispatch doesn't respect drawing order. 813b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen mOverlayView.bringToFront(); 814b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen } 81521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen updateChildIndices(); 81621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen } 81721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen 81821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen @Override 8198b805b17158886035b38261eb611d8641701ae43Michael Jurka public void onChildViewRemoved(View parent, View child) { 82021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen updateChildIndices(); 82121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen } 82221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen 823432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen @Override 824432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen public void bringChildToFront(View child) { 825432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen super.bringChildToFront(child); 826b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen if (child != mOverlayView && mOverlayView != null) { 827b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen // ensure that the overlay view stays on top. we can't use drawing order for this 828b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen // because in API level 16 touch dispatch doesn't respect drawing order. 829b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen mOverlayView.bringToFront(); 830b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen } 831432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen updateChildIndices(); 832432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen } 833432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen 83421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen private void updateChildIndices() { 835432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen mTopViewIndex = -1; 83655bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi int childCount = getChildCount(); 83755bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi for (int i = 0; i < childCount; i++) { 838b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen if (getChildAt(i) instanceof DragView) { 839432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen mTopViewIndex = i; 84055bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi } 84121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen } 8422d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen mChildCountOnLastUpdate = childCount; 84321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen } 84421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen 84521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen @Override 84621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen protected int getChildDrawingOrder(int childCount, int i) { 8472d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen if (mChildCountOnLastUpdate != childCount) { 8482d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen // between platform versions 17 and 18, behavior for onChildViewRemoved / Added changed. 8492d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen // Pre-18, the child was not added / removed by the time of those callbacks. We need to 8502d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen // force update our representation of things here to avoid crashing on pre-18 devices 8512d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen // in certain instances. 8522d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen updateChildIndices(); 8532d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen } 8542d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen 855432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen // i represents the current draw iteration 856432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen if (mTopViewIndex == -1) { 857432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen // in general we do nothing 85821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen return i; 859432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen } else if (i == childCount - 1) { 860432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen // if we have a top index, we return it when drawing last item (highest z-order) 861432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen return mTopViewIndex; 862432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen } else if (i < mTopViewIndex) { 86321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen return i; 86455bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi } else { 865432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen // for indexes greater than the top index, we fetch one item above to shift for the 866432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen // displacement of the top index 867432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen return i + 1; 86821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen } 86921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen } 870360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 871360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung void onEnterScrollArea(int direction) { 872360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung mInScrollArea = true; 873360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung invalidate(); 874360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung } 875360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 876360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung void onExitScrollArea() { 877360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung mInScrollArea = false; 878360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung invalidate(); 879360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung } 880360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 881c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen void showPageHints() { 882c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen mShowPageHints = true; 883c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen invalidate(); 884c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen } 885c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen 886c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen void hidePageHints() { 887c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen mShowPageHints = false; 888c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen invalidate(); 889c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen } 890c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen 891fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung /** 892fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung * Note: this is a reimplementation of View.isLayoutRtl() since that is currently hidden api. 893fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung */ 894fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung private boolean isLayoutRtl() { 895fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); 896fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung } 897fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung 898360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung @Override 899360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung protected void dispatchDraw(Canvas canvas) { 9006c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen // Draw the background gradient below children. 9016c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen if (mBackground != null && mBackgroundAlpha > 0.0f) { 9026c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen int alpha = (int) (mBackgroundAlpha * 255); 9036c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen mBackground.setAlpha(alpha); 9046c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen mBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); 9056c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen mBackground.draw(canvas); 9066c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen } 9076c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen 908360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung super.dispatchDraw(canvas); 9098cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen } 910360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 9118cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen private void drawPageHints(Canvas canvas) { 912c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen if (mShowPageHints) { 913360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung Workspace workspace = mLauncher.getWorkspace(); 91461a9a5c359e3e14cb1beaf43dbdb54e00911fe80Adam Cohen int width = getMeasuredWidth(); 915360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung Rect childRect = new Rect(); 916c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen getDescendantRectRelativeToSelf(workspace.getChildAt(workspace.getChildCount() - 1), 917c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen childRect); 918360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 919360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung int page = workspace.getNextPage(); 920fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung final boolean isRtl = isLayoutRtl(); 921fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung CellLayout leftPage = (CellLayout) workspace.getChildAt(isRtl ? page + 1 : page - 1); 922fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung CellLayout rightPage = (CellLayout) workspace.getChildAt(isRtl ? page - 1 : page + 1); 923360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung 924c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen if (leftPage != null && leftPage.isDragTarget()) { 925c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen Drawable left = mInScrollArea && leftPage.getIsDragOverlapping() ? 926c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen mLeftHoverDrawableActive : mLeftHoverDrawable; 927c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen left.setBounds(0, childRect.top, 928c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen left.getIntrinsicWidth(), childRect.bottom); 929c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen left.draw(canvas); 930c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen } 931c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen if (rightPage != null && rightPage.isDragTarget()) { 932c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen Drawable right = mInScrollArea && rightPage.getIsDragOverlapping() ? 933c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen mRightHoverDrawableActive : mRightHoverDrawable; 934c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen right.setBounds(width - right.getIntrinsicWidth(), 935360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung childRect.top, width, childRect.bottom); 936c50438c802355dff714b04f42a32e518cb9e91d8Adam Cohen right.draw(canvas); 937360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung } 938360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung } 939360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung } 940b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen 9418cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 9428cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen boolean ret = super.drawChild(canvas, child, drawingTime); 9438cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen 9448cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen // We want to draw the page hints above the workspace, but below the drag view. 9458cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen if (child instanceof Workspace) { 9468cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen drawPageHints(canvas); 9478cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen } 9488cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen return ret; 9498cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen } 9508cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen 9516c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen public void setBackgroundAlpha(float alpha) { 9526c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen if (alpha != mBackgroundAlpha) { 9536c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen mBackgroundAlpha = alpha; 9546c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen invalidate(); 9556c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen } 9566c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen } 9576c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen 9586c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen public float getBackgroundAlpha() { 9596c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen return mBackgroundAlpha; 9606c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen } 9616c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen 962b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen public void setTouchCompleteListener(TouchCompleteListener listener) { 963b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen mTouchCompleteListener = listener; 964b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen } 965b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen 966b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen public interface TouchCompleteListener { 967b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen public void onTouchComplete(); 968b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen } 96931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project} 970