blob: 611da0dbc890fa4cd9a8f89f7817207200769678 [file] [log] [blame]
/*
* Copyright (C) 2019 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.systemui;
import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import com.android.systemui.util.leak.RotationUtils;
/**
* Layout class representing the Global Actions menu which appears when the power button is held.
*/
public abstract class MultiListLayout extends LinearLayout {
protected boolean mHasOutsideTouch;
protected MultiListAdapter mAdapter;
protected int mRotation;
protected RotationListener mRotationListener;
public MultiListLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mRotation = RotationUtils.getRotation(context);
}
protected abstract ViewGroup getSeparatedView();
protected abstract ViewGroup getListView();
/**
* Sets the divided view, which may have a differently-colored background.
*/
public abstract void setDivisionView(View v);
/**
* Set the view accessibility delegate for the list view container.
*/
public void setListViewAccessibilityDelegate(View.AccessibilityDelegate delegate) {
getListView().setAccessibilityDelegate(delegate);
}
protected void setSeparatedViewVisibility(boolean visible) {
ViewGroup separatedView = getSeparatedView();
if (separatedView != null) {
separatedView.setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
/**
* Sets the adapter used to inflate items.
*/
public void setAdapter(MultiListAdapter adapter) {
mAdapter = adapter;
}
/**
* Sets this layout to respond to an outside touch listener.
*/
public void setOutsideTouchListener(OnClickListener onClickListener) {
mHasOutsideTouch = true;
requestLayout();
setOnClickListener(onClickListener);
setClickable(true);
setFocusable(true);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
int newRotation = RotationUtils.getRotation(mContext);
if (newRotation != mRotation) {
rotate(mRotation, newRotation);
mRotation = newRotation;
}
}
protected void rotate(int from, int to) {
if (mRotationListener != null) {
mRotationListener.onRotate(from, to);
}
}
/**
* Update the list of items in both the separated and list views.
* For this to work, mAdapter must already have been set.
*/
public void updateList() {
if (mAdapter == null) {
throw new IllegalStateException("mAdapter must be set before calling updateList");
}
onUpdateList();
}
protected void removeAllSeparatedViews() {
ViewGroup separated = getSeparatedView();
if (separated != null) {
separated.removeAllViews();
}
}
protected void removeAllListViews() {
ViewGroup list = getListView();
if (list != null) {
list.removeAllViews();
}
}
protected void removeAllItems() {
removeAllListViews();
removeAllSeparatedViews();
}
protected void onUpdateList() {
removeAllItems();
setSeparatedViewVisibility(mAdapter.hasSeparatedItems());
}
public void setRotationListener(RotationListener listener) {
mRotationListener = listener;
}
/**
* Retrieve the MultiListLayout associated with the given view.
*/
public static MultiListLayout get(View v) {
if (v instanceof MultiListLayout) return (MultiListLayout) v;
if (v.getParent() instanceof View) {
return get((View) v.getParent());
}
return null;
}
/**
* Interface to provide callbacks which trigger when this list detects a rotation.
*/
public interface RotationListener {
void onRotate(int from, int to);
}
/**
* Get the X offset in pixels for use when animating the view onto or off of the screen.
*/
public abstract float getAnimationOffsetX();
/**
* Get the Y offset in pixels for use when animating the view onto or off of the screen.
*/
public abstract float getAnimationOffsetY();
/**
* Adapter class for converting items into child views for MultiListLayout and handling
* callbacks for input events.
*/
public abstract static class MultiListAdapter extends BaseAdapter {
/**
* Counts the number of items to be rendered in the separated view.
*/
public abstract int countSeparatedItems();
/**
* Counts the number of items be rendered in the list view.
*/
public abstract int countListItems();
/**
* Callback to run when an individual item is clicked or pressed.
* @param position The index of the item which was clicked.
*/
public abstract void onClickItem(int position);
/**
* Callback to run when an individual item is long-clicked or long-pressed.
* @param position The index of the item which was long-clicked.
* @return True if the long-click was handled, false otherwise.
*/
public abstract boolean onLongClickItem(int position);
/**
* Determines whether the mAdapter contains any separated items, used to determine whether
* or not to hide the separated list from view.
*/
public boolean hasSeparatedItems() {
return countSeparatedItems() > 0;
}
/**
* Determines whether the item at the given index should be rendered in the separarted view.
* @param position The index of the item.
*/
public abstract boolean shouldBeSeparated(int position);
}
}