blob: 611da0dbc890fa4cd9a8f89f7817207200769678 [file] [log] [blame]
Aaron Heuckrothf708d472019-01-10 16:54:51 -05001/*
2 * Copyright (C) 2019 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.systemui;
18
19import android.content.Context;
Aaron Heuckroth75e249f2019-02-01 15:59:57 -050020import android.content.res.Configuration;
Aaron Heuckrothf708d472019-01-10 16:54:51 -050021import android.util.AttributeSet;
22import android.view.View;
23import android.view.ViewGroup;
Aaron Heuckroth57d60d22019-03-05 14:00:12 -050024import android.widget.BaseAdapter;
Aaron Heuckrothf708d472019-01-10 16:54:51 -050025import android.widget.LinearLayout;
26
Aaron Heuckroth75e249f2019-02-01 15:59:57 -050027import com.android.systemui.util.leak.RotationUtils;
28
Aaron Heuckrothf708d472019-01-10 16:54:51 -050029/**
30 * Layout class representing the Global Actions menu which appears when the power button is held.
31 */
32public abstract class MultiListLayout extends LinearLayout {
Aaron Heuckroth166392f2019-01-17 16:50:59 -050033 protected boolean mHasOutsideTouch;
Aaron Heuckroth57d60d22019-03-05 14:00:12 -050034 protected MultiListAdapter mAdapter;
Aaron Heuckroth75e249f2019-02-01 15:59:57 -050035 protected int mRotation;
36 protected RotationListener mRotationListener;
37
Aaron Heuckrothf708d472019-01-10 16:54:51 -050038 public MultiListLayout(Context context, AttributeSet attrs) {
39 super(context, attrs);
Aaron Heuckroth75e249f2019-02-01 15:59:57 -050040 mRotation = RotationUtils.getRotation(context);
Aaron Heuckrothf708d472019-01-10 16:54:51 -050041 }
42
43 protected abstract ViewGroup getSeparatedView();
44
45 protected abstract ViewGroup getListView();
46
47 /**
Aaron Heuckrothf708d472019-01-10 16:54:51 -050048 * Sets the divided view, which may have a differently-colored background.
49 */
50 public abstract void setDivisionView(View v);
51
52 /**
53 * Set the view accessibility delegate for the list view container.
54 */
55 public void setListViewAccessibilityDelegate(View.AccessibilityDelegate delegate) {
56 getListView().setAccessibilityDelegate(delegate);
57 }
58
59 protected void setSeparatedViewVisibility(boolean visible) {
Aran Ink780d4502020-02-14 10:39:58 -050060 ViewGroup separatedView = getSeparatedView();
61 if (separatedView != null) {
62 separatedView.setVisibility(visible ? View.VISIBLE : View.GONE);
63 }
Aaron Heuckrothf708d472019-01-10 16:54:51 -050064 }
65
66 /**
Aaron Heuckroth57d60d22019-03-05 14:00:12 -050067 * Sets the adapter used to inflate items.
68 */
69 public void setAdapter(MultiListAdapter adapter) {
70 mAdapter = adapter;
Aaron Heuckrothf708d472019-01-10 16:54:51 -050071 }
72
73 /**
74 * Sets this layout to respond to an outside touch listener.
75 */
76 public void setOutsideTouchListener(OnClickListener onClickListener) {
77 mHasOutsideTouch = true;
78 requestLayout();
79 setOnClickListener(onClickListener);
80 setClickable(true);
81 setFocusable(true);
82 }
83
Aaron Heuckroth75e249f2019-02-01 15:59:57 -050084 @Override
85 protected void onConfigurationChanged(Configuration newConfig) {
86 super.onConfigurationChanged(newConfig);
87 int newRotation = RotationUtils.getRotation(mContext);
88 if (newRotation != mRotation) {
89 rotate(mRotation, newRotation);
90 mRotation = newRotation;
91 }
92 }
93
94 protected void rotate(int from, int to) {
95 if (mRotationListener != null) {
96 mRotationListener.onRotate(from, to);
97 }
98 }
99
Aaron Heuckroth57d60d22019-03-05 14:00:12 -0500100 /**
101 * Update the list of items in both the separated and list views.
102 * For this to work, mAdapter must already have been set.
103 */
104 public void updateList() {
105 if (mAdapter == null) {
106 throw new IllegalStateException("mAdapter must be set before calling updateList");
107 }
108 onUpdateList();
109 }
110
Aaron Heuckrothe2d92ac2019-05-01 10:44:59 -0400111 protected void removeAllSeparatedViews() {
112 ViewGroup separated = getSeparatedView();
113 if (separated != null) {
114 separated.removeAllViews();
115 }
116 }
117
118 protected void removeAllListViews() {
119 ViewGroup list = getListView();
120 if (list != null) {
121 list.removeAllViews();
122 }
123 }
124
125 protected void removeAllItems() {
126 removeAllListViews();
127 removeAllSeparatedViews();
128 }
129
Aaron Heuckrothf19d2722019-03-11 17:06:02 -0400130 protected void onUpdateList() {
Aaron Heuckroth5e28f8c82019-04-24 13:26:12 -0400131 removeAllItems();
Aaron Heuckrothf19d2722019-03-11 17:06:02 -0400132 setSeparatedViewVisibility(mAdapter.hasSeparatedItems());
133 }
Aaron Heuckroth57d60d22019-03-05 14:00:12 -0500134
Aaron Heuckroth75e249f2019-02-01 15:59:57 -0500135 public void setRotationListener(RotationListener listener) {
136 mRotationListener = listener;
137 }
138
Aaron Heuckrothf708d472019-01-10 16:54:51 -0500139 /**
140 * Retrieve the MultiListLayout associated with the given view.
141 */
142 public static MultiListLayout get(View v) {
143 if (v instanceof MultiListLayout) return (MultiListLayout) v;
144 if (v.getParent() instanceof View) {
145 return get((View) v.getParent());
146 }
147 return null;
148 }
Aaron Heuckroth75e249f2019-02-01 15:59:57 -0500149
Aaron Heuckroth4ea2fdb2019-02-14 16:28:35 -0500150 /**
151 * Interface to provide callbacks which trigger when this list detects a rotation.
152 */
153 public interface RotationListener {
Aaron Heuckroth75e249f2019-02-01 15:59:57 -0500154 void onRotate(int from, int to);
155 }
Aaron Heuckroth57d60d22019-03-05 14:00:12 -0500156
157 /**
Aaron Heuckrothc7926612019-04-02 14:21:57 -0400158 * Get the X offset in pixels for use when animating the view onto or off of the screen.
159 */
160 public abstract float getAnimationOffsetX();
161
162 /**
163 * Get the Y offset in pixels for use when animating the view onto or off of the screen.
164 */
165 public abstract float getAnimationOffsetY();
166
167 /**
Aaron Heuckroth57d60d22019-03-05 14:00:12 -0500168 * Adapter class for converting items into child views for MultiListLayout and handling
169 * callbacks for input events.
170 */
171 public abstract static class MultiListAdapter extends BaseAdapter {
172 /**
Aaron Heuckroth5e28f8c82019-04-24 13:26:12 -0400173 * Counts the number of items to be rendered in the separated view.
Aaron Heuckroth57d60d22019-03-05 14:00:12 -0500174 */
Aaron Heuckroth5e28f8c82019-04-24 13:26:12 -0400175 public abstract int countSeparatedItems();
Aaron Heuckroth57d60d22019-03-05 14:00:12 -0500176
177 /**
Aaron Heuckroth5e28f8c82019-04-24 13:26:12 -0400178 * Counts the number of items be rendered in the list view.
Aaron Heuckroth57d60d22019-03-05 14:00:12 -0500179 */
Aaron Heuckroth5e28f8c82019-04-24 13:26:12 -0400180 public abstract int countListItems();
Aaron Heuckroth57d60d22019-03-05 14:00:12 -0500181
182 /**
183 * Callback to run when an individual item is clicked or pressed.
184 * @param position The index of the item which was clicked.
185 */
186 public abstract void onClickItem(int position);
187
188 /**
189 * Callback to run when an individual item is long-clicked or long-pressed.
190 * @param position The index of the item which was long-clicked.
191 * @return True if the long-click was handled, false otherwise.
192 */
193 public abstract boolean onLongClickItem(int position);
Aaron Heuckrothf19d2722019-03-11 17:06:02 -0400194
195 /**
196 * Determines whether the mAdapter contains any separated items, used to determine whether
197 * or not to hide the separated list from view.
198 */
199 public boolean hasSeparatedItems() {
Aaron Heuckroth5e28f8c82019-04-24 13:26:12 -0400200 return countSeparatedItems() > 0;
Aaron Heuckrothf19d2722019-03-11 17:06:02 -0400201 }
Aaron Heuckroth5e28f8c82019-04-24 13:26:12 -0400202
203 /**
204 * Determines whether the item at the given index should be rendered in the separarted view.
205 * @param position The index of the item.
206 */
207 public abstract boolean shouldBeSeparated(int position);
Aaron Heuckroth57d60d22019-03-05 14:00:12 -0500208 }
Aaron Heuckrothf708d472019-01-10 16:54:51 -0500209}