package com.sxjs.common.base.baseadapter.listener;
import android.os.Build;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import com.sxjs.common.base.baseadapter.BaseQuickAdapter;
import com.sxjs.common.base.baseadapter.BaseViewHolder;
import java.util.Set;
import static com.sxjs.common.base.baseadapter.BaseQuickAdapter.EMPTY_VIEW;
import static com.sxjs.common.base.baseadapter.BaseQuickAdapter.FOOTER_VIEW;
import static com.sxjs.common.base.baseadapter.BaseQuickAdapter.HEADER_VIEW;
import static com.sxjs.common.base.baseadapter.BaseQuickAdapter.LOADING_VIEW;
/**
* Created by AllenCoder on 2016/8/03.
* <p>
* This can be useful for applications that wish to implement various forms of click and longclick and childView click
* manipulation of item views within the RecyclerView. SimpleClickListener may intercept
* a touch interaction already in progress even if the SimpleClickListener is already handling that
* gesture stream itself for the purposes of scrolling.
*
* @see RecyclerView.OnItemTouchListener
*/
public abstract class SimpleClickListener implements RecyclerView.OnItemTouchListener {
private GestureDetectorCompat mGestureDetector;
private RecyclerView recyclerView;
protected BaseQuickAdapter baseQuickAdapter;
private boolean mIsPrepressed = false;
private boolean mIsShowPress = false;
private View mPressedView = null;
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
if (recyclerView == null) {
this.recyclerView = rv;
this.baseQuickAdapter = (BaseQuickAdapter) recyclerView.getAdapter();
mGestureDetector = new GestureDetectorCompat(recyclerView.getContext(), new ItemTouchHelperGestureListener(recyclerView));
}else if (recyclerView!=rv){
this.recyclerView = rv;
this.baseQuickAdapter = (BaseQuickAdapter) recyclerView.getAdapter();
mGestureDetector = new GestureDetectorCompat(recyclerView.getContext(), new ItemTouchHelperGestureListener(recyclerView));
}
if (!mGestureDetector.onTouchEvent(e) && e.getActionMasked() == MotionEvent.ACTION_UP && mIsShowPress) {
if (mPressedView!=null){
BaseViewHolder vh = (BaseViewHolder) recyclerView.getChildViewHolder(mPressedView);
if (vh == null ||!isHeaderOrFooterView(vh.getItemViewType())) {
mPressedView.setPressed(false);
}
}
mIsShowPress = false;
mIsPrepressed = false;
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
mGestureDetector.onTouchEvent(e);
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {
private RecyclerView recyclerView;
@Override
public boolean onDown(MotionEvent e) {
mIsPrepressed = true;
mPressedView = recyclerView.findChildViewUnder(e.getX(), e.getY());
super.onDown(e);
return false;
}
@Override
public void onShowPress(MotionEvent e) {
if (mIsPrepressed && mPressedView != null) {
// mPressedView.setPressed(true);
mIsShowPress = true;
}
super.onShowPress(e);
}
ItemTouchHelperGestureListener(RecyclerView recyclerView) {
this.recyclerView = recyclerView;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
if (mIsPrepressed && mPressedView != null) {
if (recyclerView.getScrollState()!=RecyclerView.SCROLL_STATE_IDLE){
return false;
}
final View pressedView = mPressedView;
BaseViewHolder vh = (BaseViewHolder) recyclerView.getChildViewHolder(pressedView);
if (isHeaderOrFooterPosition(vh.getLayoutPosition())) {
return false;
}
Set<Integer> childClickViewIds = vh.getChildClickViewIds();
Set<Integer> nestViewIds = vh.getNestViews();
if (childClickViewIds != null && childClickViewIds.size() > 0) {
for (Integer childClickViewId : childClickViewIds) {
View childView = pressedView.findViewById(childClickViewId);
if (childView != null) {
if (inRangeOfView(childView, e) && childView.isEnabled()) {
if (nestViewIds!=null&&nestViewIds.contains(childClickViewId)){
return false;
}
setPressViewHotSpot(e, childView);
childView.setPressed(true);
onItemChildClick(baseQuickAdapter, childView, vh.getLayoutPosition() - baseQuickAdapter.getHeaderLayoutCount());
resetPressedView(childView);
return true;
} else {
childView.setPressed(false);
}
}
}
setPressViewHotSpot(e,pressedView);
mPressedView.setPressed(true);
for (Integer childClickViewId : childClickViewIds) {
View childView = pressedView.findViewById(childClickViewId);
if (childView!=null){
childView.setPressed(false);
}
}
onItemClick(baseQuickAdapter, pressedView, vh.getLayoutPosition() - baseQuickAdapter.getHeaderLayoutCount());
} else {
setPressViewHotSpot(e,pressedView);
mPressedView.setPressed(true);
if (childClickViewIds != null && childClickViewIds.size() > 0) {
for (Integer childClickViewId : childClickViewIds) {
View childView = pressedView.findViewById(childClickViewId);
if (childView!=null){
childView.setPressed(false);
}
}
}
onItemClick(baseQuickAdapter, pressedView, vh.getLayoutPosition() - baseQuickAdapter.getHeaderLayoutCount());
}
resetPressedView(pressedView);
}
return true;
}
private void resetPressedView(final View pressedView) {
if (pressedView!=null){
pressedView.postDelayed(new Runnable() {
@Override
public void run() {
if (pressedView!=null){
pressedView.setPressed(false);
}
}
},50);
}
mIsPrepressed = false;
mPressedView = null;
}
@Override
public void onLongPress(MotionEvent e) {
boolean isChildLongClick =false;
if (recyclerView.getScrollState()!=RecyclerView.SCROLL_STATE_IDLE){
return ;
}
if (mIsPrepressed && mPressedView != null) {
mPressedView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
BaseViewHolder vh = (BaseViewHolder) recyclerView.getChildViewHolder(mPressedView);
if (!isHeaderOrFooterPosition(vh.getLayoutPosition())) {
Set<Integer> longClickViewIds = vh.getItemChildLongClickViewIds();
Set<Integer> nestViewIds = vh.getNestViews();
if (longClickViewIds != null && longClickViewIds.size() > 0) {
for (Integer longClickViewId : longClickViewIds) {
View childView = mPressedView.findViewById(longClickViewId);
if (inRangeOfView(childView, e) && childView.isEnabled()) {
if (nestViewIds!=null&&nestViewIds.contains(longClickViewId)){
isChildLongClick=true;
break;
}
setPressViewHotSpot(e, childView);
onItemChildLongClick(baseQuickAdapter, childView, vh.getLayoutPosition() - baseQuickAdapter.getHeaderLayoutCount());
childView.setPressed(true);
mIsShowPress = true;
isChildLongClick = true;
break;
}
}
}
if (!isChildLongClick){
onItemLongClick(baseQuickAdapter, mPressedView, vh.getLayoutPosition() - baseQuickAdapter.getHeaderLayoutCount());
setPressViewHotSpot(e,mPressedView);
mPressedView.setPressed(true);
if (longClickViewIds != null) {
for (Integer longClickViewId : longClickViewIds) {
View childView = mPressedView.findViewById(longClickViewId);
childView.setPressed(false);
}
}
mIsShowPress = true;
}
}
}
}
}
private void setPressViewHotSpot(final MotionEvent e,final View mPressedView) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
/**
* when click Outside the region ,mPressedView is null
*/
if (mPressedView !=null && mPressedView.getBackground() != null) {
mPressedView.getBackground().setHotspot(e.getRawX(), e.getY()-mPressedView.getY());
}
}
}
/**
* Callback method to be invoked when an item in this AdapterView has
* been clicked.
*
* @param view The view within the AdapterView that was clicked (this
* will be a view provided by the adapter)
* @param position The position of the view in the adapter.
*/
public abstract void onItemClick(BaseQuickAdapter adapter, View view, int position);
/**
* callback method to be invoked when an item in this view has been
* click and held
*
* @param view The view whihin the AbsListView that was clicked
* @param position The position of the view int the adapter
* @return true if the callback consumed the long click ,false otherwise
*/
public abstract void onItemLongClick(BaseQuickAdapter adapter, View view, int position);
public abstract void onItemChildClick(BaseQuickAdapter adapter, View view, int position);
public abstract void onItemChildLongClick(BaseQuickAdapter adapter, View view, int position);
public boolean inRangeOfView(View view, MotionEvent ev) {
int[] location = new int[2];
if (view==null||!view.isShown()){
return false;
}
view.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
if (ev.getRawX() < x
|| ev.getRawX() > (x + view.getWidth())
|| ev.getRawY() < y
|| ev.getRawY() > (y + view.getHeight())) {
return false;
}
return true;
}
private boolean isHeaderOrFooterPosition(int position) {
/**
* have a headview and EMPTY_VIEW FOOTER_VIEW LOADING_VIEW
*/
if (baseQuickAdapter==null){
if (recyclerView!=null){
baseQuickAdapter= (BaseQuickAdapter) recyclerView.getAdapter();
}else {
return false;
}
}
int type = baseQuickAdapter.getItemViewType(position);
return (type == EMPTY_VIEW || type == HEADER_VIEW || type == FOOTER_VIEW || type == LOADING_VIEW);
}
private boolean isHeaderOrFooterView(int type) {
return (type == EMPTY_VIEW || type == HEADER_VIEW || type == FOOTER_VIEW || type == LOADING_VIEW);
}
}