社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
public class HorizontalView extends ViewGroup {
private int lastInterceptX;
private int lastInterceptY;
private int lastX;
private int lastY;
private int childWidth;
private int curIndex;
private Scroller scroller;
//测试滑动速度
private VelocityTracker tracker;
public HorizontalView(Context context) {
this(context, null);
}
public HorizontalView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HorizontalView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
scroller = new Scroller(getContext());
tracker = VelocityTracker.obtain();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
measureChildren(widthMeasureSpec, heightMeasureSpec);
int widthSpec = MeasureSpec.getMode(widthMeasureSpec);
int heightSpec = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
//若无子元素,宽高设置为0
if (getChildCount() == 0) {
setMeasuredDimension(0, 0);
}
View childOne = getChildAt(0);
int childWidth = childOne.getMeasuredWidth();
int childHeight = childOne.getMeasuredHeight();
if (widthSpec == MeasureSpec.AT_MOST) {
//若宽为 at_most , 定义宽为所有子元素的宽
widthSize = childWidth * getChildCount();
}
if (heightSpec == MeasureSpec.AT_MOST) {
//若高为 at_most 定义高为第一个子元素的高
heightSize = childHeight;
}
setMeasuredDimension(widthSize, heightSize);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childCount = getChildCount();
int left = 0;
View child;
for (int i = 0; i < childCount; i++) {
child = getChildAt(i);
if (child.getVisibility() != View.GONE) {
int width = child.getMeasuredWidth();
childWidth = width;
child.layout(left, 0, left + width, child.getMeasuredHeight());
left += width;
}
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercept = false;
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
//滑动时再次点击停止
intercept = false;
if (!scroller.isFinished()) {
scroller.abortAnimation();
}
break;
case MotionEvent.ACTION_MOVE:
int deltaX = x - lastInterceptX;
int deltaY = y - lastInterceptY;
intercept = Math.abs(deltaX) - Math.abs(deltaY) > 0;
break;
case MotionEvent.ACTION_UP:
break;
}
lastInterceptX = x;
lastInterceptY = y;
lastX = x;
lastY = y;
return intercept;
}
//若 viewGroup 拦截则执行
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!scroller.isFinished()) {
scroller.abortAnimation();
}
break;
case MotionEvent.ACTION_MOVE:
int deltaX = x - lastX;
scrollBy(-deltaX, 0);
break;
case MotionEvent.ACTION_UP:
int dis = getScrollX() - curIndex * childWidth;
if (Math.abs(dis) > childWidth / 2) {
if (dis > 0) {
curIndex++;
} else {
curIndex--;
}
} else {
tracker.computeCurrentVelocity(1000);
float xV = tracker.getXVelocity();
if (xV > 50) {
if (xV > 0) {
curIndex--;
} else {
curIndex++;
}
}
}
//修正curIndex
curIndex = curIndex < 0 ? 0 :
curIndex > getChildCount() - 1 ? getChildCount() - 1 : curIndex;
//处理 Action_move 滑动结果,左滑或右滑
smoothScrollTo(curIndex * childWidth, 0);
//重置计算器
tracker.clear();
break;
}
lastX = x;
lastY = y;
return super.onTouchEvent(event);
}
@Override
public void computeScroll() {
super.computeScroll();
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
postInvalidate();
}
}
/**
* 弹性滑动
*/
public void smoothScrollTo(int destX, int destY) {
scroller.startScroll(getScrollX(), getScrollY(),
destX - getScrollX(), destY - getScrollY(), 1000);
invalidate();
}
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!