diff --git a/app/src/main/java/com/mxdl/customview/MainActivity.java b/app/src/main/java/com/mxdl/customview/MainActivity.java index e4c9ed0a59a8050cc6c0337fcb0a2fdfb9cc732e..065f0d41952c31ac6607782aa2c0dbad41772dab 100644 --- a/app/src/main/java/com/mxdl/customview/MainActivity.java +++ b/app/src/main/java/com/mxdl/customview/MainActivity.java @@ -47,12 +47,12 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe case R.id.btn_horizontal_scroll_view_ex: startActivity(new Intent(this, HorizontalScrollViewExActivity.class)); break; - case R.id.btn_sticky_layout: - startActivity(new Intent(this, StickyLayoutActivity.class)); - break; case R.id.btn_pinned_header: startActivity(new Intent(this, PinnedHeaderActivity.class)); break; + case R.id.btn_sticky_layout: + startActivity(new Intent(this, StickyLayoutActivity.class)); + break; case R.id.btn_capture_rect: startActivity(new Intent(this, CaptureRectViewActivity.class)); break; diff --git a/app/src/main/java/com/mxdl/customview/refer/HorizontalScrollViewEx.java b/app/src/main/java/com/mxdl/customview/refer/HorizontalScrollViewEx.java new file mode 100644 index 0000000000000000000000000000000000000000..94ef31e2ae99905cc24aa7b7690eaceafbb3bea0 --- /dev/null +++ b/app/src/main/java/com/mxdl/customview/refer/HorizontalScrollViewEx.java @@ -0,0 +1,208 @@ +package com.mxdl.customview.refer; + +/** + * Description:
+ * Author: mxdl
+ * Date: 2019/10/22
+ * Version: V1.0.0
+ * Update:
+ */ +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Scroller; + +public class HorizontalScrollViewEx extends ViewGroup { + private static final String TAG = "HorizontalScrollViewEx"; + + private int mChildrenSize; + private int mChildWidth; + private int mChildIndex; + + // 分别记录上次滑动的坐标 + private int mLastX = 0; + private int mLastY = 0; + // 分别记录上次滑动的坐标(onInterceptTouchEvent) + private int mLastXIntercept = 0; + private int mLastYIntercept = 0; + + private Scroller mScroller; + private VelocityTracker mVelocityTracker; + + public HorizontalScrollViewEx(Context context) { + super(context); + init(); + } + + public HorizontalScrollViewEx(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public HorizontalScrollViewEx(Context context, AttributeSet attrs, + int defStyle) { + super(context, attrs, defStyle); + init(); + } + + private void init() { + mScroller = new Scroller(getContext()); + mVelocityTracker = VelocityTracker.obtain(); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + boolean intercepted = false; + int x = (int) event.getX(); + int y = (int) event.getY(); + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: { + intercepted = false; + if (!mScroller.isFinished()) { + mScroller.abortAnimation(); + intercepted = true; + } + break; + } + case MotionEvent.ACTION_MOVE: { + int deltaX = x - mLastXIntercept; + int deltaY = y - mLastYIntercept; + if (Math.abs(deltaX) > Math.abs(deltaY)) { + intercepted = true; + } else { + intercepted = false; + } + break; + } + case MotionEvent.ACTION_UP: { + intercepted = false; + break; + } + default: + break; + } + + Log.d(TAG, "intercepted=" + intercepted); + mLastX = x; + mLastY = y; + mLastXIntercept = x; + mLastYIntercept = y; + + return intercepted; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + mVelocityTracker.addMovement(event); + int x = (int) event.getX(); + int y = (int) event.getY(); + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: { + if (!mScroller.isFinished()) { + mScroller.abortAnimation(); + } + break; + } + case MotionEvent.ACTION_MOVE: { + int deltaX = x - mLastX; + int deltaY = y - mLastY; + scrollBy(-deltaX, 0); + break; + } + case MotionEvent.ACTION_UP: { + int scrollX = getScrollX(); + int scrollToChildIndex = scrollX / mChildWidth; + mVelocityTracker.computeCurrentVelocity(1000); + float xVelocity = mVelocityTracker.getXVelocity(); + if (Math.abs(xVelocity) >= 50) { + mChildIndex = xVelocity > 0 ? mChildIndex - 1 : mChildIndex + 1; + } else { + mChildIndex = (scrollX + mChildWidth / 2) / mChildWidth; + } + mChildIndex = Math.max(0, Math.min(mChildIndex, mChildrenSize - 1)); + int dx = mChildIndex * mChildWidth - scrollX; + smoothScrollBy(dx, 0); + mVelocityTracker.clear(); + break; + } + default: + break; + } + + mLastX = x; + mLastY = y; + return true; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int measuredWidth = 0; + int measuredHeight = 0; + final int childCount = getChildCount(); + measureChildren(widthMeasureSpec, heightMeasureSpec); + + int widthSpaceSize = MeasureSpec.getSize(widthMeasureSpec); + int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); + int heightSpaceSize = MeasureSpec.getSize(heightMeasureSpec); + int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); + if (childCount == 0) { + setMeasuredDimension(0, 0); + } else if (heightSpecMode == MeasureSpec.AT_MOST) { + final View childView = getChildAt(0); + measuredHeight = childView.getMeasuredHeight(); + setMeasuredDimension(widthSpaceSize, childView.getMeasuredHeight()); + } else if (widthSpecMode == MeasureSpec.AT_MOST) { + final View childView = getChildAt(0); + measuredWidth = childView.getMeasuredWidth() * childCount; + setMeasuredDimension(measuredWidth, heightSpaceSize); + } else { + final View childView = getChildAt(0); + measuredWidth = childView.getMeasuredWidth() * childCount; + measuredHeight = childView.getMeasuredHeight(); + setMeasuredDimension(measuredWidth, measuredHeight); + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int childLeft = 0; + final int childCount = getChildCount(); + mChildrenSize = childCount; + + for (int i = 0; i < childCount; i++) { + final View childView = getChildAt(i); + if (childView.getVisibility() != View.GONE) { + final int childWidth = childView.getMeasuredWidth(); + mChildWidth = childWidth; + childView.layout(childLeft, 0, childLeft + childWidth, + childView.getMeasuredHeight()); + childLeft += childWidth; + } + } + } + + private void smoothScrollBy(int dx, int dy) { + mScroller.startScroll(getScrollX(), 0, dx, 0, 500); + invalidate(); + } + + @Override + public void computeScroll() { + if (mScroller.computeScrollOffset()) { + scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); + postInvalidate(); + } + } + + @Override + protected void onDetachedFromWindow() { + mVelocityTracker.recycle(); + super.onDetachedFromWindow(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mxdl/customview/refer/PinnedHeaderExpandableListView.java b/app/src/main/java/com/mxdl/customview/refer/PinnedHeaderExpandableListView.java new file mode 100644 index 0000000000000000000000000000000000000000..d38425e24e370a4d09d857938b292da2a9217800 --- /dev/null +++ b/app/src/main/java/com/mxdl/customview/refer/PinnedHeaderExpandableListView.java @@ -0,0 +1,256 @@ +package com.mxdl.customview.refer; + +/** + * Description:
+ * Author: mxdl
+ * Date: 2019/10/22
+ * Version: V1.0.0
+ * Update:
+ */ +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.ExpandableListView; +import android.widget.AbsListView.OnScrollListener; + +public class PinnedHeaderExpandableListView extends ExpandableListView implements OnScrollListener { + private static final String TAG = "PinnedListView"; + private static final boolean DEBUG = true; + + public interface OnHeaderUpdateListener { + /** + * 返回一个view对象即可 + * 注意:view必须要有LayoutParams + */ + public View getPinnedHeader(); + + public void updatePinnedHeader(View headerView, int firstVisibleGroupPos); + } + + private View mHeaderView; + private int mHeaderWidth; + private int mHeaderHeight; + + private View mTouchTarget; + + private OnScrollListener mScrollListener; + private OnHeaderUpdateListener mHeaderUpdateListener; + + private boolean mActionDownHappened = false; + protected boolean mIsHeaderGroupClickable = true; + + + public PinnedHeaderExpandableListView(Context context) { + super(context); + initView(); + } + + public PinnedHeaderExpandableListView(Context context, AttributeSet attrs) { + super(context, attrs); + initView(); + } + + public PinnedHeaderExpandableListView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initView(); + } + + private void initView() { + setFadingEdgeLength(0); + setOnScrollListener(this); + } + + @Override + public void setOnScrollListener(OnScrollListener l) { + if (l != this) { + mScrollListener = l; + } else { + mScrollListener = null; + } + super.setOnScrollListener(this); + } + + /** + * 给group添加点击事件监听 + * @param onGroupClickListener 监听 + * @param isHeaderGroupClickable 表示header是否可点击
+ * note : 当不想group可点击的时候,需要在OnGroupClickListener#onGroupClick中返回true, + * 并将isHeaderGroupClickable设为false即可 + */ + public void setOnGroupClickListener(OnGroupClickListener onGroupClickListener, boolean isHeaderGroupClickable) { + mIsHeaderGroupClickable = isHeaderGroupClickable; + super.setOnGroupClickListener(onGroupClickListener); + } + + public void setOnHeaderUpdateListener(OnHeaderUpdateListener listener) { + mHeaderUpdateListener = listener; + if (listener == null) { + mHeaderView = null; + mHeaderWidth = mHeaderHeight = 0; + return; + } + mHeaderView = listener.getPinnedHeader(); + int firstVisiblePos = getFirstVisiblePosition(); + int firstVisibleGroupPos = getPackedPositionGroup(getExpandableListPosition(firstVisiblePos)); + listener.updatePinnedHeader(mHeaderView, firstVisibleGroupPos); + requestLayout(); + postInvalidate(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (mHeaderView == null) { + return; + } + measureChild(mHeaderView, widthMeasureSpec, heightMeasureSpec); + mHeaderWidth = mHeaderView.getMeasuredWidth(); + mHeaderHeight = mHeaderView.getMeasuredHeight(); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + if (mHeaderView == null) { + return; + } + int delta = mHeaderView.getTop(); + mHeaderView.layout(0, delta, mHeaderWidth, mHeaderHeight + delta); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (mHeaderView != null) { + drawChild(canvas, mHeaderView, getDrawingTime()); + } + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + int x = (int) ev.getX(); + int y = (int) ev.getY(); + int pos = pointToPosition(x, y); + if (mHeaderView != null && y >= mHeaderView.getTop() && y <= mHeaderView.getBottom()) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + mTouchTarget = getTouchTarget(mHeaderView, x, y); + mActionDownHappened = true; + } else if (ev.getAction() == MotionEvent.ACTION_UP) { + View touchTarget = getTouchTarget(mHeaderView, x, y); + if (touchTarget == mTouchTarget && mTouchTarget.isClickable()) { + mTouchTarget.performClick(); + invalidate(new Rect(0, 0, mHeaderWidth, mHeaderHeight)); + } else if (mIsHeaderGroupClickable){ + int groupPosition = getPackedPositionGroup(getExpandableListPosition(pos)); + if (groupPosition != INVALID_POSITION && mActionDownHappened) { + if (isGroupExpanded(groupPosition)) { + collapseGroup(groupPosition); + } else { + expandGroup(groupPosition); + } + } + } + mActionDownHappened = false; + } + return true; + } + + return super.dispatchTouchEvent(ev); + } + + private View getTouchTarget(View view, int x, int y) { + if (!(view instanceof ViewGroup)) { + return view; + } + + ViewGroup parent = (ViewGroup)view; + int childrenCount = parent.getChildCount(); + final boolean customOrder = isChildrenDrawingOrderEnabled(); + View target = null; + for (int i = childrenCount - 1; i >= 0; i--) { + final int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i; + final View child = parent.getChildAt(childIndex); + if (isTouchPointInView(child, x, y)) { + target = child; + break; + } + } + if (target == null) { + target = parent; + } + + return target; + } + + private boolean isTouchPointInView(View view, int x, int y) { + if (view.isClickable() && y >= view.getTop() && y <= view.getBottom() + && x >= view.getLeft() && x <= view.getRight()) { + return true; + } + return false; + } + + public void requestRefreshHeader() { + refreshHeader(); + invalidate(new Rect(0, 0, mHeaderWidth, mHeaderHeight)); + } + + protected void refreshHeader() { + if (mHeaderView == null) { + return; + } + int firstVisiblePos = getFirstVisiblePosition(); + int pos = firstVisiblePos + 1; + int firstVisibleGroupPos = getPackedPositionGroup(getExpandableListPosition(firstVisiblePos)); + int group = getPackedPositionGroup(getExpandableListPosition(pos)); + if (DEBUG) { + Log.d(TAG, "refreshHeader firstVisibleGroupPos=" + firstVisibleGroupPos); + } + + if (group == firstVisibleGroupPos + 1) { + View view = getChildAt(1); + if (view == null) { + Log.w(TAG, "Warning : refreshHeader getChildAt(1)=null"); + return; + } + if (view.getTop() <= mHeaderHeight) { + int delta = mHeaderHeight - view.getTop(); + mHeaderView.layout(0, -delta, mHeaderWidth, mHeaderHeight - delta); + } else { + //TODO : note it, when cause bug, remove it + mHeaderView.layout(0, 0, mHeaderWidth, mHeaderHeight); + } + } else { + mHeaderView.layout(0, 0, mHeaderWidth, mHeaderHeight); + } + + if (mHeaderUpdateListener != null) { + mHeaderUpdateListener.updatePinnedHeader(mHeaderView, firstVisibleGroupPos); + } + } + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + if (mScrollListener != null) { + mScrollListener.onScrollStateChanged(view, scrollState); + } + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, + int visibleItemCount, int totalItemCount) { + if (totalItemCount > 0) { + refreshHeader(); + } + if (mScrollListener != null) { + mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/mxdl/customview/refer/StickyLayout.java b/app/src/main/java/com/mxdl/customview/refer/StickyLayout.java new file mode 100644 index 0000000000000000000000000000000000000000..d68cc777d767169b13c5ead2daf1a878ddd81f33 --- /dev/null +++ b/app/src/main/java/com/mxdl/customview/refer/StickyLayout.java @@ -0,0 +1,286 @@ +package com.mxdl.customview.refer; + +/** + * Description:
+ * Author: mxdl
+ * Date: 2019/10/22
+ * Version: V1.0.0
+ * Update:
+ */ +import java.util.NoSuchElementException; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.widget.LinearLayout; + + +public class StickyLayout extends LinearLayout { + private static final String TAG = "StickyLayout"; + private static final boolean DEBUG = true; + + public interface OnGiveUpTouchEventListener { + public boolean giveUpTouchEvent(MotionEvent event); + } + + private View mHeader; + private View mContent; + private OnGiveUpTouchEventListener mGiveUpTouchEventListener; + + // header的高度 单位:px + private int mOriginalHeaderHeight; + private int mHeaderHeight; + + private int mStatus = STATUS_EXPANDED; + public static final int STATUS_EXPANDED = 1; + public static final int STATUS_COLLAPSED = 2; + + private int mTouchSlop; + + // 分别记录上次滑动的坐标 + private int mLastX = 0; + private int mLastY = 0; + + // 分别记录上次滑动的坐标(onInterceptTouchEvent) + private int mLastXIntercept = 0; + private int mLastYIntercept = 0; + + // 用来控制滑动角度,仅当角度a满足如下条件才进行滑动:tan a = deltaX / deltaY > 2 + private static final int TAN = 2; + + private boolean mIsSticky = true; + private boolean mInitDataSucceed = false; + private boolean mDisallowInterceptTouchEventOnHeader = true; + + public StickyLayout(Context context) { + super(context); + } + + public StickyLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public StickyLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + super.onWindowFocusChanged(hasWindowFocus); + if (hasWindowFocus && (mHeader == null || mContent == null)) { + initData(); + } + } + + private void initData() { + int headerId= getResources().getIdentifier("sticky_header", "id", getContext().getPackageName()); + int contentId = getResources().getIdentifier("sticky_content", "id", getContext().getPackageName()); + if (headerId != 0 && contentId != 0) { + mHeader = findViewById(headerId); + mContent = findViewById(contentId); + mOriginalHeaderHeight = mHeader.getMeasuredHeight(); + mHeaderHeight = mOriginalHeaderHeight; + mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); + if (mHeaderHeight > 0) { + mInitDataSucceed = true; + } + if (DEBUG) { + Log.d(TAG, "mTouchSlop = " + mTouchSlop + "mHeaderHeight = " + mHeaderHeight); + } + } else { + throw new NoSuchElementException("Did your view with id \"sticky_header\" or \"sticky_content\" exists?"); + } + } + + public void setOnGiveUpTouchEventListener(OnGiveUpTouchEventListener l) { + mGiveUpTouchEventListener = l; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + int intercepted = 0; + int x = (int) event.getX(); + int y = (int) event.getY(); + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: { + mLastXIntercept = x; + mLastYIntercept = y; + mLastX = x; + mLastY = y; + intercepted = 0; + break; + } + case MotionEvent.ACTION_MOVE: { + int deltaX = x - mLastXIntercept; + int deltaY = y - mLastYIntercept; + if (mDisallowInterceptTouchEventOnHeader && y <= getHeaderHeight()) { + intercepted = 0; + } else if (Math.abs(deltaY) <= Math.abs(deltaX)) { + intercepted = 0; + } else if (mStatus == STATUS_EXPANDED && deltaY <= -mTouchSlop) { + intercepted = 1; + } else if (mGiveUpTouchEventListener != null) { + if (mGiveUpTouchEventListener.giveUpTouchEvent(event) && deltaY >= mTouchSlop) { + intercepted = 1; + } + } + break; + } + case MotionEvent.ACTION_UP: { + intercepted = 0; + mLastXIntercept = mLastYIntercept = 0; + break; + } + default: + break; + } + + if (DEBUG) { + Log.d(TAG, "intercepted=" + intercepted); + } + return intercepted != 0 && mIsSticky; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!mIsSticky) { + return true; + } + int x = (int) event.getX(); + int y = (int) event.getY(); + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: { + break; + } + case MotionEvent.ACTION_MOVE: { + int deltaX = x - mLastX; + int deltaY = y - mLastY; + if (DEBUG) { + Log.d(TAG, "mHeaderHeight=" + mHeaderHeight + " deltaY=" + deltaY + " mlastY=" + mLastY); + } + mHeaderHeight += deltaY; + setHeaderHeight(mHeaderHeight); + break; + } + case MotionEvent.ACTION_UP: { + // 这里做了下判断,当松开手的时候,会自动向两边滑动,具体向哪边滑,要看当前所处的位置 + int destHeight = 0; + if (mHeaderHeight <= mOriginalHeaderHeight * 0.5) { + destHeight = 0; + mStatus = STATUS_COLLAPSED; + } else { + destHeight = mOriginalHeaderHeight; + mStatus = STATUS_EXPANDED; + } + // 慢慢滑向终点 + this.smoothSetHeaderHeight(mHeaderHeight, destHeight, 500); + break; + } + default: + break; + } + mLastX = x; + mLastY = y; + return true; + } + + public void smoothSetHeaderHeight(final int from, final int to, long duration) { + smoothSetHeaderHeight(from, to, duration, false); + } + + public void smoothSetHeaderHeight(final int from, final int to, long duration, final boolean modifyOriginalHeaderHeight) { + final int frameCount = (int) (duration / 1000f * 30) + 1; + final float partation = (to - from) / (float) frameCount; + new Thread("Thread#smoothSetHeaderHeight") { + + @Override + public void run() { + for (int i = 0; i < frameCount; i++) { + final int height; + if (i == frameCount - 1) { + height = to; + } else { + height = (int) (from + partation * i); + } + post(new Runnable() { + public void run() { + setHeaderHeight(height); + } + }); + try { + sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + if (modifyOriginalHeaderHeight) { + setOriginalHeaderHeight(to); + } + }; + + }.start(); + } + + public void setOriginalHeaderHeight(int originalHeaderHeight) { + mOriginalHeaderHeight = originalHeaderHeight; + } + + public void setHeaderHeight(int height, boolean modifyOriginalHeaderHeight) { + if (modifyOriginalHeaderHeight) { + setOriginalHeaderHeight(height); + } + setHeaderHeight(height); + } + + public void setHeaderHeight(int height) { + if (!mInitDataSucceed) { + initData(); + } + + if (DEBUG) { + Log.d(TAG, "setHeaderHeight height=" + height); + } + if (height <= 0) { + height = 0; + } else if (height > mOriginalHeaderHeight) { + height = mOriginalHeaderHeight; + } + + if (height == 0) { + mStatus = STATUS_COLLAPSED; + } else { + mStatus = STATUS_EXPANDED; + } + + if (mHeader != null && mHeader.getLayoutParams() != null) { + mHeader.getLayoutParams().height = height; + mHeader.requestLayout(); + mHeaderHeight = height; + } else { + if (DEBUG) { + Log.e(TAG, "null LayoutParams when setHeaderHeight"); + } + } + } + + public int getHeaderHeight() { + return mHeaderHeight; + } + + public void setSticky(boolean isSticky) { + mIsSticky = isSticky; + } + + public void requestDisallowInterceptTouchEventOnHeader(boolean disallowIntercept) { + mDisallowInterceptTouchEventOnHeader = disallowIntercept; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/mxdl/customview/view/HorizontalScrollViewEx.java b/app/src/main/java/com/mxdl/customview/view/HorizontalScrollViewEx.java index 0bf58e61d9ba4b9c017870b34200de7ce7d0c710..620f9f5c433a980fd3ad09205a839576dde93cd8 100644 --- a/app/src/main/java/com/mxdl/customview/view/HorizontalScrollViewEx.java +++ b/app/src/main/java/com/mxdl/customview/view/HorizontalScrollViewEx.java @@ -35,9 +35,10 @@ import android.widget.Scroller; * 4.对速度检测器没有添加事件,知道获取的速度一直是0 * 5.computeScroll()方法里面没有postinvlate * 6.对于正在滑动中再次进行滑动没有做优化 + * 7.Math.abs(dx) >= Math.abs(dy) 加上等于会导致0,0的情况也被拦截,上滑,下滑会翻页 */ public class HorizontalScrollViewEx extends ViewGroup { - + public static final String TAG = HorizontalScrollViewEx.class.getSimpleName(); private Scroller mScroller; private VelocityTracker mVelocityTracker; private int mLastX; @@ -127,11 +128,12 @@ public class HorizontalScrollViewEx extends ViewGroup { case MotionEvent.ACTION_MOVE: int dx = x - mLastInterceptX; int dy = y - mLastInterceptY; - if (Math.abs(dx) >= Math.abs(dy)) { + if (Math.abs(dx) > Math.abs(dy)) { intercept = true; } else { intercept = false; } + Log.v(TAG,"dx:"+dx+";dy:"+dy+"intercept:"+intercept); break; case MotionEvent.ACTION_UP: intercept = false;