1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher3; 18 19 import android.annotation.SuppressLint; 20 import android.content.Context; 21 import android.support.annotation.IntDef; 22 import android.util.AttributeSet; 23 import android.view.MotionEvent; 24 import android.view.View; 25 import android.widget.LinearLayout; 26 27 import com.android.launcher3.dragndrop.DragLayer; 28 29 import java.lang.annotation.Retention; 30 import java.lang.annotation.RetentionPolicy; 31 32 /** 33 * Base class for a View which shows a floating UI on top of the launcher UI. 34 */ 35 public abstract class AbstractFloatingView extends LinearLayout { 36 37 @IntDef(flag = true, value = { 38 TYPE_FOLDER, 39 TYPE_POPUP_CONTAINER_WITH_ARROW, 40 TYPE_WIDGETS_BOTTOM_SHEET 41 }) 42 @Retention(RetentionPolicy.SOURCE) 43 public @interface FloatingViewType {} 44 public static final int TYPE_FOLDER = 1 << 0; 45 public static final int TYPE_POPUP_CONTAINER_WITH_ARROW = 1 << 1; 46 public static final int TYPE_WIDGETS_BOTTOM_SHEET = 1 << 2; 47 48 protected boolean mIsOpen; 49 AbstractFloatingView(Context context, AttributeSet attrs)50 public AbstractFloatingView(Context context, AttributeSet attrs) { 51 super(context, attrs); 52 } 53 AbstractFloatingView(Context context, AttributeSet attrs, int defStyleAttr)54 public AbstractFloatingView(Context context, AttributeSet attrs, int defStyleAttr) { 55 super(context, attrs, defStyleAttr); 56 } 57 58 /** 59 * We need to handle touch events to prevent them from falling through to the workspace below. 60 */ 61 @SuppressLint("ClickableViewAccessibility") 62 @Override onTouchEvent(MotionEvent ev)63 public boolean onTouchEvent(MotionEvent ev) { 64 return true; 65 } 66 close(boolean animate)67 public final void close(boolean animate) { 68 animate &= !Utilities.isPowerSaverOn(getContext()); 69 handleClose(animate); 70 Launcher.getLauncher(getContext()).getUserEventDispatcher().resetElapsedContainerMillis(); 71 } 72 handleClose(boolean animate)73 protected abstract void handleClose(boolean animate); 74 75 /** 76 * If the view is current handling keyboard, return the active target, null otherwise 77 */ getActiveTextView()78 public ExtendedEditText getActiveTextView() { 79 return null; 80 } 81 82 83 /** 84 * Any additional view (outside of this container) where touch should be allowed while this 85 * view is visible. 86 */ getExtendedTouchView()87 public View getExtendedTouchView() { 88 return null; 89 } 90 isOpen()91 public final boolean isOpen() { 92 return mIsOpen; 93 } 94 onWidgetsBound()95 protected void onWidgetsBound() { 96 } 97 isOfType(@loatingViewType int type)98 protected abstract boolean isOfType(@FloatingViewType int type); 99 getOpenView( Launcher launcher, @FloatingViewType int type)100 protected static <T extends AbstractFloatingView> T getOpenView( 101 Launcher launcher, @FloatingViewType int type) { 102 DragLayer dragLayer = launcher.getDragLayer(); 103 // Iterate in reverse order. AbstractFloatingView is added later to the dragLayer, 104 // and will be one of the last views. 105 for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) { 106 View child = dragLayer.getChildAt(i); 107 if (child instanceof AbstractFloatingView) { 108 AbstractFloatingView view = (AbstractFloatingView) child; 109 if (view.isOfType(type) && view.isOpen()) { 110 return (T) view; 111 } 112 } 113 } 114 return null; 115 } 116 closeOpenContainer(Launcher launcher, @FloatingViewType int type)117 public static void closeOpenContainer(Launcher launcher, @FloatingViewType int type) { 118 AbstractFloatingView view = getOpenView(launcher, type); 119 if (view != null) { 120 view.close(true); 121 } 122 } 123 closeAllOpenViews(Launcher launcher, boolean animate)124 public static void closeAllOpenViews(Launcher launcher, boolean animate) { 125 DragLayer dragLayer = launcher.getDragLayer(); 126 // Iterate in reverse order. AbstractFloatingView is added later to the dragLayer, 127 // and will be one of the last views. 128 for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) { 129 View child = dragLayer.getChildAt(i); 130 if (child instanceof AbstractFloatingView) { 131 ((AbstractFloatingView) child).close(animate); 132 } 133 } 134 } 135 closeAllOpenViews(Launcher launcher)136 public static void closeAllOpenViews(Launcher launcher) { 137 closeAllOpenViews(launcher, true); 138 } 139 getTopOpenView(Launcher launcher)140 public static AbstractFloatingView getTopOpenView(Launcher launcher) { 141 return getOpenView(launcher, TYPE_FOLDER | TYPE_POPUP_CONTAINER_WITH_ARROW 142 | TYPE_WIDGETS_BOTTOM_SHEET); 143 } 144 getLogContainerType()145 public abstract int getLogContainerType(); 146 } 147