Suppress auto-closing drawer and add ripple effect on spring load roots.
Bug: 28865182 Change-Id: Ief7967e33b9a0d7e94a667172121d8007f78115b (cherry picked from commit 17182ca46f7a8f3ae03bb8f5a16116246a5fbd91)
This commit is contained in:
committed by
Garfield Tan
parent
92b6768eaa
commit
d9ddb3ba5b
35
packages/DocumentsUI/res/drawable/root_item_background.xml
Normal file
35
packages/DocumentsUI/res/drawable/root_item_background.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2016 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.
|
||||
-->
|
||||
|
||||
<ripple
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res/com.android.documentsui"
|
||||
android:color="?attr/colorControlHighlight">
|
||||
<item
|
||||
android:id="@android:id/mask"
|
||||
android:drawable="@android:color/white"/>
|
||||
|
||||
<item>
|
||||
<selector>
|
||||
<item
|
||||
app:state_highlighted="true"
|
||||
android:drawable="@color/item_doc_background_selected"/>
|
||||
<item
|
||||
app:state_highlighted="false"
|
||||
android:drawable="@android:color/transparent"/>
|
||||
</selector>
|
||||
</item>
|
||||
</ripple>
|
||||
@@ -19,5 +19,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="8dp"
|
||||
android:listSelector="@android:color/transparent"
|
||||
android:drawSelectorOnTop="true"
|
||||
android:divider="@null" />
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<com.android.documentsui.RootItemView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp"
|
||||
@@ -22,7 +23,8 @@
|
||||
android:paddingEnd="@dimen/list_item_padding"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:baselineAligned="false">
|
||||
android:baselineAligned="false"
|
||||
android:background="@drawable/root_item_background">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="@dimen/icon_size"
|
||||
@@ -68,4 +70,4 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</com.android.documentsui.RootItemView>
|
||||
|
||||
@@ -17,4 +17,8 @@
|
||||
<declare-styleable name="DocumentsTheme">
|
||||
<attr name="colorActionMode" format="color"/>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="RootItemView">
|
||||
<attr name="state_highlighted" format="boolean"/>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
|
||||
@@ -17,4 +17,5 @@
|
||||
<resources>
|
||||
<item name="drag_hovering_tag" type="id" />
|
||||
<item name="item_position_tag" type="id" />
|
||||
<item name="layout_id_tag" type="id" />
|
||||
</resources>
|
||||
@@ -256,8 +256,6 @@ public abstract class BaseActivity extends Activity
|
||||
} else {
|
||||
new PickRootTask(this, root).executeOnExecutor(getExecutorForCurrentDirectory());
|
||||
}
|
||||
|
||||
mNavigator.revealRootsDrawer(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.documentsui;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Log;
|
||||
import android.view.DragEvent;
|
||||
import android.view.View;
|
||||
@@ -62,6 +63,7 @@ public class ItemDragListener<H extends DragHost> implements OnDragListener {
|
||||
handleEnteredEvent(v);
|
||||
return true;
|
||||
case DragEvent.ACTION_DRAG_LOCATION:
|
||||
handleLocationEvent(v, event.getX(), event.getY());
|
||||
return true;
|
||||
case DragEvent.ACTION_DRAG_EXITED:
|
||||
case DragEvent.ACTION_DRAG_ENDED:
|
||||
@@ -83,6 +85,13 @@ public class ItemDragListener<H extends DragHost> implements OnDragListener {
|
||||
mHoverTimer.schedule(task, ViewConfiguration.getLongPressTimeout());
|
||||
}
|
||||
|
||||
private void handleLocationEvent(View v, float x, float y) {
|
||||
Drawable background = v.getBackground();
|
||||
if (background != null) {
|
||||
background.setHotspot(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleExitedEndedEvent(View v) {
|
||||
mDragHost.setDropTargetHighlight(v, false);
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.documentsui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
public final class RootItemView extends LinearLayout {
|
||||
private static final int[] STATE_HIGHLIGHTED = {R.attr.state_highlighted};
|
||||
|
||||
private boolean mHighlighted = false;
|
||||
|
||||
public RootItemView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] onCreateDrawableState(int extraSpace) {
|
||||
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
|
||||
|
||||
if (mHighlighted) {
|
||||
mergeDrawableStates(drawableState, STATE_HIGHLIGHTED);
|
||||
}
|
||||
|
||||
return drawableState;
|
||||
}
|
||||
|
||||
public void setHighlight(boolean highlight) {
|
||||
mHighlighted = highlight;
|
||||
refreshDrawableState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesizes pressed state to trick RippleDrawable starting a ripple effect.
|
||||
*/
|
||||
public void drawRipple() {
|
||||
setPressed(true);
|
||||
setPressed(false);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package com.android.documentsui;
|
||||
|
||||
import static com.android.documentsui.Shared.DEBUG;
|
||||
|
||||
import android.annotation.LayoutRes;
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
@@ -26,12 +27,13 @@ import android.app.LoaderManager.LoaderCallbacks;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.Loader;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.Formatter;
|
||||
@@ -54,7 +56,9 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -198,6 +202,10 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
|
||||
*/
|
||||
@Override
|
||||
public void onViewHovered(View view) {
|
||||
// SpacerView doesn't have DragListener so this view is guaranteed to be a RootItemView.
|
||||
RootItemView itemView = (RootItemView) view;
|
||||
itemView.drawRipple();
|
||||
|
||||
final int position = (Integer) view.getTag(R.id.item_position_tag);
|
||||
final Item item = mAdapter.getItem(position);
|
||||
item.open(this);
|
||||
@@ -205,10 +213,9 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
|
||||
|
||||
@Override
|
||||
public void setDropTargetHighlight(View v, boolean highlight) {
|
||||
@ColorRes int colorId = highlight ? R.color.item_doc_background_selected
|
||||
: android.R.color.transparent;
|
||||
|
||||
v.setBackgroundColor(getActivity().getColor(colorId));
|
||||
// SpacerView doesn't have DragListener so this view is guaranteed to be a RootItemView.
|
||||
RootItemView itemView = (RootItemView) v;
|
||||
itemView.setHighlight(highlight);
|
||||
}
|
||||
|
||||
private OnItemClickListener mItemListener = new OnItemClickListener() {
|
||||
@@ -216,6 +223,8 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final Item item = mAdapter.getItem(position);
|
||||
item.open(RootsFragment.this);
|
||||
|
||||
((BaseActivity) getActivity()).setRootsDrawerOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -223,32 +232,34 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
|
||||
@Override
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final Item item = mAdapter.getItem(position);
|
||||
if (item instanceof AppItem) {
|
||||
showAppDetails(((AppItem) item).info);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return item.showAppDetails(RootsFragment.this);
|
||||
}
|
||||
};
|
||||
|
||||
private static abstract class Item {
|
||||
private final int mLayoutId;
|
||||
private final @LayoutRes int mLayoutId;
|
||||
private final String mStringId;
|
||||
|
||||
public Item(int layoutId) {
|
||||
public Item(@LayoutRes int layoutId, String stringId) {
|
||||
mLayoutId = layoutId;
|
||||
mStringId = stringId;
|
||||
}
|
||||
|
||||
public View getView(View convertView, ViewGroup parent) {
|
||||
// Disable recycling views because 1) it's very unlikely a view can be recycled here;
|
||||
// 2) there is no easy way for us to know with which layout id the convertView was
|
||||
// inflated; and 3) simplicity is much appreciated at this time.
|
||||
convertView = LayoutInflater.from(parent.getContext())
|
||||
if (convertView == null
|
||||
|| (Integer) convertView.getTag(R.id.layout_id_tag) != mLayoutId) {
|
||||
convertView = LayoutInflater.from(parent.getContext())
|
||||
.inflate(mLayoutId, parent, false);
|
||||
}
|
||||
convertView.setTag(R.id.layout_id_tag, mLayoutId);
|
||||
bindView(convertView);
|
||||
return convertView;
|
||||
}
|
||||
|
||||
boolean showAppDetails(RootsFragment fragment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
abstract void bindView(View convertView);
|
||||
|
||||
abstract boolean isDropTarget();
|
||||
@@ -257,13 +268,23 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
|
||||
}
|
||||
|
||||
private static class RootItem extends Item {
|
||||
private static final String STRING_ID_FORMAT = "RootItem{%s/%s}";
|
||||
|
||||
public final RootInfo root;
|
||||
|
||||
public RootItem(RootInfo root) {
|
||||
super(R.layout.item_root);
|
||||
super(R.layout.item_root, getStringId(root));
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
private static String getStringId(RootInfo root) {
|
||||
// Empty URI authority is invalid, so we can use empty string if root.authority is null.
|
||||
// Directly passing null to String.format() will write "null" which can be a valid URI
|
||||
// authority.
|
||||
String authority = (root.authority == null ? "" : root.authority);
|
||||
return String.format(STRING_ID_FORMAT, authority, root.rootId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View convertView) {
|
||||
final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
|
||||
@@ -291,7 +312,7 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(RootsFragment fragment) {
|
||||
void open(RootsFragment fragment) {
|
||||
BaseActivity activity = BaseActivity.get(fragment);
|
||||
Metrics.logRootVisited(fragment.getActivity(), root);
|
||||
activity.onRootPicked(root);
|
||||
@@ -299,8 +320,11 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
|
||||
}
|
||||
|
||||
private static class SpacerItem extends Item {
|
||||
private static final String STRING_ID = "SpacerItem";
|
||||
|
||||
public SpacerItem() {
|
||||
super(R.layout.item_root_spacer);
|
||||
// Multiple spacer items can share the same string id as they're identical.
|
||||
super(R.layout.item_root_spacer, STRING_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -314,19 +338,35 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(RootsFragment fragment) {
|
||||
void open(RootsFragment fragment) {
|
||||
if (DEBUG) Log.d(TAG, "Ignoring click/hover on spacer item.");
|
||||
}
|
||||
}
|
||||
|
||||
private static class AppItem extends Item {
|
||||
private static final String STRING_ID_FORMAT = "AppItem{%s/%s}";
|
||||
|
||||
public final ResolveInfo info;
|
||||
|
||||
public AppItem(ResolveInfo info) {
|
||||
super(R.layout.item_root);
|
||||
super(R.layout.item_root, getStringId(info));
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
private static String getStringId(ResolveInfo info) {
|
||||
ActivityInfo activityInfo = info.activityInfo;
|
||||
|
||||
String component = String.format(
|
||||
STRING_ID_FORMAT, activityInfo.applicationInfo.packageName, activityInfo.name);
|
||||
return component;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean showAppDetails(RootsFragment fragment) {
|
||||
fragment.showAppDetails(info);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void bindView(View convertView) {
|
||||
final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
|
||||
@@ -348,7 +388,7 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(RootsFragment fragment) {
|
||||
void open(RootsFragment fragment) {
|
||||
DocumentsActivity activity = DocumentsActivity.get(fragment);
|
||||
Metrics.logAppVisited(fragment.getActivity(), info);
|
||||
activity.onAppPicked(info);
|
||||
@@ -356,6 +396,9 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
|
||||
}
|
||||
|
||||
private static class RootsAdapter extends ArrayAdapter<Item> {
|
||||
private static final Map<String, Long> sIdMap = new HashMap<String, Long>();
|
||||
// the next available id to associate with a new string id
|
||||
private static long sNextAvailableId;
|
||||
|
||||
private OnDragListener mDragListener;
|
||||
|
||||
@@ -429,6 +472,30 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStableIds() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
// Ensure this method is only called in main thread because we don't have any
|
||||
// concurrency protection.
|
||||
assert(Looper.myLooper() == Looper.getMainLooper());
|
||||
|
||||
String stringId = getItem(position).mStringId;
|
||||
|
||||
long id;
|
||||
if (sIdMap.containsKey(stringId)) {
|
||||
id = sIdMap.get(stringId);
|
||||
} else {
|
||||
id = sNextAvailableId++;
|
||||
sIdMap.put(stringId, id);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
final Item item = getItem(position);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.documentsui;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
@@ -29,6 +30,7 @@ import android.view.View;
|
||||
|
||||
import com.android.documentsui.testing.ClipDatas;
|
||||
import com.android.documentsui.testing.DragEvents;
|
||||
import com.android.documentsui.testing.TestDrawable;
|
||||
import com.android.documentsui.testing.TestTimer;
|
||||
import com.android.documentsui.testing.Views;
|
||||
|
||||
@@ -46,6 +48,7 @@ public class ItemDragListenerTest {
|
||||
private static final long DELAY_AFTER_HOVERING = ItemDragListener.SPRING_TIMEOUT + 1;
|
||||
|
||||
private View mTestView;
|
||||
private TestDrawable mTestBackground;
|
||||
private TestDragHost mTestDragHost;
|
||||
private TestTimer mTestTimer;
|
||||
|
||||
@@ -54,9 +57,10 @@ public class ItemDragListenerTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
mTestView = Views.createTestView();
|
||||
|
||||
mTestBackground = new TestDrawable();
|
||||
mTestTimer = new TestTimer();
|
||||
mTestDragHost = new TestDragHost();
|
||||
|
||||
mListener = new TestDragListener(mTestDragHost, mTestTimer);
|
||||
}
|
||||
|
||||
@@ -87,6 +91,25 @@ public class ItemDragListenerTest {
|
||||
assertNull(mTestDragHost.mHighlightedView);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDragLocation_notCrashWithoutBackground() {
|
||||
DragEvent locationEvent = DragEvents.createTestLocationEvent(3, 4);
|
||||
mListener.onDrag(mTestView, locationEvent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDragLocation_setHotSpotOnBackground() {
|
||||
Views.setBackground(mTestView, mTestBackground);
|
||||
|
||||
final float x = 2;
|
||||
final float y = 4;
|
||||
DragEvent locationEvent = DragEvents.createTestLocationEvent(x, y);
|
||||
mListener.onDrag(mTestView, locationEvent);
|
||||
|
||||
assertEquals(x, mTestBackground.hotspotX, 0);
|
||||
assertEquals(y, mTestBackground.hotspotY, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHover_OpensView() {
|
||||
triggerDragEvent(DragEvent.ACTION_DRAG_ENTERED);
|
||||
|
||||
@@ -32,6 +32,14 @@ public final class DragEvents {
|
||||
return mockEvent;
|
||||
}
|
||||
|
||||
public static DragEvent createTestLocationEvent(float x, float y) {
|
||||
final DragEvent locationEvent = createTestDragEvent(DragEvent.ACTION_DRAG_LOCATION);
|
||||
Mockito.when(locationEvent.getX()).thenReturn(x);
|
||||
Mockito.when(locationEvent.getY()).thenReturn(y);
|
||||
|
||||
return locationEvent;
|
||||
}
|
||||
|
||||
public static DragEvent createTestDropEvent(ClipData clipData) {
|
||||
final DragEvent dropEvent = createTestDragEvent(DragEvent.ACTION_DROP);
|
||||
Mockito.when(dropEvent.getClipData()).thenReturn(clipData);
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.documentsui.testing;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
public class TestDrawable extends Drawable {
|
||||
|
||||
public float hotspotX;
|
||||
public float hotspotY;
|
||||
|
||||
@Override
|
||||
public void setHotspot(float x, float y) {
|
||||
hotspotX = x;
|
||||
hotspotY = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter colorFilter) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.documentsui.testing;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
@@ -31,4 +32,8 @@ public final class Views {
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
public static void setBackground(View testView, Drawable background) {
|
||||
Mockito.when(testView.getBackground()).thenReturn(background);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user