Move GestureListener to own file.
And: - make MotionInputEvent AutoCloseable (and update obtainers accordingly). - remove unused constructor args and overloading from MultiSelectManager. Change-Id: I335a95c3d05ab10bdcbfebab8dc69f0b2f681e3a
This commit is contained in:
@@ -138,7 +138,7 @@ public final class Events {
|
||||
int getItemPosition();
|
||||
}
|
||||
|
||||
public static final class MotionInputEvent implements InputEvent {
|
||||
public static final class MotionInputEvent implements InputEvent, AutoCloseable {
|
||||
private static final String TAG = "MotionInputEvent";
|
||||
|
||||
private static final Pools.SimplePool<MotionInputEvent> sPool = new Pools.SimplePool<>(1);
|
||||
@@ -199,6 +199,11 @@ public final class Events {
|
||||
assert(released);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseEvent() {
|
||||
return Events.isMouseEvent(mEvent);
|
||||
|
||||
@@ -52,13 +52,13 @@ import com.android.documentsui.model.DocumentStack;
|
||||
import com.android.documentsui.model.DurableUtils;
|
||||
import com.android.documentsui.model.RootInfo;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
/**
|
||||
* Display directories where recent creates took place.
|
||||
*/
|
||||
@@ -141,17 +141,13 @@ public class RecentsCreateFragment extends Fragment {
|
||||
new RecyclerView.OnItemTouchListener() {
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
|
||||
final MotionInputEvent event = MotionInputEvent.obtain(e, mRecView);
|
||||
try {
|
||||
try (MotionInputEvent event = MotionInputEvent.obtain(e, mRecView)) {
|
||||
if (event.isOverItem() && event.isActionUp()) {
|
||||
final DocumentStack stack = mAdapter.getItem(event.getItemPosition());
|
||||
((BaseActivity) getActivity()).onStackPicked(stack);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} finally {
|
||||
event.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +243,7 @@ public class RecentsCreateFragment extends Fragment {
|
||||
|
||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
||||
return new StackHolder(
|
||||
(View) inflater.inflate(R.layout.item_doc_list, parent, false));
|
||||
inflater.inflate(R.layout.item_doc_list, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -85,21 +85,15 @@ public class BandController extends RecyclerView.OnScrollListener {
|
||||
new RecyclerView.OnItemTouchListener() {
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
|
||||
final MotionInputEvent event = MotionInputEvent.obtain(e, view);
|
||||
try {
|
||||
try (MotionInputEvent event = MotionInputEvent.obtain(e, view)) {
|
||||
return handleEvent(event);
|
||||
} finally {
|
||||
event.recycle();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
|
||||
if (Events.isMouseEvent(e)) {
|
||||
final MotionInputEvent event = MotionInputEvent.obtain(e, view);
|
||||
try {
|
||||
try (MotionInputEvent event = MotionInputEvent.obtain(e, view)) {
|
||||
processInputEvent(event);
|
||||
} finally {
|
||||
event.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,13 +58,11 @@ import android.util.SparseArray;
|
||||
import android.view.ActionMode;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.DragEvent;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
@@ -74,11 +72,9 @@ import android.widget.Toolbar;
|
||||
import com.android.documentsui.BaseActivity;
|
||||
import com.android.documentsui.DirectoryLoader;
|
||||
import com.android.documentsui.DirectoryResult;
|
||||
import com.android.documentsui.UrisSupplier;
|
||||
import com.android.documentsui.DocumentClipper;
|
||||
import com.android.documentsui.DocumentsActivity;
|
||||
import com.android.documentsui.DocumentsApplication;
|
||||
import com.android.documentsui.Events;
|
||||
import com.android.documentsui.Events.MotionInputEvent;
|
||||
import com.android.documentsui.ItemDragListener;
|
||||
import com.android.documentsui.MenuManager;
|
||||
@@ -94,6 +90,7 @@ import com.android.documentsui.Shared;
|
||||
import com.android.documentsui.Snackbars;
|
||||
import com.android.documentsui.State;
|
||||
import com.android.documentsui.State.ViewMode;
|
||||
import com.android.documentsui.UrisSupplier;
|
||||
import com.android.documentsui.dirlist.MultiSelectManager.Selection;
|
||||
import com.android.documentsui.model.DocumentInfo;
|
||||
import com.android.documentsui.model.RootInfo;
|
||||
@@ -295,22 +292,27 @@ public class DirectoryFragment extends Fragment
|
||||
}
|
||||
mRecView.setLayoutManager(mLayout);
|
||||
|
||||
mGestureDetector =
|
||||
new ListeningGestureDetector(this.getContext(), mDragHelper, new GestureListener());
|
||||
|
||||
mRecView.addOnItemTouchListener(mGestureDetector);
|
||||
mEmptyView.setOnTouchListener(mGestureDetector);
|
||||
|
||||
// TODO: instead of inserting the view into the constructor, extract listener-creation code
|
||||
// and set the listener on the view after the fact. Then the view doesn't need to be passed
|
||||
// into the selection manager.
|
||||
mSelectionManager = new MultiSelectManager(
|
||||
mRecView,
|
||||
mAdapter,
|
||||
state.allowMultiple
|
||||
? MultiSelectManager.MODE_MULTIPLE
|
||||
: MultiSelectManager.MODE_SINGLE,
|
||||
null);
|
||||
: MultiSelectManager.MODE_SINGLE);
|
||||
|
||||
GestureListener gestureListener = new GestureListener(
|
||||
mSelectionManager,
|
||||
mRecView,
|
||||
this::getTarget,
|
||||
this::onDoubleTap,
|
||||
this::onRightClick);
|
||||
|
||||
mGestureDetector =
|
||||
new ListeningGestureDetector(this.getContext(), mDragHelper, gestureListener);
|
||||
|
||||
mRecView.addOnItemTouchListener(mGestureDetector);
|
||||
mEmptyView.setOnTouchListener(mGestureDetector);
|
||||
|
||||
if (state.allowMultiple) {
|
||||
mBandController = new BandController(mRecView, mAdapter, mSelectionManager);
|
||||
@@ -426,44 +428,38 @@ public class DirectoryFragment extends Fragment
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean onRightClick(MotionEvent e) {
|
||||
// First get target to see if it's a blank window or a file/doc
|
||||
final MotionInputEvent event = MotionInputEvent.obtain(e, mRecView);
|
||||
try {
|
||||
if (event.getItemPosition() != RecyclerView.NO_POSITION) {
|
||||
final DocumentHolder holder = getTarget(event);
|
||||
String modelId = getModelId(holder.itemView);
|
||||
if (!mSelectionManager.getSelection().contains(modelId)) {
|
||||
mSelectionManager.clearSelection();
|
||||
// Set selection on the one single item
|
||||
List<String> ids = Collections.singletonList(modelId);
|
||||
mSelectionManager.setItemsSelected(ids, true);
|
||||
}
|
||||
protected boolean onRightClick(MotionInputEvent e) {
|
||||
if (e.getItemPosition() != RecyclerView.NO_POSITION) {
|
||||
final DocumentHolder holder = getTarget(e);
|
||||
String modelId = getModelId(holder.itemView);
|
||||
if (!mSelectionManager.getSelection().contains(modelId)) {
|
||||
mSelectionManager.clearSelection();
|
||||
// Set selection on the one single item
|
||||
List<String> ids = Collections.singletonList(modelId);
|
||||
mSelectionManager.setItemsSelected(ids, true);
|
||||
}
|
||||
|
||||
// We are registering for context menu here so long-press doesn't trigger this
|
||||
// floating context menu, and then quickly unregister right afterwards
|
||||
registerForContextMenu(holder.itemView);
|
||||
mRecView.showContextMenuForChild(holder.itemView,
|
||||
e.getX() - holder.itemView.getLeft(), e.getY() - holder.itemView.getTop());
|
||||
unregisterForContextMenu(holder.itemView);
|
||||
}
|
||||
// If there was no corresponding item pos, that means user right-clicked on the blank
|
||||
// pane
|
||||
// We would want to show different options then, and not select any item
|
||||
// The blank pane could be the recyclerView or the emptyView, so we need to register
|
||||
// according to whichever one is visible
|
||||
else if (mEmptyView.getVisibility() == View.VISIBLE) {
|
||||
registerForContextMenu(mEmptyView);
|
||||
mEmptyView.showContextMenu(e.getX(), e.getY());
|
||||
unregisterForContextMenu(mEmptyView);
|
||||
return true;
|
||||
} else {
|
||||
registerForContextMenu(mRecView);
|
||||
mRecView.showContextMenu(e.getX(), e.getY());
|
||||
unregisterForContextMenu(mRecView);
|
||||
}
|
||||
} finally {
|
||||
event.recycle();
|
||||
// We are registering for context menu here so long-press doesn't trigger this
|
||||
// floating context menu, and then quickly unregister right afterwards
|
||||
registerForContextMenu(holder.itemView);
|
||||
mRecView.showContextMenuForChild(holder.itemView,
|
||||
e.getX() - holder.itemView.getLeft(), e.getY() - holder.itemView.getTop());
|
||||
unregisterForContextMenu(holder.itemView);
|
||||
}
|
||||
// If there was no corresponding item pos, that means user right-clicked on the blank
|
||||
// pane
|
||||
// We would want to show different options then, and not select any item
|
||||
// The blank pane could be the recyclerView or the emptyView, so we need to register
|
||||
// according to whichever one is visible
|
||||
else if (mEmptyView.getVisibility() == View.VISIBLE) {
|
||||
registerForContextMenu(mEmptyView);
|
||||
mEmptyView.showContextMenu(e.getX(), e.getY());
|
||||
unregisterForContextMenu(mEmptyView);
|
||||
return true;
|
||||
} else {
|
||||
registerForContextMenu(mRecView);
|
||||
mRecView.showContextMenu(e.getX(), e.getY());
|
||||
unregisterForContextMenu(mRecView);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1554,81 +1550,6 @@ public class DirectoryFragment extends Fragment
|
||||
return mTuner.canSelectType(docMimeType, docFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
* The gesture listener for items in the list/grid view. Interprets gestures and sends the
|
||||
* events to the target DocumentHolder, whence they are routed to the appropriate listener.
|
||||
*/
|
||||
class GestureListener extends GestureDetector.SimpleOnGestureListener {
|
||||
// From the RecyclerView, we get two events sent to
|
||||
// ListeningGestureDetector#onInterceptTouchEvent on a mouse click; we first get an
|
||||
// ACTION_DOWN Event for clicking on the mouse, and then an ACTION_UP event from releasing
|
||||
// the mouse click. ACTION_UP event doesn't have information regarding the button (primary
|
||||
// vs. secondary), so we have to save that somewhere first from ACTION_DOWN, and then reuse
|
||||
// it later. The ACTION_DOWN event doesn't get forwarded to GestureListener, so we have open
|
||||
// up a public set method to set it.
|
||||
private int mLastButtonState = -1;
|
||||
|
||||
public void setLastButtonState(int state) {
|
||||
mLastButtonState = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSingleTapUp(MotionEvent e) {
|
||||
// Single tap logic:
|
||||
// We first see if it's a mouse event, and if it was right click by checking on
|
||||
// @{code ListeningGestureDetector#mLastButtonState}
|
||||
// If the selection manager is active, it gets first whack at handling tap
|
||||
// events. Otherwise, tap events are routed to the target DocumentHolder.
|
||||
if (Events.isMouseEvent(e) && mLastButtonState == MotionEvent.BUTTON_SECONDARY) {
|
||||
mLastButtonState = -1;
|
||||
return onRightClick(e);
|
||||
}
|
||||
|
||||
final MotionInputEvent event = MotionInputEvent.obtain(e, mRecView);
|
||||
try {
|
||||
boolean handled = mSelectionManager.onSingleTapUp(event);
|
||||
|
||||
if (handled) {
|
||||
return handled;
|
||||
}
|
||||
|
||||
// Give the DocumentHolder a crack at the event.
|
||||
DocumentHolder holder = DirectoryFragment.this.getTarget(event);
|
||||
if (holder != null) {
|
||||
handled = holder.onSingleTapUp(e);
|
||||
}
|
||||
|
||||
return handled;
|
||||
} finally {
|
||||
event.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLongPress(MotionEvent e) {
|
||||
// Long-press events get routed directly to the selection manager. They can be
|
||||
// changed to route through the DocumentHolder if necessary.
|
||||
final MotionInputEvent event = MotionInputEvent.obtain(e, mRecView);
|
||||
try {
|
||||
mSelectionManager.onLongPress(event);
|
||||
} finally {
|
||||
event.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTap(MotionEvent e) {
|
||||
// Double-tap events are handled directly by the DirectoryFragment. They can be changed
|
||||
// to route through the DocumentHolder if necessary.
|
||||
final MotionInputEvent event = MotionInputEvent.obtain(e, mRecView);
|
||||
return DirectoryFragment.this.onDoubleTap(event);
|
||||
}
|
||||
|
||||
public boolean onRightClick(MotionEvent e) {
|
||||
return DirectoryFragment.this.onRightClick(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void showDirectory(
|
||||
FragmentManager fm, RootInfo root, DocumentInfo doc, int anim) {
|
||||
create(fm, TYPE_NORMAL, root, doc, null, anim);
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.dirlist;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.documentsui.Events;
|
||||
import com.android.documentsui.Events.MotionInputEvent;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* The gesture listener for items in the directly list, interprets gestures, and sends the
|
||||
* events to the target DocumentHolder, whence they are routed to the appropriate listener.
|
||||
*/
|
||||
final class GestureListener extends GestureDetector.SimpleOnGestureListener {
|
||||
// From the RecyclerView, we get two events sent to
|
||||
// ListeningGestureDetector#onInterceptTouchEvent on a mouse click; we first get an
|
||||
// ACTION_DOWN Event for clicking on the mouse, and then an ACTION_UP event from releasing
|
||||
// the mouse click. ACTION_UP event doesn't have information regarding the button (primary
|
||||
// vs. secondary), so we have to save that somewhere first from ACTION_DOWN, and then reuse
|
||||
// it later. The ACTION_DOWN event doesn't get forwarded to GestureListener, so we have open
|
||||
// up a public set method to set it.
|
||||
private int mLastButtonState = -1;
|
||||
private MultiSelectManager mSelectionMgr;
|
||||
private RecyclerView mRecView;
|
||||
private Function<MotionInputEvent, DocumentHolder> mDocFinder;
|
||||
private Predicate<MotionInputEvent> mDoubleTapHandler;
|
||||
private Predicate<MotionInputEvent> mRightClickHandler;
|
||||
|
||||
public GestureListener(
|
||||
MultiSelectManager selectionMgr,
|
||||
RecyclerView recView,
|
||||
Function<MotionInputEvent, DocumentHolder> docFinder,
|
||||
Predicate<MotionInputEvent> doubleTapHandler,
|
||||
Predicate<MotionInputEvent> rightClickHandler) {
|
||||
mSelectionMgr = selectionMgr;
|
||||
mRecView = recView;
|
||||
mDocFinder = docFinder;
|
||||
mDoubleTapHandler = doubleTapHandler;
|
||||
mRightClickHandler = rightClickHandler;
|
||||
}
|
||||
|
||||
public void setLastButtonState(int state) {
|
||||
mLastButtonState = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSingleTapUp(MotionEvent e) {
|
||||
// Single tap logic:
|
||||
// We first see if it's a mouse event, and if it was right click by checking on
|
||||
// @{code ListeningGestureDetector#mLastButtonState}
|
||||
// If the selection manager is active, it gets first whack at handling tap
|
||||
// events. Otherwise, tap events are routed to the target DocumentHolder.
|
||||
if (Events.isMouseEvent(e) && mLastButtonState == MotionEvent.BUTTON_SECONDARY) {
|
||||
mLastButtonState = -1;
|
||||
return onRightClick(e);
|
||||
}
|
||||
|
||||
try (MotionInputEvent event = MotionInputEvent.obtain(e, mRecView)) {
|
||||
boolean handled = mSelectionMgr.onSingleTapUp(event);
|
||||
|
||||
if (handled) {
|
||||
return handled;
|
||||
}
|
||||
|
||||
// Give the DocumentHolder a crack at the event.
|
||||
DocumentHolder holder = mDocFinder.apply(event);
|
||||
if (holder != null) {
|
||||
handled = holder.onSingleTapUp(e);
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLongPress(MotionEvent e) {
|
||||
// Long-press events get routed directly to the selection manager. They can be
|
||||
// changed to route through the DocumentHolder if necessary.
|
||||
try (MotionInputEvent event = MotionInputEvent.obtain(e, mRecView)) {
|
||||
mSelectionMgr.onLongPress(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTap(MotionEvent e) {
|
||||
// Double-tap events are handled directly by the DirectoryFragment. They can be changed
|
||||
// to route through the DocumentHolder if necessary.
|
||||
|
||||
try (MotionInputEvent event = MotionInputEvent.obtain(e, mRecView)) {
|
||||
return mDoubleTapHandler.test(event);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onRightClick(MotionEvent e) {
|
||||
try (MotionInputEvent event = MotionInputEvent.obtain(e, mRecView)) {
|
||||
return mRightClickHandler.test(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import android.view.View;
|
||||
import android.view.View.OnTouchListener;
|
||||
|
||||
import com.android.documentsui.Events;
|
||||
import com.android.documentsui.dirlist.DirectoryFragment.GestureListener;
|
||||
|
||||
// Previously we listened to events with one class, only to bounce them forward
|
||||
// to GestureDetector. We're still doing that here, but with a single class
|
||||
|
||||
@@ -65,39 +65,13 @@ public final class MultiSelectManager {
|
||||
private Range mRanger;
|
||||
private boolean mSingleSelect;
|
||||
|
||||
/**
|
||||
* @param mode Selection single or multiple selection mode.
|
||||
* @param initialSelection selection state probably preserved in external state.
|
||||
*/
|
||||
public MultiSelectManager(
|
||||
final RecyclerView recyclerView,
|
||||
DocumentsAdapter adapter,
|
||||
@SelectionMode int mode,
|
||||
@Nullable Selection initialSelection) {
|
||||
|
||||
this(adapter, mode, initialSelection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance with {@code adapter} and {@code helper}.
|
||||
* @param runtimeSelectionEnvironment
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting
|
||||
MultiSelectManager(
|
||||
DocumentsAdapter adapter,
|
||||
@SelectionMode int mode,
|
||||
@Nullable Selection initialSelection) {
|
||||
public MultiSelectManager(DocumentsAdapter adapter, @SelectionMode int mode) {
|
||||
|
||||
assert(adapter != null);
|
||||
|
||||
mAdapter = adapter;
|
||||
|
||||
mSingleSelect = mode == MODE_SINGLE;
|
||||
if (initialSelection != null) {
|
||||
mSelection.copyFrom(initialSelection);
|
||||
}
|
||||
|
||||
mAdapter.registerAdapterDataObserver(
|
||||
new RecyclerView.AdapterDataObserver() {
|
||||
|
||||
|
||||
@@ -46,10 +46,11 @@ public class MultiSelectManagerTest extends AndroidTestCase {
|
||||
private TestCallback mCallback;
|
||||
private TestDocumentsAdapter mAdapter;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
mCallback = new TestCallback();
|
||||
mAdapter = new TestDocumentsAdapter(items);
|
||||
mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_MULTIPLE, null);
|
||||
mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_MULTIPLE);
|
||||
mManager.addCallback(mCallback);
|
||||
}
|
||||
|
||||
@@ -173,7 +174,7 @@ public class MultiSelectManagerTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
public void testSingleSelectMode() {
|
||||
mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_SINGLE, null);
|
||||
mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_SINGLE);
|
||||
mManager.addCallback(mCallback);
|
||||
longPress(20);
|
||||
tap(13);
|
||||
@@ -181,7 +182,7 @@ public class MultiSelectManagerTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
public void testSingleSelectMode_ShiftTap() {
|
||||
mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_SINGLE, null);
|
||||
mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_SINGLE);
|
||||
mManager.addCallback(mCallback);
|
||||
longPress(13);
|
||||
shiftTap(20);
|
||||
@@ -228,7 +229,7 @@ public class MultiSelectManagerTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
public void testRangeSelection_singleSelect() {
|
||||
mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_SINGLE, null);
|
||||
mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_SINGLE);
|
||||
mManager.addCallback(mCallback);
|
||||
mManager.startRangeSelection(11);
|
||||
mManager.snapRangeSelection(19);
|
||||
|
||||
Reference in New Issue
Block a user