itemtouchhelper compile passed

This commit is contained in:
houzh 2024-02-17 11:21:15 +08:00
parent d27503e282
commit 5a74cc79ec
4 changed files with 211 additions and 141 deletions

View File

@ -1,115 +1,111 @@
#if 0
#include <widgetEx/recyclerview/itemtouchhelper.h>
#include <core/neverdestroyed.h>
namespace cdroid{
#if 0
class ItemTouchHelperpublic RecyclerView::ItemDecoration
implements RecyclerView.OnChildAttachStateChangeListener {
private:
OnItemTouchListener mOnItemTouchListener;
//= new OnItemTouchListener() {
bool onInterceptTouchEvent(RecyclerView& recyclerView,MotionEvent& event) {
mGestureDetector.onTouchEvent(event);
LOG_IF(_DEBUG,"intercept: x:%.f ,y:%.f",event.getX(),event.getY());
const int action = event.getActionMasked();
if (action == MotionEvent::ACTION_DOWN) {
mActivePointerId = event.getPointerId(0);
mInitialTouchX = event.getX();
mInitialTouchY = event.getY();
obtainVelocityTracker();
if (mSelected == null) {
final RecoverAnimation animation = findAnimation(event);
if (animation != null) {
mInitialTouchX -= animation.mX;
mInitialTouchY -= animation.mY;
endRecoverAnimation(animation.mViewHolder, true);
if (mPendingCleanup.remove(animation.mViewHolder.itemView)) {
mCallback->clearView(mRecyclerView, animation.mViewHolder);
}
select(animation.mViewHolder, animation.mActionState);
updateDxDy(event, mSelectedFlags, 0);
}
}
} else if (action == MotionEvent::ACTION_CANCEL || action == MotionEvent::ACTION_UP) {
mActivePointerId = ACTIVE_POINTER_ID_NONE;
select(nullptr, ACTION_STATE_IDLE);
} else if (mActivePointerId != ACTIVE_POINTER_ID_NONE) {
// in a non scroll orientation, if distance change is above threshold, we
// can select the item
final int index = event.findPointerIndex(mActivePointerId);
LOGD_IF(_DEBUG,"pointer index %d",index);
if (index >= 0) {
checkSelectForSwipe(action, event, index);
}
}
if (mVelocityTracker != nullptr) {
mVelocityTracker->addMovement(event);
}
return mSelected != nullptr;
}
void onTouchEvent(RecyclerView& recyclerView,MotionEvent& event) {
//mGestureDetector.onTouchEvent(event);
LOGD_IF(_DEBUG,"on touch: x:%d,y:%d",mInitialTouchX,mInitialTouchY);
if (mVelocityTracker != nullptr) {
mVelocityTracker->addMovement(event);
bool ItemTouchHelper::onInterceptTouchEvent(RecyclerView& recyclerView,MotionEvent& event) {
//mGestureDetector.onTouchEvent(event);
LOGD_IF(_DEBUG,"intercept: x:%.f ,y:%.f",event.getX(),event.getY());
const int action = event.getActionMasked();
if (action == MotionEvent::ACTION_DOWN) {
mActivePointerId = event.getPointerId(0);
mInitialTouchX = event.getX();
mInitialTouchY = event.getY();
obtainVelocityTracker();
if (mSelected == nullptr) {
RecoverAnimation* animation = findAnimation(event);
if (animation != nullptr) {
mInitialTouchX -= animation->mX;
mInitialTouchY -= animation->mY;
endRecoverAnimation(*animation->mViewHolder, true);
auto it=std::find(mPendingCleanup.begin(),mPendingCleanup.end(),animation->mViewHolder->itemView);
if (it!=mPendingCleanup.end()){//remove(animation->mViewHolder->itemView)) {
mPendingCleanup.erase(it);
mCallback->clearView(*mRecyclerView, *animation->mViewHolder);
}
select(animation->mViewHolder, animation->mActionState);
updateDxDy(event, mSelectedFlags, 0);
}
}
if (mActivePointerId == ACTIVE_POINTER_ID_NONE) {
return;
} else if (action == MotionEvent::ACTION_CANCEL || action == MotionEvent::ACTION_UP) {
mActivePointerId = ACTIVE_POINTER_ID_NONE;
select(nullptr, ACTION_STATE_IDLE);
} else if (mActivePointerId != ACTIVE_POINTER_ID_NONE) {
// in a non scroll orientation, if distance change is above threshold, we
// can select the item
const int index = event.findPointerIndex(mActivePointerId);
LOGD_IF(_DEBUG,"pointer index %d",index);
if (index >= 0) {
checkSelectForSwipe(action, event, index);
}
const int action = event.getActionMasked();
const int activePointerIndex = event.findPointerIndex(mActivePointerId);
}
if (mVelocityTracker != nullptr) {
mVelocityTracker->addMovement(event);
}
return mSelected != nullptr;
}
void ItemTouchHelper::onTouchEvent(RecyclerView& recyclerView,MotionEvent& event) {
//mGestureDetector.onTouchEvent(event);
LOGD_IF(_DEBUG,"on touch: x:%d,y:%d",mInitialTouchX,mInitialTouchY);
if (mVelocityTracker != nullptr) {
mVelocityTracker->addMovement(event);
}
if (mActivePointerId == ACTIVE_POINTER_ID_NONE) {
return;
}
const int action = event.getActionMasked();
const int activePointerIndex = event.findPointerIndex(mActivePointerId);
if (activePointerIndex >= 0) {
checkSelectForSwipe(action, event, activePointerIndex);
}
RecyclerView::ViewHolder* viewHolder = mSelected;
if (viewHolder == nullptr) {
return;
}
switch (action) {
case MotionEvent::ACTION_MOVE:
// Find the index of the active pointer and fetch its position
if (activePointerIndex >= 0) {
checkSelectForSwipe(action, event, activePointerIndex);
updateDxDy(event, mSelectedFlags, activePointerIndex);
moveIfNecessary(*viewHolder);
mRecyclerView->removeCallbacks(mScrollRunnable);
mScrollRunnable();//.run();
mRecyclerView->invalidate();
}
ViewHolder* viewHolder = mSelected;
if (viewHolder == nullptr) {
return;
break;
case MotionEvent::ACTION_CANCEL:
if (mVelocityTracker != nullptr) {
mVelocityTracker->clear();
}
switch (action) {
case MotionEvent::ACTION_MOVE: {
// Find the index of the active pointer and fetch its position
if (activePointerIndex >= 0) {
updateDxDy(event, mSelectedFlags, activePointerIndex);
moveIfNecessary(viewHolder);
mRecyclerView->removeCallbacks(mScrollRunnable);
mScrollRunnable.run();
mRecyclerView->invalidate();
}
break;
// fall through
case MotionEvent::ACTION_UP:
select(nullptr, ACTION_STATE_IDLE);
mActivePointerId = ACTIVE_POINTER_ID_NONE;
break;
case MotionEvent::ACTION_POINTER_UP: {
const int pointerIndex = event.getActionIndex();
const int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
const int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mActivePointerId = event.getPointerId(newPointerIndex);
updateDxDy(event, mSelectedFlags, pointerIndex);
}
case MotionEvent::ACTION_CANCEL:
if (mVelocityTracker != nullptr) {
mVelocityTracker->clear();
}
// fall through
case MotionEvent::ACTION_UP:
select(null, ACTION_STATE_IDLE);
mActivePointerId = ACTIVE_POINTER_ID_NONE;
break;
case MotionEvent::ACTION_POINTER_UP: {
const int pointerIndex = event.getActionIndex();
const int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mActivePointerId = event.getPointerId(newPointerIndex);
updateDxDy(event, mSelectedFlags, pointerIndex);
}
break;
}
}
}
}
void onRequestDisallowInterceptTouchEvent(bool disallowIntercept) {
if (!disallowIntercept) {
return;
}
select(null, ACTION_STATE_IDLE);
void ItemTouchHelper::onRequestDisallowInterceptTouchEvent(bool disallowIntercept) {
if (!disallowIntercept) {
return;
}
};
#endif
ItemTouchHelper::ItemTouchHelper(Callback& callback) {
select(nullptr, ACTION_STATE_IDLE);
}
ItemTouchHelper::ItemTouchHelper(Callback* callback) {
mCallback = callback;
mScrollRunnable = [this]() {
if (mSelected != nullptr && scrollIfNecessary()) {
@ -120,6 +116,9 @@ ItemTouchHelper::ItemTouchHelper(Callback& callback) {
mRecyclerView->postOnAnimation(mScrollRunnable);
}
};
mOnItemTouchListener.onInterceptTouchEvent = std::bind(&ItemTouchHelper::onInterceptTouchEvent,this,std::placeholders::_1,std::placeholders::_2);
mOnItemTouchListener.onTouchEvent = std::bind(&ItemTouchHelper::onTouchEvent,this,std::placeholders::_1,std::placeholders::_2);
mOnItemTouchListener.onRequestDisallowInterceptTouchEvent = std::bind(&ItemTouchHelper::onRequestDisallowInterceptTouchEvent,this,std::placeholders::_1);
}
bool ItemTouchHelper::hitTest(View& child, float x, float y, float left, float top) {
@ -150,14 +149,14 @@ void ItemTouchHelper::setupCallbacks() {
mSlop = vc.getScaledTouchSlop();
mRecyclerView->addItemDecoration(this);
mRecyclerView->addOnItemTouchListener(mOnItemTouchListener);
mRecyclerView->addOnChildAttachStateChangeListener(*this);
LOGD("TOBEOPENED");//mRecyclerView->addOnChildAttachStateChangeListener(*this);
startGestureDetection();
}
void ItemTouchHelper::destroyCallbacks() {
mRecyclerView->removeItemDecoration(this);
mRecyclerView->removeOnItemTouchListener(mOnItemTouchListener);
mRecyclerView->removeOnChildAttachStateChangeListener(*this);
LOGD("TOBEOPENED");//mRecyclerView->removeOnChildAttachStateChangeListener(*this);
// clean all attached
const int recoverAnimSize = mRecoverAnimations.size();
for (int i = recoverAnimSize - 1; i >= 0; i--) {
@ -207,7 +206,7 @@ void ItemTouchHelper::onDrawOver(Canvas& c, RecyclerView& parent, RecyclerView::
dx = mTmpPosition[0];
dy = mTmpPosition[1];
}
mCallback->onDrawOver(c, &parent, *mSelected, mRecoverAnimations, mActionState, dx, dy);
mCallback->onDrawOver(c, parent, mSelected, mRecoverAnimations, mActionState, dx, dy);
}
void ItemTouchHelper::onDraw(Canvas& c, RecyclerView& parent, RecyclerView::State& state) {
@ -347,7 +346,7 @@ void ItemTouchHelper::select(RecyclerView::ViewHolder* selected, int actionState
void ItemTouchHelper::postDispatchSwipe(RecoverAnimation* anim,int swipeDir) {
// wait until animations are complete.
const Runnable r=[this,anim,r,swipeDir]() {
const Runnable r([this,anim,r,swipeDir]() {
if (mRecyclerView != nullptr && mRecyclerView->isAttachedToWindow() && !anim->mOverridden
&& anim->mViewHolder->getAdapterPosition() != RecyclerView::NO_POSITION) {
RecyclerView::ItemAnimator* animator = mRecyclerView->getItemAnimator();
@ -361,7 +360,7 @@ void ItemTouchHelper::postDispatchSwipe(RecoverAnimation* anim,int swipeDir) {
mRecyclerView->post(r);
}
}
};
});
mRecyclerView->post(r);
}
@ -871,23 +870,11 @@ void ItemTouchHelper::removeChildDrawingOrderCallbackIfNecessary(View* view) {
}
}
/*************************************************************************************************/
/*public abstract static class ItemTouchHelper::Callback {
//public abstract static class ItemTouchHelper::Callback {
private static final Interpolator sDragScrollInterpolator = new Interpolator() {
public float getInterpolation(float t) {
return t * t * t * t * t;
}
};
private static final Interpolator sDragViewScrollCapInterpolator = new Interpolator() {
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t * t * t + 1.0f;
}
};*/
static ItemTouchUIUtil getDefaultUIUtil() {
return ItemTouchUIUtilImpl.INSTANCE;
static NeverDestroyed<ItemTouchUIUtilImpl>INSTANCE;
ItemTouchUIUtil& ItemTouchHelper::Callback::getDefaultUIUtil() {
return *INSTANCE;
}
int ItemTouchHelper::Callback::convertToRelativeDirection(int flags, int layoutDirection) {
@ -1043,7 +1030,7 @@ RecyclerView::ViewHolder* ItemTouchHelper::Callback::chooseDropTarget(RecyclerVi
void ItemTouchHelper::Callback::onSelectedChanged(RecyclerView::ViewHolder* viewHolder, int actionState) {
if (viewHolder != nullptr) {
ItemTouchUIUtilImpl.INSTANCE.onSelected(viewHolder->itemView);
getDefaultUIUtil().onSelected(*viewHolder->itemView);
}
}
@ -1106,20 +1093,19 @@ void ItemTouchHelper::Callback::onDraw(Canvas& c, RecyclerView& parent, Recycler
}
}
void ItemTouchHelper::Callback::onDrawOver(Canvas& c, RecyclerView& parent, RecyclerView::ViewHolder& selected,
void ItemTouchHelper::Callback::onDrawOver(Canvas& c, RecyclerView& parent, RecyclerView::ViewHolder* selected,
std::vector<ItemTouchHelper::RecoverAnimation*>& recoverAnimationList,
int actionState, float dX, float dY) {
const int recoverAnimSize = recoverAnimationList.size();
for (int i = 0; i < recoverAnimSize; i++) {
ItemTouchHelper::RecoverAnimation* anim = recoverAnimationList.at(i);
c.save();
onChildDrawOver(c, parent, anim->mViewHolder, anim->mX, anim->mY, anim->mActionState,
false);
onChildDrawOver(c, parent, *anim->mViewHolder, anim->mX, anim->mY, anim->mActionState, false);
c.restore();
}
if (&selected != nullptr) {
if (selected != nullptr) {
c.save();
onChildDrawOver(c, parent, selected, dX, dY, actionState, true);
onChildDrawOver(c, parent, *selected, dX, dY, actionState, true);
c.restore();
}
bool hasRunningAnimation = false;
@ -1137,19 +1123,17 @@ void ItemTouchHelper::Callback::onDrawOver(Canvas& c, RecyclerView& parent, Recy
}
void ItemTouchHelper::Callback::clearView(RecyclerView& recyclerView,RecyclerView::ViewHolder& viewHolder) {
ItemTouchUIUtilImpl.INSTANCE.clearView(viewHolder.itemView);
getDefaultUIUtil().clearView(*viewHolder.itemView);
}
void ItemTouchHelper::Callback::onChildDraw(Canvas& c,RecyclerView& recyclerView,RecyclerView::ViewHolder& viewHolder,
float dX, float dY, int actionState, bool isCurrentlyActive) {
ItemTouchUIUtilImpl.INSTANCE.onDraw(c, recyclerView, viewHolder.itemView, dX, dY,
actionState, isCurrentlyActive);
getDefaultUIUtil().onDraw(c, recyclerView, *viewHolder.itemView, dX, dY, actionState, isCurrentlyActive);
}
void ItemTouchHelper::Callback::onChildDrawOver(Canvas& c,RecyclerView& recyclerView, RecyclerView::ViewHolder& viewHolder,
float dX, float dY, int actionState, bool isCurrentlyActive) {
ItemTouchUIUtilImpl.INSTANCE.onDrawOver(c, recyclerView, viewHolder.itemView, dX, dY,
actionState, isCurrentlyActive);
getDefaultUIUtil().onDrawOver(c, recyclerView, *viewHolder.itemView, dX, dY, actionState, isCurrentlyActive);
}
long ItemTouchHelper::Callback::getAnimationDuration(RecyclerView& recyclerView, int animationType,
@ -1171,15 +1155,17 @@ int ItemTouchHelper::Callback::interpolateOutOfBoundsScroll(RecyclerView& recycl
const int direction = (int) signum(viewSizeOutOfBounds);
// might be negative if other direction
float outOfBoundsRatio = std::min(1.f, 1.f * absOutOfBounds / viewSize);
const int cappedScroll = (int) (direction * maxScroll
* sDragViewScrollCapInterpolator->getInterpolation(outOfBoundsRatio));
outOfBoundsRatio -=1.f;
outOfBoundsRatio = outOfBoundsRatio*outOfBoundsRatio*outOfBoundsRatio*outOfBoundsRatio*outOfBoundsRatio+1.f;
const int cappedScroll = (int) (direction * maxScroll*outOfBoundsRatio);//* sDragViewScrollCapInterpolator->getInterpolation(outOfBoundsRatio));
float timeRatio;
if (msSinceStartScroll > DRAG_SCROLL_ACCELERATION_LIMIT_TIME_MS) {
timeRatio = 1.f;
} else {
timeRatio = (float) msSinceStartScroll / DRAG_SCROLL_ACCELERATION_LIMIT_TIME_MS;
}
const int value = (int) (cappedScroll * sDragScrollInterpolator->getInterpolation(timeRatio));
timeRatio = timeRatio*timeRatio*timeRatio*timeRatio*timeRatio;
const int value = (int) (cappedScroll * timeRatio);/*sDragScrollInterpolator->getInterpolation(timeRatio)*/;
if (value == 0) {
return viewSizeOutOfBounds > 0 ? 1 : -1;
}
@ -1279,12 +1265,12 @@ ItemTouchHelper::RecoverAnimation::RecoverAnimation(RecyclerView::ViewHolder* vi
mTargetY = targetY;
mValueAnimator = ValueAnimator::ofFloat({0.f, 1.f});
ValueAnimator::AnimatorUpdateListener ls;
ls.onAnimationUpdate=[](ValueAnimator& animation) {
ls/*onAnimationUpdate*/ = [this](ValueAnimator& animation) {
setFraction(animation.getAnimatedFraction());
};
mValueAnimator->addUpdateListener(ls);
mValueAnimator->setTarget(viewHolder->itemView);
mValueAnimator->addListener(this);
mValueAnimator->addListener(*this);
setFraction(0.f);
}
@ -1338,5 +1324,4 @@ void ItemTouchHelper::RecoverAnimation::onAnimationRepeat(Animator& animation) {
}
}/*endof namespace*/
#endif

View File

@ -1,6 +1,7 @@
#ifndef __ITEMTOUCH_HELPER_H__
#define __ITEMTOUCH_HELPER_H__
#include <widgetEx/recyclerview/recyclerview.h>
#include <widgetEx/recyclerview/itemtouchuiutil.h>
namespace cdroid{
class ItemTouchHelper:public RecyclerView::ItemDecoration{
@ -96,8 +97,12 @@ private:
int checkVerticalSwipe(RecyclerView::ViewHolder& viewHolder, int flags);
void addChildDrawingOrderCallback();
void removeChildDrawingOrderCallbackIfNecessary(View* view);
/*binding functions for mOnItemTouchListener*/
bool onInterceptTouchEvent(RecyclerView& recyclerView,MotionEvent& event);
void onTouchEvent(RecyclerView& recyclerView,MotionEvent& event);
void onRequestDisallowInterceptTouchEvent(bool disallowIntercept);
public:
ItemTouchHelper(Callback& callback);
ItemTouchHelper(Callback* callback);
void attachToRecyclerView(RecyclerView* recyclerView);
void onDrawOver(Canvas& c, RecyclerView& parent, RecyclerView::State& state)override;
void onDraw(Canvas& c, RecyclerView& parent, RecyclerView::State& state)override;
@ -135,12 +140,10 @@ protected:
bool hasSwipeFlag(RecyclerView& recyclerView, RecyclerView::ViewHolder& viewHolder);
void onDraw(Canvas& c, RecyclerView& parent, RecyclerView::ViewHolder& selected,
std::vector<ItemTouchHelper::RecoverAnimation*>& recoverAnimationList,int actionState, float dX, float dY);
void onDrawOver(Canvas& c, RecyclerView* parent, RecyclerView::ViewHolder& selected,
void onDrawOver(Canvas& c, RecyclerView& parent, RecyclerView::ViewHolder* selected,
std::vector<ItemTouchHelper::RecoverAnimation*>& recoverAnimationList, int actionState, float dX, float dY);
public:
static ItemTouchUIUtil getDefaultUIUtil() {
return ItemTouchUIUtilImpl.INSTANCE;
}
static ItemTouchUIUtil& getDefaultUIUtil();
static int convertToRelativeDirection(int flags, int layoutDirection);
static int makeMovementFlags(int dragFlags, int swipeFlags);
static int makeFlag(int actionState, int directions);

View File

@ -0,0 +1,53 @@
#include <widgetEx/recyclerview/itemtouchuiutil.h>
namespace cdroid{
void ItemTouchUIUtilImpl::onDraw(Canvas& c, RecyclerView& recyclerView, View& view, float dX, float dY,
int actionState, bool isCurrentlyActive){
/*if (isCurrentlyActive) {
Object* originalElevation = view.getTag(R.id.item_touch_helper_previous_elevation);
if (originalElevation == null) {
originalElevation = ciew.getElevation();
float newElevation = 1.f + findMaxElevation(recyclerView, view);
view.setElevation(newElevation);
view.setTag(R.id.item_touch_helper_previous_elevation, originalElevation);
}
}*/
view.setTranslationX(dX);
view.setTranslationY(dY);
}
float ItemTouchUIUtilImpl::findMaxElevation(RecyclerView& recyclerView, View& itemView) {
const int childCount = recyclerView.getChildCount();
float max = 0;
for (int i = 0; i < childCount; i++) {
View* child = recyclerView.getChildAt(i);
if (child == &itemView) {
continue;
}
const float elevation = child->getElevation();
if (elevation > max) {
max = elevation;
}
}
return max;
}
void ItemTouchUIUtilImpl::onDrawOver(Canvas& c, RecyclerView& recyclerView, View& view, float dX, float dY,
int actionState, bool isCurrentlyActive){
}
void ItemTouchUIUtilImpl::clearView(View& view){
/*Object* tag = view.getTag(R.id.item_touch_helper_previous_elevation);
if (tag != nullptr && tag instanceof Float) {
view.setElevation((Float) tag);
}
view.setTag(R.id.item_touch_helper_previous_elevation, null);
*/
view.setTranslationX(0.f);
view.setTranslationY(0.f);
}
void ItemTouchUIUtilImpl::onSelected(View& view){
}
}/*endof namespace*/

View File

@ -0,0 +1,29 @@
#ifndef __ITEMTOUCHUI_UTIL_H__
#define __ITEMTOUCHUI_UTIL_H__
#include <widgetEx/recyclerview/recyclerview.h>
namespace cdroid{
class ItemTouchUIUtil {
public:
virtual void onDraw(Canvas& c, RecyclerView& recyclerView, View& view,
float dX, float dY, int actionState, bool isCurrentlyActive)=0;
virtual void onDrawOver(Canvas& c, RecyclerView& recyclerView, View& view,
float dX, float dY, int actionState, bool isCurrentlyActive)=0;
virtual void clearView(View& view)=0;
virtual void onSelected(View& view)=0;
};
class ItemTouchUIUtilImpl:public ItemTouchUIUtil {
private:
static float findMaxElevation(RecyclerView& recyclerView, View& itemView);
friend class ItemTouchHelper;
public:
void onDraw(Canvas& c, RecyclerView& recyclerView, View& view, float dX, float dY,
int actionState, bool isCurrentlyActive)override;
void onDrawOver(Canvas& c, RecyclerView& recyclerView, View& view, float dX, float dY,
int actionState, bool isCurrentlyActive)override;
void clearView(View& view);
void onSelected(View& view);
};
}
#endif/*__ITEMTOUCHUI_UTIL_H__*/