package com.imooc.dialogdemo.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;
public class HorizontalView extends ViewGroup {
private int lastInterceptX;
private int lastInterceptY;
private int lastX;
private int lastY;
private int currentIndex = 0;// 当前子元素
int childWidth = 0;
private Scroller scroller;
private VelocityTracker velocityTracker;
public HorizontalView(Context context) {
super(context);
initView();
}
public HorizontalView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public HorizontalView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
scroller = new Scroller(getContext());
velocityTracker = VelocityTracker.obtain();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int withMode = MeasureSpec.getMode(widthMeasureSpec);
int withSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
measureChildren(widthMeasureSpec,heightMeasureSpec);
// 如果没有子 view 则宽和高都设置为 0
if (getChildCount()==0){
setMeasuredDimension(0,0);
}
// 处理 wrap_content 情况
// 宽和高都是 AT_MOST: 宽度为所有子view 的宽度之和,高度为第一个子View 的高度
else if (withMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST){
View childView = getChildAt(0);
setMeasuredDimension(childView.getMeasuredWidth()*getChildCount(),childView.getMeasuredHeight());
}
//宽是 AT_MOST: 宽度为所有子view 的宽度之和
else if (withMode == MeasureSpec.AT_MOST){
View childView = getChildAt(0);
setMeasuredDimension(childView.getMeasuredWidth()*getChildCount(),heightSize);
}
//高是 AT_MOST: 宽度为第一个子View 的高度
else if (heightMode == MeasureSpec.AT_MOST){
View childView = getChildAt(0);
setMeasuredDimension(withSize,childView.getMeasuredHeight());
}
}
@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() != GONE){
int width = child.getMeasuredWidth();
childWidth = width;
child.layout(width,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;
// 判断是不是水平滑动
if (Math.abs(deltaX) - Math.abs(deltaY) > 0){
intercept = true;
}else{
intercept = false;
}
break;
case MotionEvent.ACTION_UP:
intercept = false;
break;
}
lastX = x;
lastY = y;
lastInterceptX = x;
lastInterceptY = y;
return intercept;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean intercept = false;
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (ev.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 distance = getScrollX() - currentIndex*childWidth;
if (Math.abs(distance)>childWidth/2){
if (distance>0){
currentIndex++;
}else{
currentIndex--;
}
}else{
velocityTracker.computeCurrentVelocity(1000);
float xV = velocityTracker.getXVelocity();
if (Math.abs(xV)>50){
// 切换到上一个页面
if (xV>0){
currentIndex --;
}else{
currentIndex ++;
}
}
}
currentIndex = currentIndex < 0 ? 0: currentIndex > getChildCount() -1?
getChildCount()-1:currentIndex;
smoothScrollTo(currentIndex * childWidth, 0);
velocityTracker.clear();
break;
}
lastX = x;
lastY = y;
return true;
}
@Override
public void computeScroll() {
super.computeScroll();
if (scroller.computeScrollOffset()){
scrollTo(scroller.getCurrX(),scroller.getCurrY());
postInvalidate();
}
}
/**
* 弹性滑动到指定位置
*/
private void smoothScrollTo(int destX, int destY) {
scroller.startScroll(getScrollX(),getScrollY(),destX-getScrollX(),
destY - getScrollY(),1000);
invalidate();
}
}
自定义ViewGroup,实现水平 HorizontalView
最新推荐文章于 2023-07-07 16:42:43 发布