1 /* 2 * Copyright (C) 2021 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.views; 17 18 import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; 19 20 import android.animation.PropertyValuesHolder; 21 import android.content.Context; 22 import android.graphics.Rect; 23 import android.util.AttributeSet; 24 import android.view.LayoutInflater; 25 26 import com.android.launcher3.DeviceProfile; 27 import com.android.launcher3.Insettable; 28 import com.android.launcher3.Launcher; 29 import com.android.launcher3.R; 30 31 /** 32 * Education view about widgets. 33 */ 34 public class WidgetsEduView extends AbstractSlideInView<Launcher> implements Insettable { 35 36 private static final int DEFAULT_CLOSE_DURATION = 200; 37 38 private Rect mInsets = new Rect(); 39 WidgetsEduView(Context context, AttributeSet attr)40 public WidgetsEduView(Context context, AttributeSet attr) { 41 this(context, attr, 0); 42 } 43 WidgetsEduView(Context context, AttributeSet attrs, int defStyleAttr)44 public WidgetsEduView(Context context, AttributeSet attrs, 45 int defStyleAttr) { 46 super(context, attrs, defStyleAttr); 47 } 48 49 @Override handleClose(boolean animate)50 protected void handleClose(boolean animate) { 51 handleClose(true, DEFAULT_CLOSE_DURATION); 52 } 53 54 @Override isOfType(int type)55 protected boolean isOfType(int type) { 56 return (type & TYPE_WIDGETS_EDUCATION_DIALOG) != 0; 57 } 58 59 @Override onFinishInflate()60 protected void onFinishInflate() { 61 super.onFinishInflate(); 62 mContent = findViewById(R.id.edu_view); 63 findViewById(R.id.edu_close_button) 64 .setOnClickListener(v -> close(/* animate= */ true)); 65 } 66 67 @Override setInsets(Rect insets)68 public void setInsets(Rect insets) { 69 mInsets.set(insets); 70 mContent.setPadding(mContent.getPaddingStart(), 71 mContent.getPaddingTop(), mContent.getPaddingEnd(), insets.bottom); 72 } 73 show()74 private void show() { 75 attachToContainer(); 76 animateOpen(); 77 } 78 79 @Override getScrimColor(Context context)80 protected int getScrimColor(Context context) { 81 return context.getResources().getColor(R.color.widgets_picker_scrim); 82 } 83 84 @Override onLayout(boolean changed, int l, int t, int r, int b)85 protected void onLayout(boolean changed, int l, int t, int r, int b) { 86 int width = r - l; 87 int height = b - t; 88 89 // Lay out the content as center bottom aligned. 90 int contentWidth = mContent.getMeasuredWidth(); 91 int contentLeft = (width - contentWidth - mInsets.left - mInsets.right) / 2 + mInsets.left; 92 mContent.layout(contentLeft, height - mContent.getMeasuredHeight(), 93 contentLeft + contentWidth, height); 94 95 setTranslationShift(mTranslationShift); 96 } 97 98 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)99 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 100 DeviceProfile deviceProfile = mActivityContext.getDeviceProfile(); 101 int widthUsed; 102 if (mInsets.bottom > 0) { 103 // Extra space between this view and mContent horizontally when the sheet is shown in 104 // portrait mode. 105 widthUsed = mInsets.left + mInsets.right; 106 } else { 107 // Extra space between this view and mContent horizontally when the sheet is shown in 108 // landscape mode. 109 Rect padding = deviceProfile.workspacePadding; 110 widthUsed = Math.max(padding.left + padding.right, 111 2 * (mInsets.left + mInsets.right)); 112 } 113 114 int heightUsed = mInsets.top + deviceProfile.edgeMarginPx; 115 measureChildWithMargins(mContent, widthMeasureSpec, 116 widthUsed, heightMeasureSpec, heightUsed); 117 setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), 118 MeasureSpec.getSize(heightMeasureSpec)); 119 } 120 animateOpen()121 private void animateOpen() { 122 if (mIsOpen || mOpenCloseAnimator.isRunning()) { 123 return; 124 } 125 mIsOpen = true; 126 mOpenCloseAnimator.setValues( 127 PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED)); 128 mOpenCloseAnimator.setInterpolator(FAST_OUT_SLOW_IN); 129 mOpenCloseAnimator.start(); 130 } 131 132 /** Shows widget education dialog. */ showEducationDialog(Launcher launcher)133 public static WidgetsEduView showEducationDialog(Launcher launcher) { 134 LayoutInflater layoutInflater = LayoutInflater.from(launcher); 135 WidgetsEduView v = (WidgetsEduView) layoutInflater.inflate( 136 R.layout.widgets_edu, launcher.getDragLayer(), false); 137 v.show(); 138 return v; 139 } 140 } 141