diff options
author | Tony Mak <tonymak@google.com> | 2017-11-29 18:39:49 +0000 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2017-12-04 17:36:33 -0800 |
commit | 191b688cc82a7997cd0c166c251aa2da3eec975f (patch) | |
tree | 66456b7a0332993998e20c632ac3b9995e7648f9 | |
parent | 4018f3df14237adb30c423fee361318cc32673de (diff) | |
download | android_packages_apps_Trebuchet-191b688cc82a7997cd0c166c251aa2da3eec975f.tar.gz android_packages_apps_Trebuchet-191b688cc82a7997cd0c166c251aa2da3eec975f.tar.bz2 android_packages_apps_Trebuchet-191b688cc82a7997cd0c166c251aa2da3eec975f.zip |
Bottom user education view shown in work tab
Introduced a BottomUserEducationView for similar use case.
Screenshot: https://hsv.googleplex.com/4856820942241792
BUG=69963630
Change-Id: Ia818ee44fa5ce97ad1778f33e6a9a3a36cea5017
-rw-r--r-- | res/drawable-hdpi/work_tab_user_education.png | bin | 0 -> 12986 bytes | |||
-rw-r--r-- | res/drawable-mdpi/work_tab_user_education.png | bin | 0 -> 7088 bytes | |||
-rw-r--r-- | res/drawable-xhdpi/work_tab_user_education.png | bin | 0 -> 20719 bytes | |||
-rw-r--r-- | res/drawable-xxhdpi/work_tab_user_education.png | bin | 0 -> 41891 bytes | |||
-rw-r--r-- | res/layout/work_tab_bottom_user_education_view.xml | 57 | ||||
-rw-r--r-- | res/values/strings.xml | 4 | ||||
-rw-r--r-- | src/com/android/launcher3/AbstractFloatingView.java | 6 | ||||
-rw-r--r-- | src/com/android/launcher3/allapps/AllAppsContainerView.java | 4 | ||||
-rw-r--r-- | src/com/android/launcher3/views/AbstractSlideInView.java | 182 | ||||
-rw-r--r-- | src/com/android/launcher3/views/BottomUserEducationView.java | 113 | ||||
-rw-r--r-- | src/com/android/launcher3/widget/BaseWidgetSheet.java | 148 |
11 files changed, 369 insertions, 145 deletions
diff --git a/res/drawable-hdpi/work_tab_user_education.png b/res/drawable-hdpi/work_tab_user_education.png Binary files differnew file mode 100644 index 000000000..1879dfb2b --- /dev/null +++ b/res/drawable-hdpi/work_tab_user_education.png diff --git a/res/drawable-mdpi/work_tab_user_education.png b/res/drawable-mdpi/work_tab_user_education.png Binary files differnew file mode 100644 index 000000000..65c7e638d --- /dev/null +++ b/res/drawable-mdpi/work_tab_user_education.png diff --git a/res/drawable-xhdpi/work_tab_user_education.png b/res/drawable-xhdpi/work_tab_user_education.png Binary files differnew file mode 100644 index 000000000..59df7a864 --- /dev/null +++ b/res/drawable-xhdpi/work_tab_user_education.png diff --git a/res/drawable-xxhdpi/work_tab_user_education.png b/res/drawable-xxhdpi/work_tab_user_education.png Binary files differnew file mode 100644 index 000000000..3c6aa208e --- /dev/null +++ b/res/drawable-xxhdpi/work_tab_user_education.png diff --git a/res/layout/work_tab_bottom_user_education_view.xml b/res/layout/work_tab_bottom_user_education_view.xml new file mode 100644 index 000000000..2a4ba5d06 --- /dev/null +++ b/res/layout/work_tab_bottom_user_education_view.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 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. +--> +<com.android.launcher3.views.BottomUserEducationView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + android:background="?android:attr/colorAccent" + android:elevation="2dp" + android:orientation="horizontal" + android:paddingLeft="20dp" + android:paddingRight="20dp"> + + <ImageView + android:layout_width="134dp" + android:layout_height="134dp" + android:layout_gravity="center_vertical" + android:src="@drawable/work_tab_user_education"/> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:paddingBottom="12dp" + android:paddingStart="24dp" + android:paddingTop="12dp"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:fontFamily="roboto-medium" + android:text="@string/bottom_work_tab_user_education_title" + android:textColor="@android:color/white" + android:textSize="20sp"/> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/bottom_work_tab_user_education_body" + android:textColor="@android:color/white" + android:textSize="14sp"/> + </LinearLayout> + +</com.android.launcher3.views.BottomUserEducationView>
\ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index cbba9a227..eca64c852 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -326,5 +326,9 @@ <!-- Label of the work mode toggle --> <string name="work_profile_toggle_label">Work profile</string> + <!-- Title in bottom user education view in work tab --> + <string name="bottom_work_tab_user_education_title">Find work apps here</string> + <!-- Body text in bottom user education view in work tab --> + <string name="bottom_work_tab_user_education_body">Each work app has an orange badge, which means it\'s kept secure by your organization. Work apps can be moved to your Home Screen for easier access.</string> </resources> diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java index 26024e531..2c6629d59 100644 --- a/src/com/android/launcher3/AbstractFloatingView.java +++ b/src/com/android/launcher3/AbstractFloatingView.java @@ -42,7 +42,8 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch TYPE_WIDGETS_BOTTOM_SHEET, TYPE_WIDGET_RESIZE_FRAME, TYPE_WIDGETS_FULL_SHEET, - TYPE_QUICKSTEP_PREVIEW + TYPE_QUICKSTEP_PREVIEW, + TYPE_ON_BOARD_POPUP }) @Retention(RetentionPolicy.SOURCE) public @interface FloatingViewType {} @@ -52,10 +53,11 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch public static final int TYPE_WIDGET_RESIZE_FRAME = 1 << 3; public static final int TYPE_WIDGETS_FULL_SHEET = 1 << 4; public static final int TYPE_QUICKSTEP_PREVIEW = 1 << 5; + public static final int TYPE_ON_BOARD_POPUP = 1 << 6; public static final int TYPE_ALL = TYPE_FOLDER | TYPE_ACTION_POPUP | TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGET_RESIZE_FRAME | TYPE_WIDGETS_FULL_SHEET - | TYPE_QUICKSTEP_PREVIEW; + | TYPE_QUICKSTEP_PREVIEW | TYPE_ON_BOARD_POPUP; protected boolean mIsOpen; diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 9ee9514fc..f4026f292 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -60,6 +60,7 @@ import com.android.launcher3.util.ComponentKeyMapper; import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.TransformingTouchDelegate; +import com.android.launcher3.views.BottomUserEducationView; import com.android.launcher3.views.SlidingTabStrip; import java.util.HashMap; @@ -515,6 +516,9 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource, if (mAH[pos].recyclerView != null) { mAH[pos].recyclerView.bindFastScrollbar(); } + if (pos == AdapterHolder.WORK) { + BottomUserEducationView.showIfNeeded(mLauncher); + } } @Override diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java new file mode 100644 index 000000000..7c4529dd7 --- /dev/null +++ b/src/com/android/launcher3/views/AbstractSlideInView.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2017 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 static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.content.Context; +import android.util.AttributeSet; +import android.util.Property; +import android.view.MotionEvent; +import android.view.View; +import android.view.animation.Interpolator; + +import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherAnimUtils; +import com.android.launcher3.Utilities; +import com.android.launcher3.anim.Interpolators; +import com.android.launcher3.touch.SwipeDetector; + +/** + * Extension of AbstractFloatingView with common methods for sliding in from bottom + */ +public abstract class AbstractSlideInView extends AbstractFloatingView + implements SwipeDetector.Listener { + + protected static Property<AbstractSlideInView, Float> TRANSLATION_SHIFT = + new Property<AbstractSlideInView, Float>(Float.class, "translationShift") { + + @Override + public Float get(AbstractSlideInView view) { + return view.mTranslationShift; + } + + @Override + public void set(AbstractSlideInView view, Float value) { + view.setTranslationShift(value); + } + }; + protected static final float TRANSLATION_SHIFT_CLOSED = 1f; + protected static final float TRANSLATION_SHIFT_OPENED = 0f; + + protected final Launcher mLauncher; + protected final SwipeDetector mSwipeDetector; + protected final ObjectAnimator mOpenCloseAnimator; + + protected View mContent; + protected Interpolator mScrollInterpolator; + + // range [0, 1], 0=> completely open, 1=> completely closed + protected float mTranslationShift = TRANSLATION_SHIFT_CLOSED; + + protected boolean mNoIntercept; + + public AbstractSlideInView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mLauncher = Launcher.getLauncher(context); + + mScrollInterpolator = Interpolators.SCROLL_CUBIC; + mSwipeDetector = new SwipeDetector(context, this, SwipeDetector.VERTICAL); + + mOpenCloseAnimator = LauncherAnimUtils.ofPropertyValuesHolder(this); + mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mSwipeDetector.finishedScrolling(); + } + }); + } + + protected void setTranslationShift(float translationShift) { + mTranslationShift = translationShift; + mContent.setTranslationY(mTranslationShift * mContent.getHeight()); + } + + @Override + public boolean onControllerInterceptTouchEvent(MotionEvent ev) { + if (mNoIntercept) { + return false; + } + + int directionsToDetectScroll = mSwipeDetector.isIdleState() ? + SwipeDetector.DIRECTION_NEGATIVE : 0; + mSwipeDetector.setDetectableScrollConditions( + directionsToDetectScroll, false); + mSwipeDetector.onTouchEvent(ev); + return mSwipeDetector.isDraggingOrSettling() + || !mLauncher.getDragLayer().isEventOverView(mContent, ev); + } + + @Override + public boolean onControllerTouchEvent(MotionEvent ev) { + mSwipeDetector.onTouchEvent(ev); + if (ev.getAction() == MotionEvent.ACTION_UP && mSwipeDetector.isIdleState()) { + // If we got ACTION_UP without ever starting swipe, close the panel. + if (!mLauncher.getDragLayer().isEventOverView(mContent, ev)) { + close(true); + } + } + return true; + } + + /* SwipeDetector.Listener */ + + @Override + public void onDragStart(boolean start) { } + + @Override + public boolean onDrag(float displacement, float velocity) { + float range = mContent.getHeight(); + displacement = Utilities.boundToRange(displacement, 0, range); + setTranslationShift(displacement / range); + return true; + } + + @Override + public void onDragEnd(float velocity, boolean fling) { + if ((fling && velocity > 0) || mTranslationShift > 0.5f) { + mScrollInterpolator = scrollInterpolatorForVelocity(velocity); + mOpenCloseAnimator.setDuration(SwipeDetector.calculateDuration( + velocity, TRANSLATION_SHIFT_CLOSED - mTranslationShift)); + close(true); + } else { + mOpenCloseAnimator.setValues(PropertyValuesHolder.ofFloat( + TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED)); + mOpenCloseAnimator.setDuration( + SwipeDetector.calculateDuration(velocity, mTranslationShift)) + .setInterpolator(Interpolators.DEACCEL); + mOpenCloseAnimator.start(); + } + } + + protected void handleClose(boolean animate, long defaultDuration) { + if (mIsOpen && !animate) { + mOpenCloseAnimator.cancel(); + setTranslationShift(TRANSLATION_SHIFT_CLOSED); + onCloseComplete(); + return; + } + if (!mIsOpen || mOpenCloseAnimator.isRunning()) { + return; + } + mOpenCloseAnimator.setValues( + PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_CLOSED)); + mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + onCloseComplete(); + } + }); + if (mSwipeDetector.isIdleState()) { + mOpenCloseAnimator + .setDuration(defaultDuration) + .setInterpolator(Interpolators.ACCEL); + } else { + mOpenCloseAnimator.setInterpolator(mScrollInterpolator); + } + mOpenCloseAnimator.start(); + } + + protected void onCloseComplete() { + mIsOpen = false; + mLauncher.getDragLayer().removeView(this); + } +} diff --git a/src/com/android/launcher3/views/BottomUserEducationView.java b/src/com/android/launcher3/views/BottomUserEducationView.java new file mode 100644 index 000000000..d79d0cefa --- /dev/null +++ b/src/com/android/launcher3/views/BottomUserEducationView.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2017 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.animation.PropertyValuesHolder; +import android.content.Context; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.LayoutInflater; + +import com.android.launcher3.Insettable; +import com.android.launcher3.Launcher; +import com.android.launcher3.R; +import com.android.launcher3.anim.Interpolators; + +public class BottomUserEducationView extends AbstractSlideInView implements Insettable { + + private static final String KEY_SHOWED_BOTTOM_USER_EDUCATION = "showed_bottom_user_education"; + + private static final int DEFAULT_CLOSE_DURATION = 200; + + private final Rect mInsets = new Rect(); + + public BottomUserEducationView(Context context, AttributeSet attr) { + this(context, attr, 0); + } + + public BottomUserEducationView(Context context, AttributeSet attrs, + int defStyleAttr) { + super(context, attrs, defStyleAttr); + mContent = this; + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + setTranslationShift(mTranslationShift); + } + + @Override + public void logActionCommand(int command) { + // Since this is on-boarding popup, it is not a user controlled action. + } + + @Override + protected boolean isOfType(int type) { + return (type & TYPE_ON_BOARD_POPUP) != 0; + } + + @Override + public void setInsets(Rect insets) { + // Extend behind left, right, and bottom insets. + int leftInset = insets.left - mInsets.left; + int rightInset = insets.right - mInsets.right; + int bottomInset = insets.bottom - mInsets.bottom; + mInsets.set(insets); + setPadding(getPaddingLeft() + leftInset, getPaddingTop(), + getPaddingRight() + rightInset, getPaddingBottom() + bottomInset); + } + + @Override + protected void handleClose(boolean animate) { + handleClose(animate, DEFAULT_CLOSE_DURATION); + if (animate) { + // We animate only when the user is visible, which is a proxy for an explicit + // close action. + mLauncher.getSharedPrefs().edit() + .putBoolean(KEY_SHOWED_BOTTOM_USER_EDUCATION, true).apply(); + } + } + + private void open(boolean animate) { + if (mIsOpen || mOpenCloseAnimator.isRunning()) { + return; + } + mIsOpen = true; + if (animate) { + mOpenCloseAnimator.setValues( + PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED)); + mOpenCloseAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); + mOpenCloseAnimator.start(); + } else { + setTranslationShift(TRANSLATION_SHIFT_OPENED); + } + } + + public static void showIfNeeded(Launcher launcher) { + if (launcher.getSharedPrefs().getBoolean(KEY_SHOWED_BOTTOM_USER_EDUCATION, false)) { + return; + } + + LayoutInflater layoutInflater = LayoutInflater.from(launcher); + BottomUserEducationView bottomUserEducationView = + (BottomUserEducationView) layoutInflater.inflate( + R.layout.work_tab_bottom_user_education_view, launcher.getDragLayer(), + false); + launcher.getDragLayer().addView(bottomUserEducationView); + bottomUserEducationView.open(true); + } +} diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java index e32875926..fa8271438 100644 --- a/src/com/android/launcher3/widget/BaseWidgetSheet.java +++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java @@ -15,94 +15,43 @@ */ package com.android.launcher3.widget; -import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.ObjectAnimator; -import android.animation.PropertyValuesHolder; import android.content.Context; import android.graphics.Point; import android.util.AttributeSet; -import android.util.Property; -import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; -import android.view.animation.Interpolator; import android.widget.Toast; -import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DragSource; import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.ItemInfo; -import com.android.launcher3.Launcher; -import com.android.launcher3.LauncherAnimUtils; import com.android.launcher3.R; import com.android.launcher3.Utilities; -import com.android.launcher3.anim.Interpolators; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.graphics.GradientView; -import com.android.launcher3.touch.SwipeDetector; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.userevent.nano.LauncherLogProto.Target; import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.Themes; +import com.android.launcher3.views.AbstractSlideInView; /** * Base class for various widgets popup */ -abstract class BaseWidgetSheet extends AbstractFloatingView - implements OnClickListener, OnLongClickListener, DragSource, SwipeDetector.Listener { +abstract class BaseWidgetSheet extends AbstractSlideInView + implements OnClickListener, OnLongClickListener, DragSource { - protected static Property<BaseWidgetSheet, Float> TRANSLATION_SHIFT = - new Property<BaseWidgetSheet, Float>(Float.class, "translationShift") { - - @Override - public Float get(BaseWidgetSheet view) { - return view.mTranslationShift; - } - - @Override - public void set(BaseWidgetSheet view, Float value) { - view.setTranslationShift(value); - } - }; - protected static final float TRANSLATION_SHIFT_CLOSED = 1f; - protected static final float TRANSLATION_SHIFT_OPENED = 0f; - /* Touch handling related member variables. */ private Toast mWidgetInstructionToast; - protected final Launcher mLauncher; - protected final SwipeDetector mSwipeDetector; - protected final ObjectAnimator mOpenCloseAnimator; - - protected View mContent; protected GradientView mGradientView; - protected Interpolator mScrollInterpolator; - - // range [0, 1], 0=> completely open, 1=> completely closed - protected float mTranslationShift = TRANSLATION_SHIFT_CLOSED; - - protected boolean mNoIntercept; public BaseWidgetSheet(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - mLauncher = Launcher.getLauncher(context); - - mScrollInterpolator = Interpolators.SCROLL_CUBIC; - mSwipeDetector = new SwipeDetector(context, this, SwipeDetector.VERTICAL); - - mOpenCloseAnimator = LauncherAnimUtils.ofPropertyValuesHolder(this); - mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mSwipeDetector.finishedScrolling(); - } - }); } @Override @@ -130,9 +79,8 @@ abstract class BaseWidgetSheet extends AbstractFloatingView } protected void setTranslationShift(float translationShift) { - mTranslationShift = translationShift; + super.setTranslationShift(translationShift); mGradientView.setAlpha(1 - mTranslationShift); - mContent.setTranslationY(mTranslationShift * mContent.getHeight()); } private boolean beginDraggingWidget(WidgetCell v) { @@ -163,94 +111,8 @@ abstract class BaseWidgetSheet extends AbstractFloatingView public void onDropCompleted(View target, DragObject d, boolean success) { } - @Override - public boolean onControllerInterceptTouchEvent(MotionEvent ev) { - if (ev.getAction() == MotionEvent.ACTION_UP && !mNoIntercept) { - // If we got ACTION_UP without ever returning true on intercept, - // the user never started dragging the bottom sheet. - if (!mLauncher.getDragLayer().isEventOverView(mContent, ev)) { - close(true); - return false; - } - } - - if (mNoIntercept) { - return false; - } - - int directionsToDetectScroll = mSwipeDetector.isIdleState() ? - SwipeDetector.DIRECTION_NEGATIVE : 0; - mSwipeDetector.setDetectableScrollConditions( - directionsToDetectScroll, false); - mSwipeDetector.onTouchEvent(ev); - return mSwipeDetector.isDraggingOrSettling(); - } - - @Override - public boolean onControllerTouchEvent(MotionEvent ev) { - return mSwipeDetector.onTouchEvent(ev); - } - - /* SwipeDetector.Listener */ - - @Override - public void onDragStart(boolean start) { } - - @Override - public boolean onDrag(float displacement, float velocity) { - float range = mContent.getHeight(); - displacement = Utilities.boundToRange(displacement, 0, range); - setTranslationShift(displacement / range); - return true; - } - - @Override - public void onDragEnd(float velocity, boolean fling) { - if ((fling && velocity > 0) || mTranslationShift > 0.5f) { - mScrollInterpolator = scrollInterpolatorForVelocity(velocity); - mOpenCloseAnimator.setDuration(SwipeDetector.calculateDuration( - velocity, TRANSLATION_SHIFT_CLOSED - mTranslationShift)); - close(true); - } else { - mOpenCloseAnimator.setValues(PropertyValuesHolder.ofFloat( - TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED)); - mOpenCloseAnimator.setDuration( - SwipeDetector.calculateDuration(velocity, mTranslationShift)) - .setInterpolator(Interpolators.DEACCEL); - mOpenCloseAnimator.start(); - } - } - - protected void handleClose(boolean animate, long defaultDuration) { - if (!mIsOpen || mOpenCloseAnimator.isRunning()) { - return; - } - if (animate) { - mOpenCloseAnimator.setValues( - PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_CLOSED)); - mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - onCloseComplete(); - } - }); - if (mSwipeDetector.isIdleState()) { - mOpenCloseAnimator - .setDuration(defaultDuration) - .setInterpolator(Interpolators.ACCEL); - } else { - mOpenCloseAnimator.setInterpolator(mScrollInterpolator); - } - mOpenCloseAnimator.start(); - } else { - setTranslationShift(TRANSLATION_SHIFT_CLOSED); - onCloseComplete(); - } - } - protected void onCloseComplete() { - mIsOpen = false; - mLauncher.getDragLayer().removeView(this); + super.onCloseComplete(); mLauncher.getSystemUiController().updateUiState( SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET, 0); } |