根据源码仿写HorizontalScrollView

根据源码仿写HorizontalScrollView

package com.myf.scrollerscalerulerview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.support.v4.view.ViewConfigurationCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
/**
 * 仿写
 * @author ZH-SW-Mengyf
 *
 */
public class HScrollerLayout extends ViewGroup {
    /**
     * 判定为拖动的最小移动像素数
     */
    private int mTouchSlop;
    
	/**
	 * 界面可滚动的左边界
	 */
	private int mLeftBorder;

	/**
	 * 界面可滚动的右边界
	 */
	private int mRightBorder;
	
	private int mEventX;
	
	private int mOverscrollDistance;
	
	private int mLastMotionX;
	
	private boolean mIsBeingDragged= false;
	
	private int mScrollX;

	public HScrollerLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	public HScrollerLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	public HScrollerLayout(Context context) {
		super(context);
		init(context);
	}
	
	private void init(Context context) {
	    // 第一步,创建Scroller的实例
        ViewConfiguration configuration = ViewConfiguration.get(context);
        // 获取TouchSlop值
        mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
        
        mOverscrollDistance = configuration.getScaledOverscrollDistance();
        
	}

	   @Override
	    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
	        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	        int childCount = getChildCount();
	        for (int i = 0; i < childCount; i++) {
	            View childView = getChildAt(i);
	            // 为ScrollerLayout中的每一个子控件测量大小
	            measureChild(childView, widthMeasureSpec, heightMeasureSpec);
	        }
	    }
	
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		if (changed) {
			int childCount = getChildCount();
			for (int i = 0; i < childCount; i++) {
				View childView = getChildAt(i);
				// 为ScrollerLayout中的每一个子控件在水平方向上进行布局
				childView.layout(i * childView.getMeasuredWidth(), 0, (i + 1)* childView.getMeasuredWidth(),childView.getMeasuredHeight());
			}
			
			// 初始化左右边界值
			mLeftBorder = getChildAt(0).getLeft();
			
			mRightBorder = getChildAt(getChildCount() - 1).getRight();

			final int scrollRange = Math.max(0, getWidth() - (mRightBorder - mLeftBorder));

			mScrollX = scrollRange;
			
			if (mScrollX > scrollRange) {
				mScrollX = scrollRange;
			} 
			else if (mScrollX < 0) {
				mScrollX = 0;
			}
			scrollTo(mScrollX, 0);
		}
	}
	
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		mEventX = (int) ev.getX();
		switch (ev.getAction()) {
		case MotionEvent.ACTION_MOVE:
			int xDiff = (int) Math.abs(mLastMotionX - mEventX);
			// 当手指拖动值大于TouchSlop值时,认为应该进行滚动,拦截子控件的事件
			if (xDiff > mTouchSlop) {
				mIsBeingDragged = true;
				mLastMotionX = mEventX; 
				return true;
			}
			break;
			
		   case MotionEvent.ACTION_CANCEL:
           case MotionEvent.ACTION_UP:
        	   mIsBeingDragged = false;
        	   break;
		}
		return super.onInterceptTouchEvent(ev);
	}

	
	@SuppressLint("NewApi") @Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			mLastMotionX = (int) event.getX();
			break;

		case MotionEvent.ACTION_MOVE:
			int x = (int) event.getX();
			int deltaX = (int) (mLastMotionX - x);
			if (!mIsBeingDragged) {
				mIsBeingDragged = true;
				if (deltaX > 0) {
					deltaX -= mTouchSlop;
				} else {
					deltaX += mTouchSlop;
				}
			}
			if (mIsBeingDragged) {
				mLastMotionX = x;
				final int range = getScrollRange();
				Log.d("myf", "range" + range + "====" + mOverscrollDistance);
				overScrollBy(deltaX, 0, mScrollX, 0, range, 0, mOverscrollDistance, 0, true);
				postInvalidateOnAnimation();
			}
			break;

		case MotionEvent.ACTION_UP:
			if (mIsBeingDragged) {
				mIsBeingDragged = false;
			}
			break;
		}

		return true;
	}
	
	/**
	 * 可以滚动的最大范围
	 * @return
	 */
    private int getScrollRange() {
        int scrollRange = (mRightBorder - mLeftBorder) - getWidth();
        return scrollRange;
    }
	
	@Override
	protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX,boolean clampedY) {
		mScrollX = scrollX;
		Log.d("myf", "onOverScrolled scrollX:"+scrollX);
		 super.scrollTo(scrollX, scrollY);
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值