1 /* 2 * Copyright (C) 2017 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 package com.android.launcher3.widget; 17 18 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; 19 20 import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound; 21 import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; 22 23 import android.content.Context; 24 import android.graphics.Point; 25 import android.util.AttributeSet; 26 import android.view.View; 27 import android.view.View.OnClickListener; 28 import android.view.View.OnLongClickListener; 29 import android.widget.Toast; 30 31 import com.android.launcher3.DragSource; 32 import com.android.launcher3.DropTarget.DragObject; 33 import com.android.launcher3.ItemInfo; 34 import com.android.launcher3.R; 35 import com.android.launcher3.Utilities; 36 import com.android.launcher3.dragndrop.DragOptions; 37 import com.android.launcher3.popup.PopupDataProvider; 38 import com.android.launcher3.touch.ItemLongClickListener; 39 import com.android.launcher3.uioverrides.WallpaperColorInfo; 40 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; 41 import com.android.launcher3.userevent.nano.LauncherLogProto.Target; 42 import com.android.launcher3.util.SystemUiController; 43 import com.android.launcher3.util.Themes; 44 import com.android.launcher3.views.AbstractSlideInView; 45 import com.android.launcher3.views.BaseDragLayer; 46 47 /** 48 * Base class for various widgets popup 49 */ 50 abstract class BaseWidgetSheet extends AbstractSlideInView 51 implements OnClickListener, OnLongClickListener, DragSource, 52 PopupDataProvider.PopupDataChangeListener { 53 54 55 /* Touch handling related member variables. */ 56 private Toast mWidgetInstructionToast; 57 58 protected final View mColorScrim; 59 BaseWidgetSheet(Context context, AttributeSet attrs, int defStyleAttr)60 public BaseWidgetSheet(Context context, AttributeSet attrs, int defStyleAttr) { 61 super(context, attrs, defStyleAttr); 62 mColorScrim = createColorScrim(context); 63 } 64 65 @Override onAttachedToWindow()66 protected void onAttachedToWindow() { 67 super.onAttachedToWindow(); 68 mLauncher.getPopupDataProvider().setChangeListener(this); 69 } 70 71 @Override onDetachedFromWindow()72 protected void onDetachedFromWindow() { 73 super.onDetachedFromWindow(); 74 mLauncher.getPopupDataProvider().setChangeListener(null); 75 } 76 77 @Override onClick(View v)78 public final void onClick(View v) { 79 // Let the user know that they have to long press to add a widget 80 if (mWidgetInstructionToast != null) { 81 mWidgetInstructionToast.cancel(); 82 } 83 84 CharSequence msg = Utilities.wrapForTts( 85 getContext().getText(R.string.long_press_widget_to_add), 86 getContext().getString(R.string.long_accessible_way_to_add)); 87 mWidgetInstructionToast = Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT); 88 mWidgetInstructionToast.show(); 89 } 90 91 @Override onLongClick(View v)92 public boolean onLongClick(View v) { 93 if (!ItemLongClickListener.canStartDrag(mLauncher)) return false; 94 95 if (v instanceof WidgetCell) { 96 return beginDraggingWidget((WidgetCell) v); 97 } 98 return true; 99 } 100 attachToContainer()101 protected void attachToContainer() { 102 getPopupContainer().addView(mColorScrim); 103 getPopupContainer().addView(this); 104 } 105 setTranslationShift(float translationShift)106 protected void setTranslationShift(float translationShift) { 107 super.setTranslationShift(translationShift); 108 mColorScrim.setAlpha(1 - mTranslationShift); 109 } 110 beginDraggingWidget(WidgetCell v)111 private boolean beginDraggingWidget(WidgetCell v) { 112 // Get the widget preview as the drag representation 113 WidgetImageView image = v.getWidgetView(); 114 115 // If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and 116 // we abort the drag. 117 if (image.getBitmap() == null) { 118 return false; 119 } 120 121 int[] loc = new int[2]; 122 getPopupContainer().getLocationInDragLayer(image, loc); 123 124 new PendingItemDragHelper(v).startDrag( 125 image.getBitmapBounds(), image.getBitmap().getWidth(), image.getWidth(), 126 new Point(loc[0], loc[1]), this, new DragOptions()); 127 close(true); 128 return true; 129 } 130 131 // 132 // Drag related handling methods that implement {@link DragSource} interface. 133 // 134 135 @Override onDropCompleted(View target, DragObject d, boolean success)136 public void onDropCompleted(View target, DragObject d, boolean success) { } 137 138 onCloseComplete()139 protected void onCloseComplete() { 140 super.onCloseComplete(); 141 getPopupContainer().removeView(mColorScrim); 142 clearNavBarColor(); 143 } 144 clearNavBarColor()145 protected void clearNavBarColor() { 146 getSystemUiController().updateUiState( 147 SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET, 0); 148 } 149 setupNavBarColor()150 protected void setupNavBarColor() { 151 boolean isSheetDark = Themes.getAttrBoolean(getContext(), R.attr.isMainColorDark); 152 getSystemUiController().updateUiState( 153 SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET, 154 isSheetDark ? SystemUiController.FLAG_DARK_NAV : SystemUiController.FLAG_LIGHT_NAV); 155 } 156 157 @Override fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent)158 public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) { 159 targetParent.containerType = ContainerType.WIDGETS; 160 targetParent.cardinality = getElementsRowCount(); 161 } 162 163 @Override logActionCommand(int command)164 public final void logActionCommand(int command) { 165 Target target = newContainerTarget(getLogContainerType()); 166 target.cardinality = getElementsRowCount(); 167 mLauncher.getUserEventDispatcher().logActionCommand(command, target); 168 } 169 170 @Override getLogContainerType()171 public int getLogContainerType() { 172 return ContainerType.WIDGETS; 173 } 174 getElementsRowCount()175 protected abstract int getElementsRowCount(); 176 getSystemUiController()177 protected SystemUiController getSystemUiController() { 178 return mLauncher.getSystemUiController(); 179 } 180 createColorScrim(Context context)181 private static View createColorScrim(Context context) { 182 View view = new View(context); 183 view.forceHasOverlappingRendering(false); 184 185 WallpaperColorInfo colors = WallpaperColorInfo.getInstance(context); 186 int alpha = context.getResources().getInteger(R.integer.extracted_color_gradient_alpha); 187 view.setBackgroundColor(setColorAlphaBound(colors.getSecondaryColor(), alpha)); 188 189 BaseDragLayer.LayoutParams lp = new BaseDragLayer.LayoutParams(MATCH_PARENT, MATCH_PARENT); 190 lp.ignoreInsets = true; 191 view.setLayoutParams(lp); 192 193 return view; 194 } 195 } 196