summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/widget/WidgetsFullSheet.java
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2017-10-10 15:21:15 -0700
committerSunny Goyal <sunnygoyal@google.com>2017-10-13 18:47:54 -0700
commitf1fbc3fbe78997f141e2770221fe5ab1b1e68014 (patch)
tree466510cf18141f0a7a841c349096f6dfc23d5e8f /src/com/android/launcher3/widget/WidgetsFullSheet.java
parent10a1bd0e652ec7ea3e3ee861fc0d72261a33a3fd (diff)
downloadandroid_packages_apps_Trebuchet-f1fbc3fbe78997f141e2770221fe5ab1b1e68014.tar.gz
android_packages_apps_Trebuchet-f1fbc3fbe78997f141e2770221fe5ab1b1e68014.tar.bz2
android_packages_apps_Trebuchet-f1fbc3fbe78997f141e2770221fe5ab1b1e68014.zip
Converting widget panel into a floating view
> The widget panel is only inflated when needed > Using the swipe up/down interaction for widgets tray > Removing additional view wrappers from all-apps > Widget tray is preserved across activity recreation > Launcher no longer has WIDGET state, the actual code around the states will be removed in a follow-up cl Bug: 67678570 Bug: 67585158 Change-Id: Ia29a7c33ec81e6c53cc24e2906b7022b6f41755b
Diffstat (limited to 'src/com/android/launcher3/widget/WidgetsFullSheet.java')
-rw-r--r--src/com/android/launcher3/widget/WidgetsFullSheet.java222
1 files changed, 222 insertions, 0 deletions
diff --git a/src/com/android/launcher3/widget/WidgetsFullSheet.java b/src/com/android/launcher3/widget/WidgetsFullSheet.java
new file mode 100644
index 000000000..72277a253
--- /dev/null
+++ b/src/com/android/launcher3/widget/WidgetsFullSheet.java
@@ -0,0 +1,222 @@
+/*
+ * 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.widget;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.PropertyValuesHolder;
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+
+import com.android.launcher3.Insettable;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
+import com.android.launcher3.R;
+
+/**
+ * Popup for showing the full list of available widgets
+ */
+public class WidgetsFullSheet extends BaseWidgetSheet
+ implements Insettable, ProviderChangedListener {
+
+ private static final long DEFAULT_OPEN_DURATION = 267;
+ private static final long FADE_IN_DURATION = 150;
+ private static final float VERTICAL_START_POSITION = 0.3f;
+
+ private static final Rect sTempRect = new Rect();
+
+ private final Rect mInsets = new Rect();
+
+ private final WidgetsListAdapter mAdapter;
+
+ private View mNavBarScrim;
+ private WidgetsRecyclerView mRecyclerView;
+
+ public WidgetsFullSheet(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ LauncherAppState apps = LauncherAppState.getInstance(context);
+ mAdapter = new WidgetsListAdapter(context,
+ LayoutInflater.from(context), apps.getWidgetCache(), apps.getIconCache(),
+ this, this);
+ }
+
+ public WidgetsFullSheet(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mContent = findViewById(R.id.container);
+ mNavBarScrim = findViewById(R.id.nav_bar_bg);
+
+ mRecyclerView = findViewById(R.id.widgets_list_view);
+ mRecyclerView.setAdapter(mAdapter);
+ mAdapter.setApplyBitmapDeferred(true, mRecyclerView);
+
+ mGradientView = findViewById(R.id.gradient_bg);
+ mGradientView.setProgress(1, false);
+
+ onWidgetsBound();
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mLauncher.getAppWidgetHost().addProviderChangeListener(this);
+ notifyWidgetProvidersChanged();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mLauncher.getAppWidgetHost().removeProviderChangeListener(this);
+ }
+
+ @Override
+ public void setInsets(Rect insets) {
+ mInsets.set(insets);
+
+ mNavBarScrim.getLayoutParams().height = insets.bottom;
+ mRecyclerView.setPadding(
+ mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(),
+ mRecyclerView.getPaddingRight(), insets.bottom);
+ if (insets.bottom > 0) {
+ setupNavBarColor();
+ }
+ requestLayout();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int widthUsed;
+ if (mInsets.bottom > 0) {
+ // If we have bottom insets, we do not show the scrim as it would overlap
+ // with the navbar scrim
+ mGradientView.setVisibility(View.INVISIBLE);
+ widthUsed = 0;
+ } else {
+ mLauncher.getDeviceProfile().getWorkspacePadding(sTempRect);
+ widthUsed = Math.max(sTempRect.left + sTempRect.right,
+ 2 * (mInsets.left + mInsets.right));
+ }
+
+ int heightUsed = mInsets.top + mLauncher.getDeviceProfile().edgeMarginPx;
+ measureChildWithMargins(mContent, widthMeasureSpec,
+ widthUsed, heightMeasureSpec, heightUsed);
+ measureChild(mGradientView, widthMeasureSpec, heightMeasureSpec);
+ setMeasuredDimension(mGradientView.getMeasuredWidth(), mGradientView.getMeasuredHeight());
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ int width = r - l;
+ int height = b - t;
+ mGradientView.layout(0, 0, width, height);
+
+ // Content is laid out as center bottom aligned
+ int contentWidth = mContent.getMeasuredWidth();
+ int contentLeft = (width - contentWidth) / 2;
+ mContent.layout(contentLeft, height - mContent.getMeasuredHeight(),
+ contentLeft + contentWidth, height);
+
+ setTranslationShift(mTranslationShift);
+ }
+
+ @Override
+ public void notifyWidgetProvidersChanged() {
+ mLauncher.refreshAndBindWidgetsForPackageUser(null);
+ }
+
+ @Override
+ protected void onWidgetsBound() {
+ mAdapter.setWidgets(mLauncher.getPopupDataProvider().getAllWidgets());
+ }
+
+ private void open(boolean animate) {
+ if (mIsOpen) {
+ return;
+ }
+ mIsOpen = true;
+ if (animate) {
+ if (mLauncher.getDragLayer().getInsets().bottom > 0) {
+ mContent.setAlpha(0);
+ setTranslationShift(VERTICAL_START_POSITION);
+ }
+ mOpenCloseAnimator.setValues(
+ PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
+ mOpenCloseAnimator
+ .setDuration(DEFAULT_OPEN_DURATION)
+ .setInterpolator(AnimationUtils.loadInterpolator(
+ getContext(), android.R.interpolator.linear_out_slow_in));
+ mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mRecyclerView.setLayoutFrozen(false);
+ mAdapter.setApplyBitmapDeferred(false, mRecyclerView);
+ mOpenCloseAnimator.removeListener(this);
+ }
+ });
+ post(new Runnable() {
+ @Override
+ public void run() {
+ mRecyclerView.setLayoutFrozen(true);
+ mOpenCloseAnimator.start();
+ mContent.animate().alpha(1).setDuration(FADE_IN_DURATION);
+ }
+ });
+ } else {
+ setTranslationShift(TRANSLATION_SHIFT_OPENED);
+ mAdapter.setApplyBitmapDeferred(false, mRecyclerView);
+ }
+ }
+
+ @Override
+ protected void handleClose(boolean animate) {
+ handleClose(animate, DEFAULT_OPEN_DURATION);
+ }
+
+ @Override
+ protected boolean isOfType(int type) {
+ return (type & TYPE_WIDGETS_FULL_SHEET) != 0;
+ }
+
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ // Disable swipe down when recycler view is scrolling
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mNoIntercept = false;
+ if (mLauncher.getDragLayer().isEventOverView(mContent, ev)) {
+ mNoIntercept = !mRecyclerView.shouldContainerScroll(ev, mLauncher.getDragLayer());
+ }
+ }
+ return super.onControllerInterceptTouchEvent(ev);
+ }
+
+ public static WidgetsFullSheet show(Launcher launcher, boolean animate) {
+ WidgetsFullSheet sheet = (WidgetsFullSheet) launcher.getLayoutInflater()
+ .inflate(R.layout.widgets_full_sheet, launcher.getDragLayer(), false);
+ launcher.getDragLayer().addView(sheet);
+ sheet.open(animate);
+ return sheet;
+ }
+}