• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.systemui;
18 
19 import android.content.Context;
20 import android.content.res.Configuration;
21 import android.util.AttributeSet;
22 import android.view.View;
23 import android.view.ViewGroup;
24 import android.widget.BaseAdapter;
25 import android.widget.LinearLayout;
26 
27 import com.android.systemui.util.leak.RotationUtils;
28 
29 /**
30  * Layout class representing the Global Actions menu which appears when the power button is held.
31  */
32 public abstract class MultiListLayout extends LinearLayout {
33     protected boolean mHasOutsideTouch;
34     protected MultiListAdapter mAdapter;
35     protected int mRotation;
36     protected RotationListener mRotationListener;
37 
MultiListLayout(Context context, AttributeSet attrs)38     public MultiListLayout(Context context, AttributeSet attrs) {
39         super(context, attrs);
40         mRotation = RotationUtils.getRotation(context);
41     }
42 
getSeparatedView()43     protected abstract ViewGroup getSeparatedView();
44 
getListView()45     protected abstract ViewGroup getListView();
46 
47     /**
48      * Sets the divided view, which may have a differently-colored background.
49      */
setDivisionView(View v)50     public abstract void setDivisionView(View v);
51 
52     /**
53      * Set the view accessibility delegate for the list view container.
54      */
setListViewAccessibilityDelegate(View.AccessibilityDelegate delegate)55     public void setListViewAccessibilityDelegate(View.AccessibilityDelegate delegate) {
56         getListView().setAccessibilityDelegate(delegate);
57     }
58 
setSeparatedViewVisibility(boolean visible)59     protected void setSeparatedViewVisibility(boolean visible) {
60         getSeparatedView().setVisibility(visible ? View.VISIBLE : View.GONE);
61     }
62 
63     /**
64      * Sets the adapter used to inflate items.
65      */
setAdapter(MultiListAdapter adapter)66     public void setAdapter(MultiListAdapter adapter) {
67         mAdapter = adapter;
68     }
69 
70     /**
71      * Sets this layout to respond to an outside touch listener.
72      */
setOutsideTouchListener(OnClickListener onClickListener)73     public void setOutsideTouchListener(OnClickListener onClickListener) {
74         mHasOutsideTouch = true;
75         requestLayout();
76         setOnClickListener(onClickListener);
77         setClickable(true);
78         setFocusable(true);
79     }
80 
81     @Override
onConfigurationChanged(Configuration newConfig)82     protected void onConfigurationChanged(Configuration newConfig) {
83         super.onConfigurationChanged(newConfig);
84         int newRotation = RotationUtils.getRotation(mContext);
85         if (newRotation != mRotation) {
86             rotate(mRotation, newRotation);
87             mRotation = newRotation;
88         }
89     }
90 
rotate(int from, int to)91     protected void rotate(int from, int to) {
92         if (mRotationListener != null) {
93             mRotationListener.onRotate(from, to);
94         }
95     }
96 
97     /**
98      * Update the list of items in both the separated and list views.
99      * For this to work, mAdapter must already have been set.
100      */
updateList()101     public void updateList() {
102         if (mAdapter == null) {
103             throw new IllegalStateException("mAdapter must be set before calling updateList");
104         }
105         onUpdateList();
106     }
107 
removeAllSeparatedViews()108     protected void removeAllSeparatedViews() {
109         ViewGroup separated = getSeparatedView();
110         if (separated != null) {
111             separated.removeAllViews();
112         }
113     }
114 
removeAllListViews()115     protected void removeAllListViews() {
116         ViewGroup list = getListView();
117         if (list != null) {
118             list.removeAllViews();
119         }
120     }
121 
removeAllItems()122     protected void removeAllItems() {
123         removeAllListViews();
124         removeAllSeparatedViews();
125     }
126 
onUpdateList()127     protected void onUpdateList() {
128         removeAllItems();
129         setSeparatedViewVisibility(mAdapter.hasSeparatedItems());
130     }
131 
setRotationListener(RotationListener listener)132     public void setRotationListener(RotationListener listener) {
133         mRotationListener = listener;
134     }
135 
136     /**
137      * Retrieve the MultiListLayout associated with the given view.
138      */
get(View v)139     public static MultiListLayout get(View v) {
140         if (v instanceof MultiListLayout) return (MultiListLayout) v;
141         if (v.getParent() instanceof View) {
142             return get((View) v.getParent());
143         }
144         return null;
145     }
146 
147     /**
148      * Interface to provide callbacks which trigger when this list detects a rotation.
149      */
150     public interface RotationListener {
onRotate(int from, int to)151         void onRotate(int from, int to);
152     }
153 
154     /**
155      * Get the X offset in pixels for use when animating the view onto or off of the screen.
156      */
getAnimationOffsetX()157     public abstract float getAnimationOffsetX();
158 
159     /**
160      * Get the Y offset in pixels for use when animating the view onto or off of the screen.
161      */
getAnimationOffsetY()162     public abstract float getAnimationOffsetY();
163 
164     /**
165      * Adapter class for converting items into child views for MultiListLayout and handling
166      * callbacks for input events.
167      */
168     public abstract static class MultiListAdapter extends BaseAdapter {
169         /**
170          * Counts the number of items to be rendered in the separated view.
171          */
countSeparatedItems()172         public abstract int countSeparatedItems();
173 
174         /**
175          * Counts the number of items be rendered in the list view.
176          */
countListItems()177         public abstract int countListItems();
178 
179         /**
180          * Callback to run when an individual item is clicked or pressed.
181          * @param position The index of the item which was clicked.
182          */
onClickItem(int position)183         public abstract void onClickItem(int position);
184 
185         /**
186          * Callback to run when an individual item is long-clicked or long-pressed.
187          * @param position The index of the item which was long-clicked.
188          * @return True if the long-click was handled, false otherwise.
189          */
onLongClickItem(int position)190         public abstract boolean onLongClickItem(int position);
191 
192         /**
193          * Determines whether the mAdapter contains any separated items, used to determine whether
194          * or not to hide the separated list from view.
195          */
hasSeparatedItems()196         public boolean hasSeparatedItems() {
197             return countSeparatedItems() > 0;
198         }
199 
200         /**
201          * Determines whether the item at the given index should be rendered in the separarted view.
202          * @param position The index of the item.
203          */
shouldBeSeparated(int position)204         public abstract boolean shouldBeSeparated(int position);
205     }
206 }
207