我的自定义ScrollView

第一次写博客,主要是公司不能传文件,就想着把关键代码写在博客里,方便以后查看.

今天,根据查找的网上资料,scrollview源码,写了一个类似的VIEW

它主要是通过measureChildWithMargins来布局child,然后通过computeScroll、fling在ontouch时实现滑动,包括拖拽滑动,以及拖拽放开后根据移动速度来滑动.


public class MyScrollView extends FrameLayout {
private static final int INVALI_POINTER_ID = -1;
private Scroller mScroller;
private int mTouchSlop;
private int mMinimumFlingVelocity;
private int mMaximumFlingVelocity;
private VelocityTracker mVelocityTracker;

private float mLastMotionY;
private boolean isDrag = false;
private int mActivePointerId = -1;


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


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


public MyScrollView(Context context) {
super(context);
init(context);
}

private void init(Context ctx){
mScroller = new Scroller(ctx);
ViewConfiguration viewConfiguration = ViewConfiguration.get(ctx);
mTouchSlop = viewConfiguration.getScaledTouchSlop();
mMinimumFlingVelocity = viewConfiguration.getScaledMinimumFlingVelocity();
mMaximumFlingVelocity = viewConfiguration.getScaledMaximumFlingVelocity();
}

@Override
protected void measureChildWithMargins(View child,
int parentWidthMeasureSpec, int widthUsed,
int parentHeightMeasureSpec, int heightUsed) {

super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
parentHeightMeasureSpec, heightUsed);

MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();

int childwidth = getChildMeasureSpec(parentWidthMeasureSpec, 
lp.leftMargin+lp.rightMargin+getPaddingLeft()+getPaddingRight()+widthUsed, 
lp.width);
int childheight = MeasureSpec.makeMeasureSpec(lp.bottomMargin+lp.topMargin, MeasureSpec.UNSPECIFIED);


child.measure(childwidth, childheight);

}

@Override
public void computeScroll() {
// TODO Auto-generated method stub
super.computeScroll();

final Scroller scroller = mScroller;
if(scroller.computeScrollOffset()){
int scrollY = scroller.getCurrY();
int maxY = getChildAt(0).getHeight() - getHeight();
boolean isToEdge = scrollY < 0 || scrollY > maxY;
if(scrollY < 0){
scrollY = 0;
}else if(scrollY > maxY){
scrollY = maxY;
}
scrollTo(0, scrollY);
if(isToEdge){
awakenScrollBars();
}
}
}

private void fling(int velocityY){
int maxY = getChildAt(0).getHeight() - getHeight();
mScroller.fling(getScrollX(), getScrollY(), 0, velocityY, 0, 0, 0, Math.max(0, maxY));
invalidate();
}

@Override
public boolean onTouchEvent(MotionEvent event) {

int contentHeight = getChildAt(0).getHeight();
if(contentHeight > getHeight()){
boolean handled = false;
if(null == mVelocityTracker){
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:{
if(!mScroller.isFinished()){
mScroller.forceFinished(true);
}
mLastMotionY = event.getY();
isDrag = true;
mActivePointerId = event.getPointerId(0);
handled = true;
}
break;
case MotionEvent.ACTION_MOVE:{
final int pointerId = mActivePointerId;
if(isDrag && pointerId != INVALI_POINTER_ID){
final int pointerIndex = event.findPointerIndex(pointerId);
final float y = event.getY(pointerIndex);
int deltaY = (int) (mLastMotionY - y);

System.out.println("zxl---myscrollview---move 2--->"+Math.abs(deltaY)+"--->"+mTouchSlop);
if(Math.abs(deltaY) > mTouchSlop){
mLastMotionY = y;
// mScroller.startScroll(getScrollX(), getScrollY(), 0, deltaY);//这个默认是250毫秒完成滑动,在拖拽滑动时不流畅
mScroller.startScroll(getScrollX(), getScrollY(), 0, deltaY, 0);
invalidate();
handled = true;
}
}
}
break;
case MotionEvent.ACTION_UP:{
final int pointerId = mActivePointerId;
if(isDrag && pointerId != INVALI_POINTER_ID){
final VelocityTracker  velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
int initialVelocityY = (int) velocityTracker.getYVelocity(pointerId);
if(Math.abs(initialVelocityY) > mMinimumFlingVelocity){
fling(-initialVelocityY);
}

isDrag = false;
mActivePointerId = INVALI_POINTER_ID;

if(mVelocityTracker != null){
mVelocityTracker.recycle();
mVelocityTracker = null;
}

handled = true;
}
}
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return handled;
}

return super.onTouchEvent(event);
}


}

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值