Remove click listener from EasyRecyclerView
This commit is contained in:
5 files changed
+54
-855
No files matched your search
@@ -17,39 +17,22 @@
|
||||
package com.hippo.easyrecyclerview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.TransitionDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.util.StateSet;
|
||||
import android.view.ActionMode;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SoundEffectConstants;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.widget.Checkable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.collection.LongSparseArray;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.hotspot.Hotspot;
|
||||
import com.hippo.yorozuya.MathUtils;
|
||||
import com.hippo.yorozuya.NumberUtils;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import fadeapp.widgets.ScrollLessRecyclerView;
|
||||
|
||||
@@ -140,61 +123,6 @@ public class EasyRecyclerView extends ScrollLessRecyclerView {
|
||||
|
||||
private Adapter mAdapter;
|
||||
|
||||
// For click and long click
|
||||
private boolean mPrePressed = false;
|
||||
private boolean mHasPerformedLongPress = false;
|
||||
private View mMotionView;
|
||||
private int mMotionPosition;
|
||||
private CheckForTap mPendingCheckForTap;
|
||||
private CheckForLongPress mPendingCheckForLongPress;
|
||||
private UnsetPressedState mUnsetPressedState;
|
||||
private PerformClick mPerformClick;
|
||||
private final float[] mTmpPoint = new float[2];
|
||||
private int mTouchSlop = -1;
|
||||
private float mStartX;
|
||||
private float mStartY;
|
||||
private OnItemClickListener mOnItemClickListener;
|
||||
private OnItemLongClickListener mOnItemLongClickListener;
|
||||
|
||||
/**
|
||||
* Indicates whether the list selector should be drawn on top of the children or behind
|
||||
*/
|
||||
boolean mDrawSelectorOnTop = false;
|
||||
/**
|
||||
* The drawable used to draw the selector
|
||||
*/
|
||||
private Drawable mSelector;
|
||||
/**
|
||||
* The current position of the selector in the list.
|
||||
*/
|
||||
private int mSelectorPosition = INVALID_POSITION;
|
||||
/**
|
||||
* Defines the selector's location and dimension at drawing time
|
||||
*/
|
||||
private final Rect mSelectorRect = new Rect();
|
||||
/**
|
||||
* The selection's left padding
|
||||
*/
|
||||
int mSelectionLeftPadding = 0;
|
||||
/**
|
||||
* The selection's top padding
|
||||
*/
|
||||
int mSelectionTopPadding = 0;
|
||||
/**
|
||||
* The selection's right padding
|
||||
*/
|
||||
int mSelectionRightPadding = 0;
|
||||
/**
|
||||
* The selection's bottom padding
|
||||
*/
|
||||
int mSelectionBottomPadding = 0;
|
||||
|
||||
private OnDrawSelectorListener mOnDrawSelectorListener;
|
||||
|
||||
private boolean mClipToPadding = false;
|
||||
|
||||
private boolean mTouchFromScrolling;
|
||||
|
||||
public EasyRecyclerView(Context context) {
|
||||
super(context);
|
||||
setEnableScroll(!Settings.getEInkMode());
|
||||
@@ -210,13 +138,6 @@ public class EasyRecyclerView extends ScrollLessRecyclerView {
|
||||
setEnableScroll(!Settings.getEInkMode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClipToPadding(boolean clipToPadding) {
|
||||
super.setClipToPadding(clipToPadding);
|
||||
|
||||
mClipToPadding = clipToPadding;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@@ -242,208 +163,6 @@ public class EasyRecyclerView extends ScrollLessRecyclerView {
|
||||
}
|
||||
}
|
||||
|
||||
void positionSelector(int position, View sel) {
|
||||
positionSelector(position, sel, false, -1, -1);
|
||||
}
|
||||
|
||||
private void positionSelector(int position, View sel, boolean manageHotspot, float x, float y) {
|
||||
final boolean positionChanged = position != mSelectorPosition;
|
||||
if (position != INVALID_POSITION) {
|
||||
mSelectorPosition = position;
|
||||
}
|
||||
|
||||
final Rect selectorRect = mSelectorRect;
|
||||
selectorRect.set(0, 0, sel.getWidth(), sel.getHeight());
|
||||
|
||||
// Adjust for selection padding.
|
||||
selectorRect.left -= mSelectionLeftPadding;
|
||||
selectorRect.top -= mSelectionTopPadding;
|
||||
selectorRect.right += mSelectionRightPadding;
|
||||
selectorRect.bottom += mSelectionBottomPadding;
|
||||
|
||||
// Update the selector drawable.
|
||||
final Drawable selector = mSelector;
|
||||
if (selector != null) {
|
||||
if (positionChanged) {
|
||||
// Wipe out the current selector state so that we can start
|
||||
// over in the new position with a fresh state.
|
||||
selector.setVisible(false, false);
|
||||
selector.setState(StateSet.NOTHING);
|
||||
}
|
||||
selector.setBounds(selectorRect);
|
||||
if (positionChanged) {
|
||||
if (getVisibility() == VISIBLE) {
|
||||
selector.setVisible(true, false);
|
||||
}
|
||||
updateSelectorState();
|
||||
}
|
||||
if (manageHotspot) {
|
||||
setSelectorHotspot(sel, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setSelectorHotspot(View sel, float x, float y) {
|
||||
Hotspot.setHotspot(mSelector, x - sel.getLeft(), y - sel.getTop());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(@NonNull Canvas canvas) {
|
||||
boolean clipToPadding = mClipToPadding;
|
||||
int saveCount = 0;
|
||||
if (clipToPadding) {
|
||||
saveCount = canvas.save();
|
||||
final int scrollX = getScrollX();
|
||||
final int scrollY = getScrollY();
|
||||
canvas.clipRect(scrollX + getPaddingLeft(), scrollY + getPaddingTop(),
|
||||
scrollX + getRight() - getLeft() - getPaddingRight(),
|
||||
scrollY + getBottom() - getTop() - getPaddingBottom());
|
||||
}
|
||||
|
||||
// Check mMotionView
|
||||
if (mMotionView != null && !ViewCompat.isAttachedToWindow(mMotionView)) {
|
||||
mMotionView = null;
|
||||
}
|
||||
|
||||
boolean drawSelector = mMotionView != null &&
|
||||
mSelectorPosition >= 0 && mSelectorPosition < mAdapter.getItemCount() &&
|
||||
(mOnDrawSelectorListener == null || mOnDrawSelectorListener.beforeDrawSelector(mSelectorPosition));
|
||||
final boolean drawSelectorOnTop = mDrawSelectorOnTop;
|
||||
|
||||
if (drawSelector && !drawSelectorOnTop) {
|
||||
int saveCount2 = canvas.save();
|
||||
canvas.translate(mMotionView.getLeft(), mMotionView.getTop());
|
||||
drawSelector(canvas);
|
||||
canvas.restoreToCount(saveCount2);
|
||||
}
|
||||
|
||||
super.dispatchDraw(canvas);
|
||||
|
||||
if (drawSelector && drawSelectorOnTop) {
|
||||
int saveCount2 = canvas.save();
|
||||
canvas.translate(mMotionView.getLeft(), mMotionView.getTop());
|
||||
drawSelector(canvas);
|
||||
canvas.restoreToCount(saveCount2);
|
||||
}
|
||||
|
||||
if (clipToPadding) {
|
||||
canvas.restoreToCount(saveCount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this view is in a state where the selector should be drawn. This will
|
||||
* happen if we have focus but are not in touch mode, or we are in the middle of displaying
|
||||
* the pressed state for an item.
|
||||
*
|
||||
* @return True if the selector should be shown
|
||||
*/
|
||||
boolean shouldShowSelector() {
|
||||
return (isFocused() && !isInTouchMode()) || isPressed();
|
||||
}
|
||||
|
||||
private void drawSelector(Canvas canvas) {
|
||||
final Drawable selector = mSelector;
|
||||
if (selector != null && !mSelectorRect.isEmpty()) {
|
||||
selector.setBounds(mSelectorRect);
|
||||
selector.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnDrawSelectorListener(OnDrawSelectorListener listener) {
|
||||
mOnDrawSelectorListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls whether the selection highlight drawable should be drawn on top of the item or
|
||||
* behind it.
|
||||
*
|
||||
* @param onTop If true, the selector will be drawn on the item it is highlighting. The default
|
||||
* is false.
|
||||
*/
|
||||
public void setDrawSelectorOnTop(boolean onTop) {
|
||||
mDrawSelectorOnTop = onTop;
|
||||
}
|
||||
|
||||
public void setSelector(Drawable sel) {
|
||||
if (mSelector != null) {
|
||||
mSelector.setCallback(null);
|
||||
unscheduleDrawable(mSelector);
|
||||
}
|
||||
mSelector = sel;
|
||||
Rect padding = new Rect();
|
||||
sel.getPadding(padding);
|
||||
mSelectionLeftPadding = padding.left;
|
||||
mSelectionTopPadding = padding.top;
|
||||
mSelectionRightPadding = padding.right;
|
||||
mSelectionBottomPadding = padding.bottom;
|
||||
sel.setCallback(this);
|
||||
updateSelectorState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the selector {@link android.graphics.drawable.Drawable} that is used to draw the
|
||||
* selection in the list.
|
||||
*
|
||||
* @return the drawable used to display the selector
|
||||
*/
|
||||
public Drawable getSelector() {
|
||||
return mSelector;
|
||||
}
|
||||
|
||||
void updateSelectorState() {
|
||||
if (mSelector != null) {
|
||||
if (shouldShowSelector()) {
|
||||
mSelector.setState(getDrawableState());
|
||||
} else {
|
||||
mSelector.setState(StateSet.NOTHING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawableStateChanged() {
|
||||
super.drawableStateChanged();
|
||||
updateSelectorState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchSetPressed(boolean pressed) {
|
||||
// Don't dispatch setPressed to our children. We call setPressed on ourselves to
|
||||
// get the selector in the right state, but we don't want to press each child.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchDrawableHotspotChanged(float x, float y) {
|
||||
// Don't dispatch hotspot changes to children. We'll manually handle
|
||||
// calling drawableHotspotChanged on the correct child.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verifyDrawable(Drawable dr) {
|
||||
return mSelector == dr || super.verifyDrawable(dr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jumpDrawablesToCurrentState() {
|
||||
super.jumpDrawablesToCurrentState();
|
||||
if (mSelector != null) {
|
||||
mSelector.jumpToCurrentState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChildAttachedToWindow(View child) {
|
||||
super.onChildAttachedToWindow(child);
|
||||
|
||||
if (mCheckStates != null) {
|
||||
int position = getChildAdapterPosition(child);
|
||||
if (position >= 0) {
|
||||
setViewChecked(child, mCheckStates.get(position));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of items currently selected. This will only be valid
|
||||
* if the choice mode is not {@link #CHOICE_MODE_NONE} (default).
|
||||
@@ -672,7 +391,7 @@ public class EasyRecyclerView extends ScrollLessRecyclerView {
|
||||
if (value) {
|
||||
mCheckedIdStates.put(mAdapter.getItemId(position), position);
|
||||
} else {
|
||||
mCheckedIdStates.delete(mAdapter.getItemId(position));
|
||||
mCheckedIdStates.remove(mAdapter.getItemId(position));
|
||||
}
|
||||
}
|
||||
if (oldValue != value) {
|
||||
@@ -797,329 +516,13 @@ public class EasyRecyclerView extends ScrollLessRecyclerView {
|
||||
}
|
||||
|
||||
public static void setViewChecked(View view, boolean checked) {
|
||||
final boolean useActivated = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
|
||||
if (view instanceof Checkable) {
|
||||
((Checkable) view).setChecked(checked);
|
||||
} else if (useActivated) {
|
||||
} else {
|
||||
view.setActivated(checked);
|
||||
}
|
||||
}
|
||||
|
||||
public float getTouchStartX() {
|
||||
return mStartX;
|
||||
}
|
||||
|
||||
public float getTouchStartY() {
|
||||
return mStartY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||
mTouchFromScrolling = SCROLL_STATE_SETTLING == getScrollState();
|
||||
}
|
||||
|
||||
return super.onInterceptTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
if (!isEnabled()) {
|
||||
// A disabled view that is clickable still consumes the touch
|
||||
// events, it just doesn't respond to them.
|
||||
return isClickable() || isLongClickable();
|
||||
}
|
||||
|
||||
switch (ev.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
onTouchDown(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
onTouchMove(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionEvent.ACTION_UP: {
|
||||
onTouchUp(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionEvent.ACTION_CANCEL: {
|
||||
onTouchCancel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
super.onTouchEvent(ev);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onTouchDown(MotionEvent ev) {
|
||||
if (isLayoutFrozen() || mTouchFromScrolling) {
|
||||
return;
|
||||
}
|
||||
|
||||
final float x = ev.getX();
|
||||
final float y = ev.getY();
|
||||
mStartX = x;
|
||||
mStartY = y;
|
||||
|
||||
mMotionView = findChildViewUnder(x, y);
|
||||
mMotionPosition = getChildAdapterPosition(mMotionView);
|
||||
|
||||
if (mMotionView != null && mMotionPosition >= 0 && mMotionView.isEnabled()) {
|
||||
mHasPerformedLongPress = false;
|
||||
|
||||
mPrePressed = true;
|
||||
if (mPendingCheckForTap == null) {
|
||||
mPendingCheckForTap = new CheckForTap();
|
||||
}
|
||||
mPendingCheckForTap.x = x;
|
||||
mPendingCheckForTap.y = y;
|
||||
mPendingCheckForTap.v = mMotionView;
|
||||
mPendingCheckForTap.p = mMotionPosition;
|
||||
postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
|
||||
|
||||
} else {
|
||||
mMotionView = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void onTouchMove(MotionEvent ev) {
|
||||
if (isLayoutFrozen() || mTouchFromScrolling) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mTouchSlop == -1) {
|
||||
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
|
||||
}
|
||||
|
||||
if (mMotionView != null && mMotionPosition >= 0 &&
|
||||
!MathUtils.near(mStartX, mStartY, ev.getX(), ev.getY(), mTouchSlop)) {
|
||||
removeTapCallback();
|
||||
if (mMotionView.isPressed()) {
|
||||
// Remove any future long press/tap checks
|
||||
removeLongPressCallback();
|
||||
mMotionView.setPressed(false);
|
||||
setPressed(false);
|
||||
}
|
||||
updateSelectorState();
|
||||
}
|
||||
}
|
||||
|
||||
private void onTouchUp(MotionEvent ev) {
|
||||
if (isLayoutFrozen() || mTouchFromScrolling) {
|
||||
return;
|
||||
}
|
||||
|
||||
View motionView = mMotionView;
|
||||
int motionPosition = mMotionPosition;
|
||||
|
||||
if (motionView != null && motionPosition >= 0) {
|
||||
final float x = ev.getX();
|
||||
final float y = ev.getY();
|
||||
|
||||
if (motionView.isPressed() || mPrePressed) {
|
||||
// The button is being released before we actually
|
||||
// showed it as pressed. Make it show the pressed
|
||||
// state now (before scheduling the click) to ensure
|
||||
// the user sees it.
|
||||
final float[] point = mTmpPoint;
|
||||
point[0] = x;
|
||||
point[1] = y;
|
||||
ViewUtils.transformPointToViewLocal(point, EasyRecyclerView.this, motionView);
|
||||
setPressed(motionView, true, point[0], point[1]);
|
||||
setPressed(true);
|
||||
positionSelector(mMotionPosition, motionView);
|
||||
if (mSelector != null) {
|
||||
Drawable d = mSelector.getCurrent();
|
||||
if (d instanceof TransitionDrawable) {
|
||||
((TransitionDrawable) d).resetTransition();
|
||||
}
|
||||
setSelectorHotspot(motionView, x, y);
|
||||
}
|
||||
|
||||
if (!mHasPerformedLongPress) {
|
||||
// This is a tap, so remove the longpress check
|
||||
removeLongPressCallback();
|
||||
|
||||
// Use a Runnable and post this rather than calling
|
||||
// performClick directly. This lets other visual state
|
||||
// of the view update before click actions start.
|
||||
if (mPerformClick == null) {
|
||||
mPerformClick = new PerformClick();
|
||||
}
|
||||
mPerformClick.v = motionView;
|
||||
mPerformClick.p = motionPosition;
|
||||
mPerformClick.rememberWindowAttachCount();
|
||||
if (!post(mPerformClick)) {
|
||||
mPerformClick.run();
|
||||
}
|
||||
}
|
||||
|
||||
if (mUnsetPressedState == null) {
|
||||
mUnsetPressedState = new UnsetPressedState();
|
||||
}
|
||||
|
||||
mUnsetPressedState.v = motionView;
|
||||
if (mPrePressed) {
|
||||
postDelayed(mUnsetPressedState, ViewConfiguration.getPressedStateDuration());
|
||||
} else if (!post(mUnsetPressedState)) {
|
||||
// If the post failed, unpress right now
|
||||
mUnsetPressedState.run();
|
||||
}
|
||||
|
||||
removeTapCallback();
|
||||
}
|
||||
|
||||
updateSelectorState();
|
||||
}
|
||||
}
|
||||
|
||||
private void onTouchCancel() {
|
||||
if (isLayoutFrozen() || mTouchFromScrolling) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mMotionView != null && mMotionPosition >= 0) {
|
||||
mMotionView.setPressed(false);
|
||||
setPressed(false);
|
||||
removeTapCallback();
|
||||
removeLongPressCallback();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeTapCallback() {
|
||||
if (mPendingCheckForTap != null) {
|
||||
mPrePressed = false;
|
||||
removeCallbacks(mPendingCheckForTap);
|
||||
mPendingCheckForTap.v = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void removeLongPressCallback() {
|
||||
if (mPendingCheckForLongPress != null) {
|
||||
removeCallbacks(mPendingCheckForLongPress);
|
||||
mPendingCheckForLongPress.v = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void setPressed(View v, boolean pressed, float x, float y) {
|
||||
v.setPressed(pressed);
|
||||
if (pressed && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
v.drawableHotspotChanged(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean performItemClick(View view, int position, long id) {
|
||||
boolean handled = false;
|
||||
boolean dispatchItemClick = true;
|
||||
|
||||
if (mChoiceMode != CHOICE_MODE_NONE && mChoiceMode != CHOICE_MODE_MULTIPLE_CUSTOM) {
|
||||
handled = true;
|
||||
boolean checkedStateChanged = false;
|
||||
|
||||
if (mChoiceMode == CHOICE_MODE_MULTIPLE ||
|
||||
(mChoiceMode == CHOICE_MODE_MULTIPLE_MODAL && mChoiceActionMode != null)) {
|
||||
boolean checked = !mCheckStates.get(position, false);
|
||||
mCheckStates.put(position, checked);
|
||||
if (mCheckedIdStates != null && mAdapter.hasStableIds()) {
|
||||
if (checked) {
|
||||
mCheckedIdStates.put(mAdapter.getItemId(position), position);
|
||||
} else {
|
||||
mCheckedIdStates.delete(mAdapter.getItemId(position));
|
||||
}
|
||||
}
|
||||
if (checked) {
|
||||
mCheckedItemCount++;
|
||||
} else {
|
||||
mCheckedItemCount--;
|
||||
}
|
||||
if (mChoiceActionMode != null) {
|
||||
mMultiChoiceModeCallback.onItemCheckedStateChanged(mChoiceActionMode,
|
||||
position, id, checked);
|
||||
dispatchItemClick = false;
|
||||
}
|
||||
checkedStateChanged = true;
|
||||
} else if (mChoiceMode == CHOICE_MODE_SINGLE) {
|
||||
boolean checked = !mCheckStates.get(position, false);
|
||||
if (checked) {
|
||||
mCheckStates.clear();
|
||||
mCheckStates.put(position, true);
|
||||
if (mCheckedIdStates != null && mAdapter.hasStableIds()) {
|
||||
mCheckedIdStates.clear();
|
||||
mCheckedIdStates.put(mAdapter.getItemId(position), position);
|
||||
}
|
||||
mCheckedItemCount = 1;
|
||||
} else if (mCheckStates.size() == 0 || !mCheckStates.valueAt(0)) {
|
||||
mCheckedItemCount = 0;
|
||||
}
|
||||
checkedStateChanged = true;
|
||||
}
|
||||
|
||||
if (checkedStateChanged) {
|
||||
updateOnScreenCheckedViews();
|
||||
}
|
||||
}
|
||||
|
||||
if (dispatchItemClick) {
|
||||
if (mOnItemClickListener != null) {
|
||||
playSoundEffect(SoundEffectConstants.CLICK);
|
||||
mOnItemClickListener.onItemClick(this, view, position, id);
|
||||
if (view != null) {
|
||||
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
private boolean performItemLongPress(final View child,
|
||||
final int longPressPosition, final long longPressId) {
|
||||
// CHOICE_MODE_MULTIPLE_MODAL takes over long press.
|
||||
if (mChoiceMode == CHOICE_MODE_MULTIPLE_MODAL) {
|
||||
if (mChoiceActionMode == null &&
|
||||
(mChoiceActionMode = startActionMode(mMultiChoiceModeCallback)) != null) {
|
||||
setItemChecked(longPressPosition, true);
|
||||
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean handled = false;
|
||||
if (mOnItemLongClickListener != null) {
|
||||
handled = mOnItemLongClickListener.onItemLongClick(this, child,
|
||||
longPressPosition, longPressId);
|
||||
}
|
||||
if (handled) {
|
||||
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be invoked when an item in this AdapterView has
|
||||
* been clicked.
|
||||
*
|
||||
* @param listener The callback that will be invoked.
|
||||
*/
|
||||
public void setOnItemClickListener(OnItemClickListener listener) {
|
||||
mOnItemClickListener = listener;
|
||||
}
|
||||
|
||||
|
||||
public void setOnItemLongClickListener(OnItemLongClickListener listener) {
|
||||
if (!isLongClickable()) {
|
||||
setLongClickable(true);
|
||||
}
|
||||
mOnItemLongClickListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* This saved state class is a Parcelable and should not extend
|
||||
* {@link android.view.View.BaseSavedState} nor {@link android.view.AbsSavedState}
|
||||
@@ -1255,196 +658,6 @@ public class EasyRecyclerView extends ScrollLessRecyclerView {
|
||||
updateOnScreenCheckedViews();
|
||||
}
|
||||
|
||||
private View findViewForAdapterPosition(int position) {
|
||||
ViewHolder holder = findViewHolderForAdapterPosition(position);
|
||||
if (holder != null) {
|
||||
return holder.itemView;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private final class CheckForTap implements Runnable {
|
||||
float x;
|
||||
float y;
|
||||
View v;
|
||||
int p;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
View view = v;
|
||||
int position = p;
|
||||
if (view != null && position >= 0 && view == findViewForAdapterPosition(position)) {
|
||||
mPrePressed = false;
|
||||
final float[] point = mTmpPoint;
|
||||
point[0] = x;
|
||||
point[1] = y;
|
||||
ViewUtils.transformPointToViewLocal(point, EasyRecyclerView.this, view);
|
||||
setPressed(v, true, point[0], point[1]);
|
||||
setPressed(true);
|
||||
positionSelector(mMotionPosition, v);
|
||||
refreshDrawableState();
|
||||
|
||||
final int longPressTimeout = ViewConfiguration.getLongPressTimeout();
|
||||
final boolean longClickable = isLongClickable();
|
||||
|
||||
if (mSelector != null) {
|
||||
final Drawable d = mSelector.getCurrent();
|
||||
if (d != null && d instanceof TransitionDrawable) {
|
||||
if (longClickable) {
|
||||
((TransitionDrawable) d).startTransition(longPressTimeout);
|
||||
} else {
|
||||
((TransitionDrawable) d).resetTransition();
|
||||
}
|
||||
}
|
||||
setSelectorHotspot(v, x, y);
|
||||
}
|
||||
|
||||
if (longClickable) {
|
||||
mHasPerformedLongPress = false;
|
||||
|
||||
if (mPendingCheckForLongPress == null) {
|
||||
mPendingCheckForLongPress = new CheckForLongPress();
|
||||
}
|
||||
mPendingCheckForLongPress.rememberWindowAttachCount();
|
||||
mPendingCheckForLongPress.v = view;
|
||||
mPendingCheckForLongPress.p = position;
|
||||
postDelayed(mPendingCheckForLongPress, longPressTimeout -
|
||||
ViewConfiguration.getTapTimeout());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Release
|
||||
v = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class CheckForLongPress extends WindowRunnable implements Runnable {
|
||||
View v;
|
||||
int p;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
View view = v;
|
||||
int position = p;
|
||||
if (view != null && position >= 0 && view == findViewForAdapterPosition(position) &&
|
||||
view.isPressed() && view.getParent() != null) {
|
||||
boolean handled = false;
|
||||
|
||||
if (sameWindow()) {
|
||||
handled = performItemLongPress(view, position, getAdapter().getItemId(position));
|
||||
}
|
||||
if (handled) {
|
||||
mHasPerformedLongPress = true;
|
||||
view.setPressed(false);
|
||||
setPressed(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Release
|
||||
v = null;
|
||||
}
|
||||
}
|
||||
|
||||
private final class UnsetPressedState implements Runnable {
|
||||
View v;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (v != null) {
|
||||
v.setPressed(false);
|
||||
setPressed(false);
|
||||
|
||||
// Release
|
||||
v = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PerformClick extends WindowRunnable implements Runnable {
|
||||
View v;
|
||||
int p;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
View view = v;
|
||||
int position = p;
|
||||
if (view != null && position >= 0 && sameWindow()) {
|
||||
performItemClick(view, position, mAdapter.getItemId(position));
|
||||
}
|
||||
|
||||
// Release
|
||||
v = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A base class for Runnables that will check that their view is still attached to
|
||||
* the original window as when the Runnable was created.
|
||||
*/
|
||||
private class WindowRunnable {
|
||||
private int mOriginalAttachCount;
|
||||
|
||||
public void rememberWindowAttachCount() {
|
||||
mOriginalAttachCount = getWindowAttachCount();
|
||||
}
|
||||
|
||||
public boolean sameWindow() {
|
||||
return getWindowAttachCount() == mOriginalAttachCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when an item in the
|
||||
* EasyRecyclerView has been clicked.
|
||||
*/
|
||||
public interface OnItemClickListener {
|
||||
/**
|
||||
* Callback method to be invoked when an item in the EasyRecyclerView
|
||||
* has been clicked.
|
||||
*
|
||||
* @param parent The EasyRecyclerView where the click happened.
|
||||
* @param view The view within the EasyRecyclerView that was clicked
|
||||
* @param position The position of the view in the adapter.
|
||||
* @param id The row id of the item that was clicked.
|
||||
* @return true if the callback consumed the click, false otherwise
|
||||
*/
|
||||
boolean onItemClick(EasyRecyclerView parent, View view, int position, long id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when an item in the
|
||||
* EasyRecyclerView has been clicked and held.
|
||||
*/
|
||||
public interface OnItemLongClickListener {
|
||||
/**
|
||||
* Callback method to be invoked when an item in the EasyRecyclerView
|
||||
* has been clicked and held.
|
||||
*
|
||||
* @param parent The EasyRecyclerView where the click happened
|
||||
* @param view The view within the EasyRecyclerView that was clicked
|
||||
* @param position The position of the view in the list
|
||||
* @param id The row id of the item that was clicked
|
||||
* @return true if the callback consumed the long click, false otherwise
|
||||
*/
|
||||
boolean onItemLongClick(EasyRecyclerView parent, View view, int position, long id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when draw selector.
|
||||
*/
|
||||
public interface OnDrawSelectorListener {
|
||||
/**
|
||||
* Callback method to be invoked before selector draw.
|
||||
*
|
||||
* @param position The EasyRecyclerView where the click happened
|
||||
* @return true if need draw selector, false otherwise
|
||||
*/
|
||||
boolean beforeDrawSelector(int position);
|
||||
}
|
||||
|
||||
/**
|
||||
* A MultiChoiceModeListener receives events for {@link android.widget.AbsListView#CHOICE_MODE_MULTIPLE_MODAL}.
|
||||
* It acts as the {@link android.view.ActionMode.Callback} for the selection mode and also receives
|
||||
@@ -1472,6 +685,7 @@ public class EasyRecyclerView extends ScrollLessRecyclerView {
|
||||
mWrapped = wrapped;
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean hasWrappedCallback() {
|
||||
return mWrapped != null;
|
||||
}
|
||||
|
||||
@@ -1403,10 +1403,6 @@ public class DownloadsScene extends ToolbarScene
|
||||
|
||||
@Override
|
||||
public void onIntoCustomChoice(EasyRecyclerView view) {
|
||||
if (mRecyclerView != null) {
|
||||
mRecyclerView.setOnItemLongClickListener(null);
|
||||
mRecyclerView.setLongClickable(false);
|
||||
}
|
||||
if (mFabLayout != null) {
|
||||
mFabLayout.setExpanded(true);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import android.util.SparseBooleanArray;
|
||||
import android.view.Display;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
@@ -93,7 +92,6 @@ import java.util.List;
|
||||
|
||||
// TODO Get favorite, modify favorite, add favorite, what a mess!
|
||||
public class FavoritesScene extends BaseScene implements
|
||||
EasyRecyclerView.OnItemClickListener,
|
||||
FastScroller.OnDragHandlerListener, SearchBarMover.Helper, SearchBar.Helper,
|
||||
FabLayout.OnClickFabListener, FabLayout.OnExpandListener,
|
||||
EasyRecyclerView.CustomChoiceListener {
|
||||
@@ -426,24 +424,20 @@ public class FavoritesScene extends BaseScene implements
|
||||
|
||||
toolbar.setTitle(R.string.collections);
|
||||
toolbar.inflateMenu(R.menu.drawer_favorites);
|
||||
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
switch (id) {
|
||||
case R.id.action_default_favorites_slot:
|
||||
String[] items = new String[12];
|
||||
items[0] = getString(R.string.let_me_select);
|
||||
items[1] = getString(R.string.local_favorites);
|
||||
String[] favCat = Settings.getFavCat();
|
||||
System.arraycopy(favCat, 0, items, 2, 10);
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
.setTitle(R.string.default_favorites_collection)
|
||||
.setItems(items, (dialog, which) -> Settings.putDefaultFavSlot(which - 2)).show();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
toolbar.setOnMenuItemClickListener(item -> {
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.action_default_favorites_slot) {
|
||||
String[] items = new String[12];
|
||||
items[0] = getString(R.string.let_me_select);
|
||||
items[1] = getString(R.string.local_favorites);
|
||||
String[] favCat = Settings.getFavCat();
|
||||
System.arraycopy(favCat, 0, items, 2, 10);
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
.setTitle(R.string.default_favorites_collection)
|
||||
.setItems(items, (dialog, which) -> Settings.putDefaultFavSlot(which - 2)).show();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
EasyRecyclerView recyclerView = view.findViewById(R.id.recycler_view_drawer);
|
||||
@@ -452,7 +446,6 @@ public class FavoritesScene extends BaseScene implements
|
||||
|
||||
mDrawerAdapter = new FavDrawerAdapter(inflater);
|
||||
recyclerView.setAdapter(mDrawerAdapter);
|
||||
recyclerView.setOnItemClickListener(this);
|
||||
|
||||
return view;
|
||||
}
|
||||
@@ -497,9 +490,7 @@ public class FavoritesScene extends BaseScene implements
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Implemented(EasyRecyclerView.OnItemClickListener.class)
|
||||
public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
|
||||
public boolean onItemClick(View view, int position) {
|
||||
if (mDrawerLayout != null && mDrawerLayout.isDrawerOpen(Gravity.RIGHT)) {
|
||||
// Skip if in search mode
|
||||
if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) {
|
||||
@@ -1088,6 +1079,7 @@ public class FavoritesScene extends BaseScene implements
|
||||
holder.value.setText(Integer.toString(mFavCountArray[position - 2]));
|
||||
holder.itemView.setEnabled(true);
|
||||
}
|
||||
holder.itemView.setOnClickListener(v -> onItemClick(holder.itemView, position));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1200,7 +1192,7 @@ public class FavoritesScene extends BaseScene implements
|
||||
|
||||
@Override
|
||||
void onItemClick(View view, int position) {
|
||||
FavoritesScene.this.onItemClick(null, view, position, 0);
|
||||
FavoritesScene.this.onItemClick(view, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -62,7 +62,7 @@ import com.hippo.yorozuya.ViewUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
public class GalleryPreviewsScene extends ToolbarScene implements EasyRecyclerView.OnItemClickListener {
|
||||
public class GalleryPreviewsScene extends ToolbarScene {
|
||||
|
||||
public static final String KEY_GALLERY_INFO = "gallery_info";
|
||||
private final static String KEY_HAS_FIRST_REFRESH = "has_first_refresh";
|
||||
@@ -116,7 +116,7 @@ public class GalleryPreviewsScene extends ToolbarScene implements EasyRecyclerVi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
boolean hasFirstRefresh;
|
||||
@@ -149,7 +149,6 @@ public class GalleryPreviewsScene extends ToolbarScene implements EasyRecyclerVi
|
||||
layoutManager.setStrategy(AutoGridLayoutManager.STRATEGY_SUITABLE_SIZE);
|
||||
mRecyclerView.setLayoutManager(layoutManager);
|
||||
mRecyclerView.setClipToPadding(false);
|
||||
mRecyclerView.setOnItemClickListener(this);
|
||||
int padding = LayoutUtils.dp2pix(context, 4);
|
||||
MarginItemDecoration decoration = new MarginItemDecoration(padding, padding, padding, padding, padding);
|
||||
mRecyclerView.addItemDecoration(decoration);
|
||||
@@ -204,22 +203,21 @@ public class GalleryPreviewsScene extends ToolbarScene implements EasyRecyclerVi
|
||||
}
|
||||
|
||||
int id = item.getItemId();
|
||||
switch (id) {
|
||||
case R.id.action_go_to:
|
||||
if (mHelper == null) {
|
||||
return true;
|
||||
}
|
||||
int pages = mHelper.getPages();
|
||||
if (pages > 0 && mHelper.canGoTo()) {
|
||||
GoToDialogHelper helper = new GoToDialogHelper(pages, mHelper.getPageForTop());
|
||||
AlertDialog dialog = new MaterialAlertDialogBuilder(context).setTitle(R.string.go_to)
|
||||
.setView(R.layout.dialog_go_to)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.create();
|
||||
dialog.show();
|
||||
helper.setDialog(dialog);
|
||||
}
|
||||
if (id == R.id.action_go_to) {
|
||||
if (mHelper == null) {
|
||||
return true;
|
||||
}
|
||||
int pages = mHelper.getPages();
|
||||
if (pages > 0 && mHelper.canGoTo()) {
|
||||
GoToDialogHelper helper = new GoToDialogHelper(pages, mHelper.getPageForTop());
|
||||
AlertDialog dialog = new MaterialAlertDialogBuilder(context).setTitle(R.string.go_to)
|
||||
.setView(R.layout.dialog_go_to)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.create();
|
||||
dialog.show();
|
||||
helper.setDialog(dialog);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -229,8 +227,7 @@ public class GalleryPreviewsScene extends ToolbarScene implements EasyRecyclerVi
|
||||
onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
|
||||
public boolean onItemClick(int position) {
|
||||
Context context = getContext2();
|
||||
if (null != context && null != mHelper && null != mGalleryInfo) {
|
||||
GalleryPreview p = mHelper.getDataAtEx(position);
|
||||
@@ -300,7 +297,7 @@ public class GalleryPreviewsScene extends ToolbarScene implements EasyRecyclerVi
|
||||
}
|
||||
}
|
||||
|
||||
private class GalleryPreviewHolder extends RecyclerView.ViewHolder {
|
||||
private static class GalleryPreviewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public LoadImageView image;
|
||||
public TextView text;
|
||||
@@ -322,14 +319,15 @@ public class GalleryPreviewsScene extends ToolbarScene implements EasyRecyclerVi
|
||||
AssertUtils.assertNotNull(mInflater);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public GalleryPreviewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
public GalleryPreviewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new GalleryPreviewHolder(mInflater.inflate(R.layout.item_gallery_preview, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressLint("SetTextI18n")
|
||||
public void onBindViewHolder(GalleryPreviewHolder holder, int position) {
|
||||
public void onBindViewHolder(@NonNull GalleryPreviewHolder holder, int position) {
|
||||
if (null != mHelper) {
|
||||
GalleryPreview preview = mHelper.getDataAtEx(position);
|
||||
if (preview != null) {
|
||||
@@ -337,6 +335,7 @@ public class GalleryPreviewsScene extends ToolbarScene implements EasyRecyclerVi
|
||||
holder.text.setText(Integer.toString(preview.getPosition() + 1));
|
||||
}
|
||||
}
|
||||
holder.itemView.setOnClickListener(v -> onItemClick(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -151,21 +151,6 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener,
|
||||
decoration.setShowLastDivider(false);
|
||||
mListView.addItemDecoration(decoration);
|
||||
mListView.setLayoutManager(layoutManager);
|
||||
mListView.setOnItemClickListener((parent, view, position, id) -> {
|
||||
if (position < mSuggestionList.size()) {
|
||||
mSuggestionList.get(position).onClick();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
mListView.setOnItemLongClickListener((parent, view, position, id) -> {
|
||||
if (position < mSuggestionList.size()) {
|
||||
return mSuggestionList.get(position).onLongClick();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addListHeader() {
|
||||
@@ -571,6 +556,19 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener,
|
||||
holder.text2.setVisibility(View.VISIBLE);
|
||||
holder.text2.setText(text2);
|
||||
}
|
||||
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
if (position < mSuggestionList.size()) {
|
||||
mSuggestionList.get(position).onClick();
|
||||
}
|
||||
});
|
||||
holder.itemView.setOnLongClickListener(v -> {
|
||||
if (position < mSuggestionList.size()) {
|
||||
return mSuggestionList.get(position).onLongClick();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in new issue
Block a user