diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2018-03-14 12:30:11 -0700 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2018-03-15 17:29:43 -0700 |
commit | 0b0847b272a37ed115504956be5ce44a96b5784c (patch) | |
tree | 03014c8d93aca5eadcdb1838808a3a035f41619a /src/com/android/launcher3/views | |
parent | 39b5534b96a889393b3bafd84dda6333ea8eb157 (diff) | |
download | android_packages_apps_Trebuchet-0b0847b272a37ed115504956be5ce44a96b5784c.tar.gz android_packages_apps_Trebuchet-0b0847b272a37ed115504956be5ce44a96b5784c.tar.bz2 android_packages_apps_Trebuchet-0b0847b272a37ed115504956be5ce44a96b5784c.zip |
Fixing taskMenu and taskView clicks in fallback activity
> Extracting common methods from Launcher & DragLauncher to base classes
> Remoting some dependencies on Launcher and using the base class instead
Change-Id: I121cacf8a14190b4703cda60bdeb4f79eee69ded
Diffstat (limited to 'src/com/android/launcher3/views')
-rw-r--r-- | src/com/android/launcher3/views/BaseDragLayer.java | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java new file mode 100644 index 000000000..489e59e75 --- /dev/null +++ b/src/com/android/launcher3/views/BaseDragLayer.java @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.views; + +import android.content.Context; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; +import android.widget.FrameLayout; + +import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.BaseActivity; +import com.android.launcher3.BaseDraggingActivity; +import com.android.launcher3.InsettableFrameLayout; +import com.android.launcher3.Utilities; +import com.android.launcher3.util.TouchController; + +import java.util.ArrayList; + +/** + * A viewgroup with utility methods for drag-n-drop and touch interception + */ +public abstract class BaseDragLayer<T extends BaseDraggingActivity> extends InsettableFrameLayout { + + protected final int[] mTmpXY = new int[2]; + protected final Rect mHitRect = new Rect(); + + protected final T mActivity; + + protected TouchController[] mControllers; + protected TouchController mActiveController; + private TouchCompleteListener mTouchCompleteListener; + + public BaseDragLayer(Context context, AttributeSet attrs) { + super(context, attrs); + mActivity = (T) BaseActivity.fromContext(context); + } + + + public boolean isEventOverView(View view, MotionEvent ev) { + getDescendantRectRelativeToSelf(view, mHitRect); + return mHitRect.contains((int) ev.getX(), (int) ev.getY()); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + int action = ev.getAction(); + + if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + if (mTouchCompleteListener != null) { + mTouchCompleteListener.onTouchComplete(); + } + mTouchCompleteListener = null; + } else if (action == MotionEvent.ACTION_DOWN) { + mActivity.finishAutoCancelActionMode(); + } + return findActiveController(ev); + } + + protected boolean findActiveController(MotionEvent ev) { + mActiveController = null; + + AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity); + if (topView != null && topView.onControllerInterceptTouchEvent(ev)) { + mActiveController = topView; + return true; + } + + for (TouchController controller : mControllers) { + if (controller.onControllerInterceptTouchEvent(ev)) { + mActiveController = controller; + return true; + } + } + return false; + } + + @Override + public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { + // Shortcuts can appear above folder + View topView = AbstractFloatingView.getTopOpenView(mActivity); + if (topView != null) { + if (child == topView) { + return super.onRequestSendAccessibilityEvent(child, event); + } + // Skip propagating onRequestSendAccessibilityEvent for all other children + // which are not topView + return false; + } + return super.onRequestSendAccessibilityEvent(child, event); + } + + @Override + public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) { + View topView = AbstractFloatingView.getTopOpenView(mActivity); + if (topView != null) { + // Only add the top view as a child for accessibility when it is open + childrenForAccessibility.add(topView); + } else { + super.addChildrenForAccessibility(childrenForAccessibility); + } + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + int action = ev.getAction(); + if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + if (mTouchCompleteListener != null) { + mTouchCompleteListener.onTouchComplete(); + } + mTouchCompleteListener = null; + } + + if (mActiveController != null) { + return mActiveController.onControllerTouchEvent(ev); + } else { + // In case no child view handled the touch event, we may not get onIntercept anymore + return findActiveController(ev); + } + } + + /** + * Determine the rect of the descendant in this DragLayer's coordinates + * + * @param descendant The descendant whose coordinates we want to find. + * @param r The rect into which to place the results. + * @return The factor by which this descendant is scaled relative to this DragLayer. + */ + public float getDescendantRectRelativeToSelf(View descendant, Rect r) { + mTmpXY[0] = 0; + mTmpXY[1] = 0; + float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY); + + r.set(mTmpXY[0], mTmpXY[1], + (int) (mTmpXY[0] + scale * descendant.getMeasuredWidth()), + (int) (mTmpXY[1] + scale * descendant.getMeasuredHeight())); + return scale; + } + + public float getLocationInDragLayer(View child, int[] loc) { + loc[0] = 0; + loc[1] = 0; + return getDescendantCoordRelativeToSelf(child, loc); + } + + public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) { + return getDescendantCoordRelativeToSelf(descendant, coord, false); + } + + /** + * Given a coordinate relative to the descendant, find the coordinate in this DragLayer's + * coordinates. + * + * @param descendant The descendant to which the passed coordinate is relative. + * @param coord The coordinate that we want mapped. + * @param includeRootScroll Whether or not to account for the scroll of the root descendant: + * sometimes this is relevant as in a child's coordinates within the root descendant. + * @return The factor by which this descendant is scaled relative to this DragLayer. Caution + * this scale factor is assumed to be equal in X and Y, and so if at any point this + * assumption fails, we will need to return a pair of scale factors. + */ + public float getDescendantCoordRelativeToSelf(View descendant, int[] coord, + boolean includeRootScroll) { + return Utilities.getDescendantCoordRelativeToAncestor(descendant, this, + coord, includeRootScroll); + } + + /** + * Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}. + */ + public void mapCoordInSelfToDescendant(View descendant, int[] coord) { + Utilities.mapCoordInSelfToDescendant(descendant, this, coord); + } + + public void getViewRectRelativeToSelf(View v, Rect r) { + int[] loc = new int[2]; + getLocationInWindow(loc); + int x = loc[0]; + int y = loc[1]; + + v.getLocationInWindow(loc); + int vX = loc[0]; + int vY = loc[1]; + + int left = vX - x; + int top = vY - y; + r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight()); + } + + @Override + public boolean dispatchUnhandledMove(View focused, int direction) { + // Consume the unhandled move if a container is open, to avoid switching pages underneath. + return AbstractFloatingView.getTopOpenView(mActivity) != null; + } + + @Override + protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { + View topView = AbstractFloatingView.getTopOpenView(mActivity); + if (topView != null) { + return topView.requestFocus(direction, previouslyFocusedRect); + } else { + return super.onRequestFocusInDescendants(direction, previouslyFocusedRect); + } + } + + @Override + public void addFocusables(ArrayList<View> views, int direction, int focusableMode) { + View topView = AbstractFloatingView.getTopOpenView(mActivity); + if (topView != null) { + topView.addFocusables(views, direction); + } else { + super.addFocusables(views, direction, focusableMode); + } + } + + public void setTouchCompleteListener(TouchCompleteListener listener) { + mTouchCompleteListener = listener; + } + + public interface TouchCompleteListener { + void onTouchComplete(); + } + + @Override + public LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + @Override + protected LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + } + + // Override to allow type-checking of LayoutParams. + @Override + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams; + } + + @Override + protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return new LayoutParams(p); + } + + public static class LayoutParams extends InsettableFrameLayout.LayoutParams { + public int x, y; + public boolean customPosition = false; + + public LayoutParams(Context c, AttributeSet attrs) { + super(c, attrs); + } + + public LayoutParams(int width, int height) { + super(width, height); + } + + public LayoutParams(ViewGroup.LayoutParams lp) { + super(lp); + } + + public void setWidth(int width) { + this.width = width; + } + + public int getWidth() { + return width; + } + + public void setHeight(int height) { + this.height = height; + } + + public int getHeight() { + return height; + } + + public void setX(int x) { + this.x = x; + } + + public int getX() { + return x; + } + + public void setY(int y) { + this.y = y; + } + + public int getY() { + return y; + } + } + + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + int count = getChildCount(); + for (int i = 0; i < count; i++) { + View child = getChildAt(i); + final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams(); + if (flp instanceof LayoutParams) { + final LayoutParams lp = (LayoutParams) flp; + if (lp.customPosition) { + child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height); + } + } + } + } +} |