Add unit tests to GlobalActionsGridLayout.
Refactor GlobalActionsGridLayout, ListGridLayout, and related classes/XML files to clean things up and improve testability. Test: Automated tests pass. (Hooray, they exist now!) Fixes: 130808337 Change-Id: I89f1a90b07425a95ce600dd104ed3a4729c2215b
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
android:clipToPadding="false"
|
||||
android:theme="@style/qs_theme"
|
||||
android:paddingLeft="@dimen/global_actions_top_padding"
|
||||
android:gravity="top|left"
|
||||
android:gravity="right"
|
||||
android:clipChildren="false"
|
||||
>
|
||||
<LinearLayout
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
android:orientation="horizontal"
|
||||
android:clipToPadding="false"
|
||||
android:theme="@style/qs_theme"
|
||||
android:gravity="top|right"
|
||||
android:gravity="left"
|
||||
android:paddingRight="@dimen/global_actions_top_padding"
|
||||
android:clipChildren="false"
|
||||
>
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:clipToPadding="false"
|
||||
android:paddingTop="@dimen/global_actions_top_padding"
|
||||
android:theme="@style/qs_theme"
|
||||
android:gravity="top|center"
|
||||
android:gravity="bottom"
|
||||
android:clipChildren="false"
|
||||
>
|
||||
<LinearLayout
|
||||
|
||||
@@ -32,13 +32,10 @@ import android.view.ViewOutlineProvider;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.systemui.globalactions.GlobalActionsDialog;
|
||||
import com.android.systemui.tuner.TunerService;
|
||||
import com.android.systemui.tuner.TunerService.Tunable;
|
||||
import com.android.systemui.util.leak.RotationUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Layout for placing two containers at a specific physical position on the device, relative to the
|
||||
* device's hardware, regardless of screen rotation.
|
||||
@@ -258,24 +255,16 @@ public class HardwareUiLayout extends MultiListLayout implements Tunable {
|
||||
@Override
|
||||
public void onUpdateList() {
|
||||
super.onUpdateList();
|
||||
ArrayList<GlobalActionsDialog.Action> separatedActions =
|
||||
mAdapter.getSeparatedItems();
|
||||
ArrayList<GlobalActionsDialog.Action> listActions = mAdapter.getListItems();
|
||||
|
||||
for (int i = 0; i < mAdapter.getCount(); i++) {
|
||||
Object action = mAdapter.getItem(i);
|
||||
int separatedIndex = separatedActions.indexOf(action);
|
||||
ViewGroup parent;
|
||||
if (separatedIndex != -1) {
|
||||
boolean separated = mAdapter.shouldBeSeparated(i);
|
||||
if (separated) {
|
||||
parent = getSeparatedView();
|
||||
} else {
|
||||
int listIndex = listActions.indexOf(action);
|
||||
parent = getListView();
|
||||
}
|
||||
View v = mAdapter.getView(i, null, parent);
|
||||
final int pos = i;
|
||||
v.setOnClickListener(view -> mAdapter.onClickItem(pos));
|
||||
v.setOnLongClickListener(view -> mAdapter.onLongClickItem(pos));
|
||||
parent.addView(v);
|
||||
}
|
||||
}
|
||||
@@ -421,7 +410,9 @@ public class HardwareUiLayout extends MultiListLayout implements Tunable {
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
|
||||
post(() -> updatePosition());
|
||||
|
||||
}
|
||||
|
||||
private void animateChild(int oldHeight, int newHeight) {
|
||||
|
||||
@@ -26,16 +26,12 @@ import android.widget.LinearLayout;
|
||||
|
||||
import com.android.systemui.util.leak.RotationUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* 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 boolean mSnapToEdge;
|
||||
|
||||
protected int mRotation;
|
||||
protected RotationListener mRotationListener;
|
||||
|
||||
@@ -51,7 +47,7 @@ public abstract class MultiListLayout extends LinearLayout {
|
||||
/**
|
||||
* Removes all child items from the separated and list views, if they exist.
|
||||
*/
|
||||
public abstract void removeAllItems();
|
||||
protected abstract void removeAllItems();
|
||||
|
||||
/**
|
||||
* Sets the divided view, which may have a differently-colored background.
|
||||
@@ -69,13 +65,6 @@ public abstract class MultiListLayout extends LinearLayout {
|
||||
getSeparatedView().setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the GlobalActions view should snap to the edge of the screen.
|
||||
*/
|
||||
public void setSnapToEdge(boolean snap) {
|
||||
mSnapToEdge = snap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the adapter used to inflate items.
|
||||
*/
|
||||
@@ -122,6 +111,7 @@ public abstract class MultiListLayout extends LinearLayout {
|
||||
}
|
||||
|
||||
protected void onUpdateList() {
|
||||
removeAllItems();
|
||||
setSeparatedViewVisibility(mAdapter.hasSeparatedItems());
|
||||
}
|
||||
|
||||
@@ -163,16 +153,14 @@ public abstract class MultiListLayout extends LinearLayout {
|
||||
*/
|
||||
public abstract static class MultiListAdapter extends BaseAdapter {
|
||||
/**
|
||||
* Creates an ArrayList of items which should be rendered in the separated view.
|
||||
* @param useSeparatedView is true if the separated view will be used, false otherwise.
|
||||
* Counts the number of items to be rendered in the separated view.
|
||||
*/
|
||||
public abstract ArrayList getSeparatedItems();
|
||||
public abstract int countSeparatedItems();
|
||||
|
||||
/**
|
||||
* Creates an ArrayList of items which should be rendered in the list view.
|
||||
* @param useSeparatedView True if the separated view will be used, false otherwise.
|
||||
* Counts the number of items be rendered in the list view.
|
||||
*/
|
||||
public abstract ArrayList getListItems();
|
||||
public abstract int countListItems();
|
||||
|
||||
/**
|
||||
* Callback to run when an individual item is clicked or pressed.
|
||||
@@ -192,7 +180,13 @@ public abstract class MultiListLayout extends LinearLayout {
|
||||
* or not to hide the separated list from view.
|
||||
*/
|
||||
public boolean hasSeparatedItems() {
|
||||
return getSeparatedItems().size() > 0;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -919,58 +919,48 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
* via {@link com.android.systemui.globalactions.GlobalActionsDialog#mDeviceProvisioned}.
|
||||
*/
|
||||
public class MyAdapter extends MultiListAdapter {
|
||||
@Override
|
||||
public int getCount() {
|
||||
private int countItems(boolean separated) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < mItems.size(); i++) {
|
||||
final Action action = mItems.get(i);
|
||||
|
||||
if (mKeyguardShowing && !action.showDuringKeyguard()) {
|
||||
continue;
|
||||
if (shouldBeShown(action) && action.shouldBeSeparated() == separated) {
|
||||
count++;
|
||||
}
|
||||
if (!mDeviceProvisioned && !action.showBeforeProvisioning()) {
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private boolean shouldBeShown(Action action) {
|
||||
if (mKeyguardShowing && !action.showDuringKeyguard()) {
|
||||
return false;
|
||||
}
|
||||
if (!mDeviceProvisioned && !action.showBeforeProvisioning()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countSeparatedItems() {
|
||||
return countItems(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countListItems() {
|
||||
return countItems(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return countSeparatedItems() + countListItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
return getItem(position).isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<Action> getSeparatedItems() {
|
||||
ArrayList<Action> separatedActions = new ArrayList<Action>();
|
||||
if (!shouldUseSeparatedView()) {
|
||||
return separatedActions;
|
||||
}
|
||||
for (int i = 0; i < mItems.size(); i++) {
|
||||
final Action action = mItems.get(i);
|
||||
if (action.shouldBeSeparated()) {
|
||||
separatedActions.add(action);
|
||||
}
|
||||
}
|
||||
return separatedActions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<Action> getListItems() {
|
||||
if (!shouldUseSeparatedView()) {
|
||||
return new ArrayList<Action>(mItems);
|
||||
}
|
||||
ArrayList<Action> listActions = new ArrayList<Action>();
|
||||
for (int i = 0; i < mItems.size(); i++) {
|
||||
final Action action = mItems.get(i);
|
||||
if (!action.shouldBeSeparated()) {
|
||||
listActions.add(action);
|
||||
}
|
||||
}
|
||||
return listActions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areAllItemsEnabled() {
|
||||
return false;
|
||||
@@ -978,14 +968,10 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
|
||||
@Override
|
||||
public Action getItem(int position) {
|
||||
|
||||
int filteredPos = 0;
|
||||
for (int i = 0; i < mItems.size(); i++) {
|
||||
final Action action = mItems.get(i);
|
||||
if (mKeyguardShowing && !action.showDuringKeyguard()) {
|
||||
continue;
|
||||
}
|
||||
if (!mDeviceProvisioned && !action.showBeforeProvisioning()) {
|
||||
if (!shouldBeShown(action)) {
|
||||
continue;
|
||||
}
|
||||
if (filteredPos == position) {
|
||||
@@ -1010,10 +996,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
Action action = getItem(position);
|
||||
View view = action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
|
||||
// Everything but screenshot, the last item, gets white background.
|
||||
if (position == getCount() - 1) {
|
||||
MultiListLayout.get(parent).setDivisionView(view);
|
||||
}
|
||||
view.setOnClickListener(v -> onClickItem(position));
|
||||
view.setOnLongClickListener(v -> onLongClickItem(position));
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -1035,6 +1019,11 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
}
|
||||
item.onPress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldBeSeparated(int position) {
|
||||
return getItem(position).shouldBeSeparated();
|
||||
}
|
||||
}
|
||||
|
||||
// note: the scheme below made more sense when we were planning on having
|
||||
@@ -1589,7 +1578,6 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
com.android.systemui.R.drawable.global_action_panel_scrim);
|
||||
mScrimAlpha = 1f;
|
||||
}
|
||||
mGlobalActionsLayout.setSnapToEdge(true);
|
||||
getWindow().setBackgroundDrawable(mBackgroundDrawable);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,19 +21,16 @@ import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
|
||||
import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.systemui.HardwareBgDrawable;
|
||||
import com.android.systemui.MultiListLayout;
|
||||
import com.android.systemui.util.leak.RotationUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Grid-based implementation of the button layout created by the global actions dialog.
|
||||
*/
|
||||
@@ -69,67 +66,65 @@ public class GlobalActionsGridLayout extends MultiListLayout {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of items expected to be rendered in the list container. This allows the
|
||||
* layout to correctly determine which parent containers will be used for items before they have
|
||||
* beenadded to the layout.
|
||||
* @param count The number of items expected.
|
||||
*/
|
||||
public void setExpectedListItemCount(int count) {
|
||||
getListView().setExpectedCount(count);
|
||||
@VisibleForTesting
|
||||
protected int getCurrentRotation() {
|
||||
return RotationUtils.getRotation(mContext);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void setupListView(ListGridLayout listView, int itemCount) {
|
||||
listView.setExpectedCount(itemCount);
|
||||
listView.setReverseSublists(shouldReverseSublists());
|
||||
listView.setReverseItems(shouldReverseListItems());
|
||||
listView.setSwapRowsAndColumns(shouldSwapRowsAndColumns());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdateList() {
|
||||
super.onUpdateList();
|
||||
ArrayList<GlobalActionsDialog.Action> separatedActions =
|
||||
mAdapter.getSeparatedItems();
|
||||
ArrayList<GlobalActionsDialog.Action> listActions = mAdapter.getListItems();
|
||||
setExpectedListItemCount(listActions.size());
|
||||
int rotation = RotationUtils.getRotation(mContext);
|
||||
|
||||
boolean reverse = false; // should we add items to parents in the reverse order?
|
||||
if (rotation == ROTATION_NONE
|
||||
|| rotation == ROTATION_SEASCAPE) {
|
||||
reverse = !reverse; // if we're in portrait or seascape, reverse items
|
||||
}
|
||||
if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
|
||||
== View.LAYOUT_DIRECTION_RTL) {
|
||||
reverse = !reverse; // if we're in an RTL language, reverse items (again)
|
||||
}
|
||||
ViewGroup separatedView = getSeparatedView();
|
||||
ListGridLayout listView = getListView();
|
||||
setupListView(listView, mAdapter.countListItems());
|
||||
|
||||
for (int i = 0; i < mAdapter.getCount(); i++) {
|
||||
Object action = mAdapter.getItem(i);
|
||||
int separatedIndex = separatedActions.indexOf(action);
|
||||
ViewGroup parent;
|
||||
if (separatedIndex != -1) {
|
||||
parent = getParentView(true, separatedIndex, rotation);
|
||||
// generate the view item
|
||||
View v;
|
||||
boolean separated = mAdapter.shouldBeSeparated(i);
|
||||
if (separated) {
|
||||
v = mAdapter.getView(i, null, separatedView);
|
||||
} else {
|
||||
int listIndex = listActions.indexOf(action);
|
||||
parent = getParentView(false, listIndex, rotation);
|
||||
v = mAdapter.getView(i, null, listView);
|
||||
}
|
||||
View v = mAdapter.getView(i, null, parent);
|
||||
final int pos = i;
|
||||
v.setOnClickListener(view -> mAdapter.onClickItem(pos));
|
||||
v.setOnLongClickListener(view -> mAdapter.onLongClickItem(pos));
|
||||
if (reverse) {
|
||||
parent.addView(v, 0); // reverse order of items
|
||||
Log.d("GlobalActionsGridLayout", "View: " + v);
|
||||
|
||||
if (separated) {
|
||||
separatedView.addView(v);
|
||||
} else {
|
||||
parent.addView(v);
|
||||
listView.addItem(v);
|
||||
}
|
||||
parent.setVisibility(View.VISIBLE);
|
||||
}
|
||||
updateSnapPosition();
|
||||
updateSeparatedButtonSize();
|
||||
updateSeparatedItemSize();
|
||||
}
|
||||
|
||||
private void updateSeparatedButtonSize() {
|
||||
/**
|
||||
* If the separated view contains only one item, expand the bounds of that item to take up the
|
||||
* entire view, so that the whole thing is touch-able.
|
||||
*/
|
||||
private void updateSeparatedItemSize() {
|
||||
ViewGroup separated = getSeparatedView();
|
||||
if (separated.getChildCount() == 0) {
|
||||
return;
|
||||
}
|
||||
View firstChild = separated.getChildAt(0);
|
||||
ViewGroup.LayoutParams childParams = firstChild.getLayoutParams();
|
||||
|
||||
if (separated.getChildCount() == 1) {
|
||||
View onlyChild = separated.getChildAt(0);
|
||||
ViewGroup.LayoutParams childParams = onlyChild.getLayoutParams();
|
||||
childParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
childParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
} else {
|
||||
childParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
childParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,19 +133,6 @@ public class GlobalActionsGridLayout extends MultiListLayout {
|
||||
return findViewById(com.android.systemui.R.id.separated_button);
|
||||
}
|
||||
|
||||
private void updateSnapPosition() {
|
||||
if (mSnapToEdge) {
|
||||
setPadding(0, 0, 0, 0);
|
||||
if (mRotation == ROTATION_LANDSCAPE) {
|
||||
setGravity(Gravity.RIGHT);
|
||||
} else if (mRotation == ROTATION_SEASCAPE) {
|
||||
setGravity(Gravity.LEFT);
|
||||
} else {
|
||||
setGravity(Gravity.BOTTOM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListGridLayout getListView() {
|
||||
return findViewById(android.R.id.list);
|
||||
@@ -168,19 +150,47 @@ public class GlobalActionsGridLayout extends MultiListLayout {
|
||||
}
|
||||
}
|
||||
|
||||
public ViewGroup getParentView(boolean separated, int index, int rotation) {
|
||||
if (separated) {
|
||||
return getSeparatedView();
|
||||
} else {
|
||||
switch (rotation) {
|
||||
case ROTATION_LANDSCAPE:
|
||||
return getListView().getParentView(index, false, true);
|
||||
case ROTATION_SEASCAPE:
|
||||
return getListView().getParentView(index, true, true);
|
||||
default:
|
||||
return getListView().getParentView(index, false, false);
|
||||
}
|
||||
/**
|
||||
* Determines whether the ListGridLayout should fill sublists in the reverse order.
|
||||
* Used to account for sublist ordering changing between landscape and seascape views.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
protected boolean shouldReverseSublists() {
|
||||
if (getCurrentRotation() == ROTATION_SEASCAPE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the ListGridLayout should fill rows first instead of columns.
|
||||
* Used to account for vertical/horizontal changes due to landscape or seascape rotations.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
protected boolean shouldSwapRowsAndColumns() {
|
||||
if (getCurrentRotation() == ROTATION_NONE) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the ListGridLayout should reverse the ordering of items within sublists.
|
||||
* Used for RTL languages to ensure that items appear in the same positions, without having to
|
||||
* override layoutDirection, which breaks Talkback ordering.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
protected boolean shouldReverseListItems() {
|
||||
int rotation = getCurrentRotation();
|
||||
boolean reverse = false; // should we add items to parents in the reverse order?
|
||||
if (rotation == ROTATION_NONE
|
||||
|| rotation == ROTATION_SEASCAPE) {
|
||||
reverse = !reverse; // if we're in portrait or seascape, reverse items
|
||||
}
|
||||
if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
|
||||
reverse = !reverse; // if we're in an RTL language, reverse items (again)
|
||||
}
|
||||
return reverse;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,7 +201,7 @@ public class GlobalActionsGridLayout extends MultiListLayout {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
private float getAnimationDistance() {
|
||||
protected float getAnimationDistance() {
|
||||
int rows = getListView().getRowCount();
|
||||
float gridItemSize = getContext().getResources().getDimension(
|
||||
com.android.systemui.R.dimen.global_actions_grid_item_height);
|
||||
@@ -200,7 +210,7 @@ public class GlobalActionsGridLayout extends MultiListLayout {
|
||||
|
||||
@Override
|
||||
public float getAnimationOffsetX() {
|
||||
switch (RotationUtils.getRotation(getContext())) {
|
||||
switch (getCurrentRotation()) {
|
||||
case ROTATION_LANDSCAPE:
|
||||
return getAnimationDistance();
|
||||
case ROTATION_SEASCAPE:
|
||||
@@ -212,7 +222,7 @@ public class GlobalActionsGridLayout extends MultiListLayout {
|
||||
|
||||
@Override
|
||||
public float getAnimationOffsetY() {
|
||||
if (RotationUtils.getRotation(mContext) == ROTATION_NONE) {
|
||||
if (getCurrentRotation() == ROTATION_NONE) {
|
||||
return getAnimationDistance();
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -22,6 +22,8 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
/**
|
||||
* Layout which uses nested LinearLayouts to create a grid with the following behavior:
|
||||
*
|
||||
@@ -40,6 +42,10 @@ import android.widget.LinearLayout;
|
||||
public class ListGridLayout extends LinearLayout {
|
||||
private static final String TAG = "ListGridLayout";
|
||||
private int mExpectedCount;
|
||||
private int mCurrentCount = 0;
|
||||
private boolean mSwapRowsAndColumns;
|
||||
private boolean mReverseSublists;
|
||||
private boolean mReverseItems;
|
||||
|
||||
// number of rows and columns to use for different numbers of items
|
||||
private final int[][] mConfigs = {
|
||||
@@ -60,17 +66,61 @@ public class ListGridLayout extends LinearLayout {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this grid should prioritize filling rows or columns first.
|
||||
*/
|
||||
public void setSwapRowsAndColumns(boolean swap) {
|
||||
mSwapRowsAndColumns = swap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this grid should fill sublists in reverse order.
|
||||
*/
|
||||
public void setReverseSublists(boolean reverse) {
|
||||
mReverseSublists = reverse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this grid should add items to sublists in reverse order.
|
||||
* @param reverse
|
||||
*/
|
||||
public void setReverseItems(boolean reverse) {
|
||||
mReverseItems = reverse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all items from this grid.
|
||||
*/
|
||||
public void removeAllItems() {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
ViewGroup subList = (ViewGroup) getChildAt(i);
|
||||
ViewGroup subList = getSublist(i);
|
||||
if (subList != null) {
|
||||
subList.removeAllViews();
|
||||
subList.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
mCurrentCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a view item to this grid, placing it in the correct sublist and ensuring that the
|
||||
* sublist is visible.
|
||||
*
|
||||
* This function is stateful, since it tracks how many items have been added thus far, to
|
||||
* determine which sublist they should be added to. To ensure that this works correctly, call
|
||||
* removeAllItems() instead of removing views individually with removeView() to ensure that the
|
||||
* counter gets reset correctly.
|
||||
* @param item
|
||||
*/
|
||||
public void addItem(View item) {
|
||||
ViewGroup parent = getParentView(mCurrentCount, mReverseSublists, mSwapRowsAndColumns);
|
||||
if (mReverseItems) {
|
||||
parent.addView(item, 0);
|
||||
} else {
|
||||
parent.addView(item);
|
||||
}
|
||||
parent.setVisibility(View.VISIBLE);
|
||||
mCurrentCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,13 +133,20 @@ public class ListGridLayout extends LinearLayout {
|
||||
* true will cause rows to fill first, adding one item to each column.
|
||||
* @return
|
||||
*/
|
||||
public ViewGroup getParentView(int index, boolean reverseSublists, boolean swapRowsAndColumns) {
|
||||
@VisibleForTesting
|
||||
protected ViewGroup getParentView(int index, boolean reverseSublists,
|
||||
boolean swapRowsAndColumns) {
|
||||
if (getRowCount() == 0 || index < 0) {
|
||||
return null;
|
||||
}
|
||||
int targetIndex = Math.min(index, getMaxElementCount() - 1);
|
||||
int row = getParentViewIndex(targetIndex, reverseSublists, swapRowsAndColumns);
|
||||
return (ViewGroup) getChildAt(row);
|
||||
return getSublist(row);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected ViewGroup getSublist(int index) {
|
||||
return (ViewGroup) getChildAt(index);
|
||||
}
|
||||
|
||||
private int reverseSublistIndex(int index) {
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* 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.globalactions;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.MultiListLayout;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.util.leak.RotationUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Tests for {@link ListGridLayout}.
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class GlobalActionsGridLayoutTest extends SysuiTestCase {
|
||||
|
||||
private GlobalActionsGridLayout mGridLayout;
|
||||
private TestAdapter mAdapter;
|
||||
private ListGridLayout mListGrid;
|
||||
|
||||
private class TestAdapter extends MultiListLayout.MultiListAdapter {
|
||||
@Override
|
||||
public void onClickItem(int index) { }
|
||||
|
||||
@Override
|
||||
public boolean onLongClickItem(int index) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countSeparatedItems() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countListItems() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldBeSeparated(int position) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return countSeparatedItems() + countListItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mGridLayout = spy((GlobalActionsGridLayout)
|
||||
LayoutInflater.from(mContext).inflate(R.layout.global_actions_grid, null));
|
||||
mAdapter = spy(new TestAdapter());
|
||||
mGridLayout.setAdapter(mAdapter);
|
||||
mListGrid = spy(mGridLayout.getListView());
|
||||
doReturn(mListGrid).when(mGridLayout).getListView();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShouldSwapRowsAndColumns() {
|
||||
doReturn(RotationUtils.ROTATION_NONE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(false, mGridLayout.shouldSwapRowsAndColumns());
|
||||
|
||||
doReturn(RotationUtils.ROTATION_LANDSCAPE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(true, mGridLayout.shouldSwapRowsAndColumns());
|
||||
|
||||
doReturn(RotationUtils.ROTATION_SEASCAPE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(true, mGridLayout.shouldSwapRowsAndColumns());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShouldReverseListItems() {
|
||||
doReturn(View.LAYOUT_DIRECTION_LTR).when(mGridLayout).getLayoutDirection();
|
||||
|
||||
doReturn(RotationUtils.ROTATION_LANDSCAPE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(false, mGridLayout.shouldReverseListItems());
|
||||
|
||||
doReturn(RotationUtils.ROTATION_NONE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(true, mGridLayout.shouldReverseListItems());
|
||||
|
||||
doReturn(RotationUtils.ROTATION_SEASCAPE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(true, mGridLayout.shouldReverseListItems());
|
||||
|
||||
doReturn(View.LAYOUT_DIRECTION_RTL).when(mGridLayout).getLayoutDirection();
|
||||
|
||||
doReturn(RotationUtils.ROTATION_LANDSCAPE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(true, mGridLayout.shouldReverseListItems());
|
||||
|
||||
doReturn(RotationUtils.ROTATION_NONE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(false, mGridLayout.shouldReverseListItems());
|
||||
|
||||
doReturn(RotationUtils.ROTATION_SEASCAPE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(false, mGridLayout.shouldReverseListItems());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShouldReverseSublists() {
|
||||
doReturn(RotationUtils.ROTATION_LANDSCAPE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(false, mGridLayout.shouldReverseSublists());
|
||||
|
||||
doReturn(RotationUtils.ROTATION_NONE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(false, mGridLayout.shouldReverseSublists());
|
||||
|
||||
doReturn(RotationUtils.ROTATION_SEASCAPE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(true, mGridLayout.shouldReverseSublists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnimationOffsetX() {
|
||||
doReturn(50f).when(mGridLayout).getAnimationDistance();
|
||||
|
||||
doReturn(RotationUtils.ROTATION_NONE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(0f, mGridLayout.getAnimationOffsetX(), .01);
|
||||
|
||||
doReturn(RotationUtils.ROTATION_LANDSCAPE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(50f, mGridLayout.getAnimationOffsetX(), .01);
|
||||
|
||||
doReturn(RotationUtils.ROTATION_SEASCAPE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(-50f, mGridLayout.getAnimationOffsetX(), .01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnimationOffsetY() {
|
||||
doReturn(50f).when(mGridLayout).getAnimationDistance();
|
||||
|
||||
doReturn(RotationUtils.ROTATION_NONE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(50f, mGridLayout.getAnimationOffsetY(), .01);
|
||||
|
||||
doReturn(RotationUtils.ROTATION_LANDSCAPE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(0f, mGridLayout.getAnimationOffsetY(), .01);
|
||||
|
||||
doReturn(RotationUtils.ROTATION_SEASCAPE).when(mGridLayout).getCurrentRotation();
|
||||
assertEquals(0f, mGridLayout.getAnimationOffsetY(), .01);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testOnUpdateList_noAdapter() {
|
||||
mGridLayout.setAdapter(null);
|
||||
mGridLayout.updateList();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnUpdateList_noItems() {
|
||||
doReturn(0).when(mAdapter).countSeparatedItems();
|
||||
doReturn(0).when(mAdapter).countListItems();
|
||||
mGridLayout.updateList();
|
||||
|
||||
ViewGroup separatedView = mGridLayout.getSeparatedView();
|
||||
ListGridLayout listView = mGridLayout.getListView();
|
||||
|
||||
assertEquals(0, separatedView.getChildCount());
|
||||
assertEquals(View.GONE, separatedView.getVisibility());
|
||||
|
||||
verify(mListGrid, times(0)).addItem(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnUpdateList_resizesFirstSeparatedItem() {
|
||||
doReturn(1).when(mAdapter).countSeparatedItems();
|
||||
doReturn(0).when(mAdapter).countListItems();
|
||||
View firstView = new View(mContext, null);
|
||||
View secondView = new View(mContext, null);
|
||||
|
||||
doReturn(firstView).when(mAdapter).getView(eq(0), any(), any());
|
||||
doReturn(true).when(mAdapter).shouldBeSeparated(0);
|
||||
|
||||
mGridLayout.updateList();
|
||||
|
||||
ViewGroup.LayoutParams childParams = firstView.getLayoutParams();
|
||||
assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, childParams.width);
|
||||
assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, childParams.height);
|
||||
|
||||
doReturn(2).when(mAdapter).countSeparatedItems();
|
||||
doReturn(secondView).when(mAdapter).getView(eq(1), any(), any());
|
||||
doReturn(true).when(mAdapter).shouldBeSeparated(1);
|
||||
|
||||
mGridLayout.updateList();
|
||||
|
||||
childParams = firstView.getLayoutParams();
|
||||
assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, childParams.width);
|
||||
assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, childParams.height);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnUpdateList_onlySeparatedItems() {
|
||||
doReturn(1).when(mAdapter).countSeparatedItems();
|
||||
doReturn(0).when(mAdapter).countListItems();
|
||||
View testView = new View(mContext, null);
|
||||
doReturn(testView).when(mAdapter).getView(eq(0), any(), any());
|
||||
doReturn(true).when(mAdapter).shouldBeSeparated(0);
|
||||
|
||||
mGridLayout.updateList();
|
||||
|
||||
verify(mListGrid, times(0)).addItem(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnUpdateList_oneSeparatedOneList() {
|
||||
doReturn(1).when(mAdapter).countSeparatedItems();
|
||||
doReturn(1).when(mAdapter).countListItems();
|
||||
View view1 = new View(mContext, null);
|
||||
View view2 = new View(mContext, null);
|
||||
|
||||
doReturn(view1).when(mAdapter).getView(eq(0), any(), any());
|
||||
doReturn(true).when(mAdapter).shouldBeSeparated(0);
|
||||
|
||||
doReturn(view2).when(mAdapter).getView(eq(1), any(), any());
|
||||
doReturn(false).when(mAdapter).shouldBeSeparated(1);
|
||||
|
||||
mGridLayout.updateList();
|
||||
|
||||
ViewGroup separatedView = mGridLayout.getSeparatedView();
|
||||
|
||||
assertEquals(1, separatedView.getChildCount());
|
||||
assertEquals(View.VISIBLE, separatedView.getVisibility());
|
||||
assertEquals(view1, separatedView.getChildAt(0));
|
||||
|
||||
verify(mListGrid, times(1)).addItem(view2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnUpdateList_fourInList() {
|
||||
doReturn(0).when(mAdapter).countSeparatedItems();
|
||||
doReturn(4).when(mAdapter).countListItems();
|
||||
View view1 = new View(mContext, null);
|
||||
View view2 = new View(mContext, null);
|
||||
View view3 = new View(mContext, null);
|
||||
View view4 = new View(mContext, null);
|
||||
|
||||
doReturn(view1).when(mAdapter).getView(eq(0), any(), any());
|
||||
doReturn(false).when(mAdapter).shouldBeSeparated(0);
|
||||
|
||||
doReturn(view2).when(mAdapter).getView(eq(1), any(), any());
|
||||
doReturn(false).when(mAdapter).shouldBeSeparated(1);
|
||||
|
||||
doReturn(view3).when(mAdapter).getView(eq(2), any(), any());
|
||||
doReturn(false).when(mAdapter).shouldBeSeparated(2);
|
||||
|
||||
doReturn(view4).when(mAdapter).getView(eq(3), any(), any());
|
||||
doReturn(false).when(mAdapter).shouldBeSeparated(3);
|
||||
|
||||
mGridLayout.updateList();
|
||||
|
||||
ViewGroup separatedView = mGridLayout.getSeparatedView();
|
||||
assertEquals(0, separatedView.getChildCount());
|
||||
assertEquals(View.GONE, separatedView.getVisibility());
|
||||
|
||||
verify(mListGrid, times(1)).addItem(view1);
|
||||
verify(mListGrid, times(1)).addItem(view2);
|
||||
verify(mListGrid, times(1)).addItem(view3);
|
||||
verify(mListGrid, times(1)).addItem(view4);
|
||||
}
|
||||
}
|
||||
@@ -125,27 +125,27 @@ public class ListGridLayoutTest extends SysuiTestCase {
|
||||
assertEquals(null,
|
||||
mListGridLayout.getParentView(-1, false, false));
|
||||
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(0, false, false));
|
||||
assertEquals(mListGridLayout.getChildAt(1),
|
||||
assertEquals(mListGridLayout.getSublist(1),
|
||||
mListGridLayout.getParentView(1, false, false));
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(2, false, false));
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(3, false, false));
|
||||
assertEquals(mListGridLayout.getChildAt(1),
|
||||
assertEquals(mListGridLayout.getSublist(1),
|
||||
mListGridLayout.getParentView(4, false, false));
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(5, false, false));
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(6, false, false));
|
||||
assertEquals(mListGridLayout.getChildAt(1),
|
||||
assertEquals(mListGridLayout.getSublist(1),
|
||||
mListGridLayout.getParentView(7, false, false));
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(8, false, false));
|
||||
|
||||
// above valid range
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(9, false, false));
|
||||
}
|
||||
|
||||
@@ -157,27 +157,27 @@ public class ListGridLayoutTest extends SysuiTestCase {
|
||||
assertEquals(null,
|
||||
mListGridLayout.getParentView(-1, true, false));
|
||||
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(0, true, false));
|
||||
assertEquals(mListGridLayout.getChildAt(1),
|
||||
assertEquals(mListGridLayout.getSublist(1),
|
||||
mListGridLayout.getParentView(1, true, false));
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(2, true, false));
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(3, true, false));
|
||||
assertEquals(mListGridLayout.getChildAt(1),
|
||||
assertEquals(mListGridLayout.getSublist(1),
|
||||
mListGridLayout.getParentView(4, true, false));
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(5, true, false));
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(6, true, false));
|
||||
assertEquals(mListGridLayout.getChildAt(1),
|
||||
assertEquals(mListGridLayout.getSublist(1),
|
||||
mListGridLayout.getParentView(7, true, false));
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(8, true, false));
|
||||
|
||||
// above valid range
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(9, true, false));
|
||||
}
|
||||
|
||||
@@ -189,27 +189,27 @@ public class ListGridLayoutTest extends SysuiTestCase {
|
||||
assertEquals(null,
|
||||
mListGridLayout.getParentView(-1, false, true));
|
||||
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(0, false, true));
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(1, false, true));
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(2, false, true));
|
||||
assertEquals(mListGridLayout.getChildAt(1),
|
||||
assertEquals(mListGridLayout.getSublist(1),
|
||||
mListGridLayout.getParentView(3, false, true));
|
||||
assertEquals(mListGridLayout.getChildAt(1),
|
||||
assertEquals(mListGridLayout.getSublist(1),
|
||||
mListGridLayout.getParentView(4, false, true));
|
||||
assertEquals(mListGridLayout.getChildAt(1),
|
||||
assertEquals(mListGridLayout.getSublist(1),
|
||||
mListGridLayout.getParentView(5, false, true));
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(6, false, true));
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(7, false, true));
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(8, false, true));
|
||||
|
||||
// above valid range
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(9, false, true));
|
||||
}
|
||||
|
||||
@@ -221,35 +221,38 @@ public class ListGridLayoutTest extends SysuiTestCase {
|
||||
assertEquals(null,
|
||||
mListGridLayout.getParentView(-1, true, true));
|
||||
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(0, true, true));
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(1, true, true));
|
||||
assertEquals(mListGridLayout.getChildAt(2),
|
||||
assertEquals(mListGridLayout.getSublist(2),
|
||||
mListGridLayout.getParentView(2, true, true));
|
||||
assertEquals(mListGridLayout.getChildAt(1),
|
||||
assertEquals(mListGridLayout.getSublist(1),
|
||||
mListGridLayout.getParentView(3, true, true));
|
||||
assertEquals(mListGridLayout.getChildAt(1),
|
||||
assertEquals(mListGridLayout.getSublist(1),
|
||||
mListGridLayout.getParentView(4, true, true));
|
||||
assertEquals(mListGridLayout.getChildAt(1),
|
||||
assertEquals(mListGridLayout.getSublist(1),
|
||||
mListGridLayout.getParentView(5, true, true));
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(6, true, true));
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(7, true, true));
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(8, true, true));
|
||||
|
||||
// above valid range
|
||||
assertEquals(mListGridLayout.getChildAt(0),
|
||||
assertEquals(mListGridLayout.getSublist(0),
|
||||
mListGridLayout.getParentView(9, true, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAllItems() {
|
||||
ViewGroup row1 = (ViewGroup) mListGridLayout.getChildAt(0);
|
||||
ViewGroup row2 = (ViewGroup) mListGridLayout.getChildAt(1);
|
||||
ViewGroup row3 = (ViewGroup) mListGridLayout.getChildAt(2);
|
||||
ViewGroup row1 = mListGridLayout.getSublist(0);
|
||||
row1.setVisibility(View.VISIBLE);
|
||||
ViewGroup row2 = mListGridLayout.getSublist(1);
|
||||
row2.setVisibility(View.VISIBLE);
|
||||
ViewGroup row3 = mListGridLayout.getSublist(2);
|
||||
row3.setVisibility(View.VISIBLE);
|
||||
View item1 = new View(mContext, null);
|
||||
View item2 = new View(mContext, null);
|
||||
View item3 = new View(mContext, null);
|
||||
@@ -265,7 +268,66 @@ public class ListGridLayoutTest extends SysuiTestCase {
|
||||
mListGridLayout.removeAllItems();
|
||||
|
||||
assertEquals(0, row1.getChildCount());
|
||||
assertEquals(View.GONE, row1.getVisibility());
|
||||
assertEquals(0, row2.getChildCount());
|
||||
assertEquals(0, row2.getChildCount());
|
||||
assertEquals(View.GONE, row2.getVisibility());
|
||||
assertEquals(0, row3.getChildCount());
|
||||
assertEquals(View.GONE, row3.getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddItem() {
|
||||
mListGridLayout.setExpectedCount(4);
|
||||
|
||||
View item1 = new View(mContext, null);
|
||||
View item2 = new View(mContext, null);
|
||||
View item3 = new View(mContext, null);
|
||||
View item4 = new View(mContext, null);
|
||||
|
||||
mListGridLayout.addItem(item1);
|
||||
mListGridLayout.addItem(item2);
|
||||
mListGridLayout.addItem(item3);
|
||||
mListGridLayout.addItem(item4);
|
||||
assertEquals(2, mListGridLayout.getSublist(0).getChildCount());
|
||||
assertEquals(2, mListGridLayout.getSublist(1).getChildCount());
|
||||
assertEquals(0, mListGridLayout.getSublist(2).getChildCount());
|
||||
|
||||
mListGridLayout.removeAllItems();
|
||||
mListGridLayout.addItem(item1);
|
||||
|
||||
assertEquals(1, mListGridLayout.getSublist(0).getChildCount());
|
||||
assertEquals(0, mListGridLayout.getSublist(1).getChildCount());
|
||||
assertEquals(0, mListGridLayout.getSublist(2).getChildCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddItem_reverseItems() {
|
||||
mListGridLayout.setExpectedCount(3);
|
||||
|
||||
View item1 = new View(mContext, null);
|
||||
View item2 = new View(mContext, null);
|
||||
View item3 = new View(mContext, null);
|
||||
|
||||
mListGridLayout.addItem(item1);
|
||||
mListGridLayout.addItem(item2);
|
||||
mListGridLayout.addItem(item3);
|
||||
|
||||
ViewGroup sublist = mListGridLayout.getSublist(0);
|
||||
|
||||
assertEquals(item1, sublist.getChildAt(0));
|
||||
assertEquals(item2, sublist.getChildAt(1));
|
||||
assertEquals(item3, sublist.getChildAt(2));
|
||||
|
||||
|
||||
mListGridLayout.removeAllItems();
|
||||
mListGridLayout.setReverseItems(true);
|
||||
|
||||
mListGridLayout.addItem(item1);
|
||||
mListGridLayout.addItem(item2);
|
||||
mListGridLayout.addItem(item3);
|
||||
|
||||
assertEquals(item3, sublist.getChildAt(0));
|
||||
assertEquals(item2, sublist.getChildAt(1));
|
||||
assertEquals(item1, sublist.getChildAt(2));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user