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
This commit is contained in:
parent
4018f3df14
commit
191b688cc8
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue