blob: eb358ec38ad7106c292b152a6290f687ccfd49e3 [file] [log] [blame]
Winson Chung94804152015-05-08 13:06:44 -07001/*
2 * Copyright (C) 2015 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
17package com.android.launcher3;
18
Jon Miranda3298d0f2016-09-22 16:50:17 -070019import android.annotation.SuppressLint;
Winson Chung94804152015-05-08 13:06:44 -070020import android.content.Context;
Sunny Goyal0ac7ede2016-01-29 13:14:14 -080021import android.content.res.TypedArray;
Jon Miranda3298d0f2016-09-22 16:50:17 -070022import android.graphics.PointF;
Jon Miranda177ad2b2016-09-21 14:27:41 -070023import android.graphics.Rect;
Hyunyoung Songa97c64b2016-06-30 11:53:44 -070024import android.graphics.drawable.ColorDrawable;
Sunny Goyal0ac7ede2016-01-29 13:14:14 -080025import android.graphics.drawable.Drawable;
26import android.graphics.drawable.InsetDrawable;
Winson Chung94804152015-05-08 13:06:44 -070027import android.util.AttributeSet;
Jon Miranda3298d0f2016-09-22 16:50:17 -070028import android.view.MotionEvent;
Sunny Goyal0ac7ede2016-01-29 13:14:14 -080029import android.view.View;
Jon Miranda3298d0f2016-09-22 16:50:17 -070030import android.view.ViewConfiguration;
Sunny Goyal0ac7ede2016-01-29 13:14:14 -080031import android.widget.FrameLayout;
Winson Chung94804152015-05-08 13:06:44 -070032
Hyunyoung Song645764e2016-06-06 14:19:02 -070033import com.android.launcher3.allapps.AllAppsContainerView;
34import com.android.launcher3.config.FeatureFlags;
Jon Miranda177ad2b2016-09-21 14:27:41 -070035import com.android.launcher3.util.TransformingTouchDelegate;
Hyunyoung Song645764e2016-06-06 14:19:02 -070036
Winson Chung94804152015-05-08 13:06:44 -070037/**
38 * A base container view, which supports resizing.
39 */
Winson1f064272016-07-18 17:18:02 -070040public abstract class BaseContainerView extends FrameLayout
41 implements DeviceProfile.LauncherLayoutChangeListener {
Winson Chung94804152015-05-08 13:06:44 -070042
Sunny Goyal8b16b962016-11-01 13:42:23 -070043 private static final Rect sBgPaddingRect = new Rect();
Sunny Goyal0ac7ede2016-01-29 13:14:14 -080044
Winson1f064272016-07-18 17:18:02 -070045 protected final Drawable mBaseDrawable;
Sunny Goyal0ac7ede2016-01-29 13:14:14 -080046
47 private View mRevealView;
48 private View mContent;
Winson Chung94804152015-05-08 13:06:44 -070049
Jon Miranda177ad2b2016-09-21 14:27:41 -070050 private TransformingTouchDelegate mTouchDelegate;
51
Jon Miranda3298d0f2016-09-22 16:50:17 -070052 private final PointF mLastTouchDownPosPx = new PointF(-1.0f, -1.0f);
53
Winson Chung94804152015-05-08 13:06:44 -070054 public BaseContainerView(Context context) {
55 this(context, null);
56 }
57
58 public BaseContainerView(Context context, AttributeSet attrs) {
59 this(context, attrs, 0);
60 }
61
62 public BaseContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
63 super(context, attrs, defStyleAttr);
Sunny Goyal05c8c572016-03-17 11:57:24 -070064
Hyunyoung Songa97c64b2016-06-30 11:53:44 -070065 if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && this instanceof AllAppsContainerView) {
Winson1f064272016-07-18 17:18:02 -070066 mBaseDrawable = new ColorDrawable();
Hyunyoung Songa97c64b2016-06-30 11:53:44 -070067 } else {
68 TypedArray a = context.obtainStyledAttributes(attrs,
69 R.styleable.BaseContainerView, defStyleAttr, 0);
Winson1f064272016-07-18 17:18:02 -070070 mBaseDrawable = a.getDrawable(R.styleable.BaseContainerView_revealBackground);
Hyunyoung Songa97c64b2016-06-30 11:53:44 -070071 a.recycle();
72 }
Sunny Goyal0ac7ede2016-01-29 13:14:14 -080073 }
74
75 @Override
Winson1f064272016-07-18 17:18:02 -070076 protected void onAttachedToWindow() {
77 super.onAttachedToWindow();
78
79 DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile();
80 grid.addLauncherLayoutChangedListener(this);
Jon Miranda177ad2b2016-09-21 14:27:41 -070081
82 View touchDelegateTargetView = getTouchDelegateTargetView();
83 if (touchDelegateTargetView != null) {
84 mTouchDelegate = new TransformingTouchDelegate(touchDelegateTargetView);
85 ((View) touchDelegateTargetView.getParent()).setTouchDelegate(mTouchDelegate);
86 }
Winson1f064272016-07-18 17:18:02 -070087 }
88
89 @Override
90 protected void onDetachedFromWindow() {
91 super.onDetachedFromWindow();
92
93 DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile();
94 grid.removeLauncherLayoutChangedListener(this);
95 }
96
97 @Override
Sunny Goyal0ac7ede2016-01-29 13:14:14 -080098 protected void onFinishInflate() {
99 super.onFinishInflate();
100
101 mContent = findViewById(R.id.main_content);
102 mRevealView = findViewById(R.id.reveal_view);
Winson Chung94804152015-05-08 13:06:44 -0700103
Winson1f064272016-07-18 17:18:02 -0700104 updatePaddings();
105 }
Sunny Goyal0ac7ede2016-01-29 13:14:14 -0800106
Winson1f064272016-07-18 17:18:02 -0700107 @Override
Sunny Goyal8b16b962016-11-01 13:42:23 -0700108 public void onLauncherLayoutChanged() {
109 updatePaddings();
110 }
Jon Miranda177ad2b2016-09-21 14:27:41 -0700111
Sunny Goyal8b16b962016-11-01 13:42:23 -0700112 /**
113 * Calculate the background padding as it can change due to insets/content padding change.
114 */
115 private void updatePaddings() {
116 Context context = getContext();
117 int paddingLeft;
118 int paddingRight;
119 int paddingTop;
120 int paddingBottom;
121
122 DeviceProfile grid = Launcher.getLauncher(context).getDeviceProfile();
123 int[] padding = grid.getContainerPadding(context);
124 paddingLeft = padding[0] + grid.edgeMarginPx;
125 paddingRight = padding[1] + grid.edgeMarginPx;
126 if (!grid.isVerticalBarLayout()) {
127 paddingTop = paddingBottom = grid.edgeMarginPx;
128 } else {
129 paddingTop = paddingBottom = 0;
Jon Miranda177ad2b2016-09-21 14:27:41 -0700130 }
Sunny Goyal8b16b962016-11-01 13:42:23 -0700131 updateBackground(paddingLeft, paddingTop, paddingRight, paddingBottom);
132 }
133
134 /**
135 * Update the background for the reveal view and content view based on the background padding.
136 */
137 protected void updateBackground(int paddingLeft, int paddingTop,
138 int paddingRight, int paddingBottom) {
139 mRevealView.setBackground(new InsetDrawable(mBaseDrawable,
140 paddingLeft, paddingTop, paddingRight, paddingBottom));
141 mContent.setBackground(new InsetDrawable(mBaseDrawable,
142 paddingLeft, paddingTop, paddingRight, paddingBottom));
Jon Miranda177ad2b2016-09-21 14:27:41 -0700143 }
144
145 @Override
Sunny Goyal8b16b962016-11-01 13:42:23 -0700146 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
147 super.onLayout(changed, left, top, right, bottom);
148
149 View touchDelegateTargetView = getTouchDelegateTargetView();
150 if (touchDelegateTargetView != null) {
151 getRevealView().getBackground().getPadding(sBgPaddingRect);
152 mTouchDelegate.setBounds(
153 touchDelegateTargetView.getLeft() - sBgPaddingRect.left,
154 touchDelegateTargetView.getTop() - sBgPaddingRect.top,
155 touchDelegateTargetView.getRight() + sBgPaddingRect.right,
156 touchDelegateTargetView.getBottom() + sBgPaddingRect.bottom);
157 }
Winson1f064272016-07-18 17:18:02 -0700158 }
159
Jon Miranda3298d0f2016-09-22 16:50:17 -0700160 @Override
161 public boolean onInterceptTouchEvent(MotionEvent ev) {
162 return handleTouchEvent(ev);
163 }
164
165 @SuppressLint("ClickableViewAccessibility")
166 @Override
167 public boolean onTouchEvent(MotionEvent ev) {
168 return handleTouchEvent(ev);
169 }
170
Winson1f064272016-07-18 17:18:02 -0700171 public void setRevealDrawableColor(int color) {
172 ((ColorDrawable) mBaseDrawable).setColor(color);
Winson Chung73f0b9b2015-07-08 14:13:08 -0700173 }
Sunny Goyal0ac7ede2016-01-29 13:14:14 -0800174
175 public final View getContentView() {
176 return mContent;
177 }
178
179 public final View getRevealView() {
180 return mRevealView;
181 }
Hyunyoung Songe4be3b32016-07-18 16:35:10 -0700182
Jon Miranda177ad2b2016-09-21 14:27:41 -0700183
Jon Miranda3298d0f2016-09-22 16:50:17 -0700184 /**
185 * Handles the touch events that shows the workspace when clicking outside the bounds of the
186 * touch delegate target view.
187 */
188 private boolean handleTouchEvent(MotionEvent ev) {
189 switch (ev.getAction()) {
190 case MotionEvent.ACTION_DOWN:
191 // Check if the touch is outside touch delegate target view
192 View touchDelegateTargetView = getTouchDelegateTargetView();
193 float leftBoundPx = touchDelegateTargetView.getLeft();
194 if (ev.getX() < leftBoundPx ||
195 ev.getX() > (touchDelegateTargetView.getWidth() + leftBoundPx)) {
196 mLastTouchDownPosPx.set((int) ev.getX(), (int) ev.getY());
197 }
198 break;
199 case MotionEvent.ACTION_UP:
200 if (mLastTouchDownPosPx.x > -1) {
201 ViewConfiguration viewConfig = ViewConfiguration.get(getContext());
202 float dx = ev.getX() - mLastTouchDownPosPx.x;
203 float dy = ev.getY() - mLastTouchDownPosPx.y;
204 float distance = PointF.length(dx, dy);
205 if (distance < viewConfig.getScaledTouchSlop()) {
206 // The background was clicked, so just go home
207 Launcher.getLauncher(getContext()).showWorkspace(true);
208 return true;
209 }
210 }
211 // Fall through
212 case MotionEvent.ACTION_CANCEL:
213 mLastTouchDownPosPx.set(-1, -1);
214 break;
215 }
216 return false;
217 }
218
Jon Miranda177ad2b2016-09-21 14:27:41 -0700219 public abstract View getTouchDelegateTargetView();
Andrew Sappersteinabef55a2016-06-19 12:49:00 -0700220}