自己动手实现一个可垂直滑动的ViewGroup,相当于可以垂直滑动的viewpager

前言

      1,理解ScrollTo(x,y)和ScrollBy(x,y)的区别,如果不知请自行百度

     2,重写ViewGroup,相关知识自行百度

     3,   资源下载http://download.csdn.net/detail/u012155141/8894845

    4,效果图

      

     

进入正题

    1,重写ViewGroup

三个构造方法和一些需要初始化的内容

      public CustomScrollLayout(Context context) {
this(context, null);
}


public CustomScrollLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}


public CustomScrollLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);


mScroller = new Scroller(context);


mGestureDetector = new GestureDetector(new IGestureDetecror());


ViewConfiguration configuration = ViewConfiguration.get(context);
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();


}


2,重写OnMeasure和OnLayout,在简单化的考虑下本例只在确定尺寸下运行

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);


int height = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);


if (heightMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException(
"ScrollLayout only can run at EXACTLY mode!");
}


int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
view.measure(widthMeasureSpec, heightMeasureSpec);
}
scrollTo(0, 0);
}


protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
int childCount = getChildCount();
int scrollHeight = 0;
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
int height = view.getMeasuredHeight();


view.layout(0, scrollHeight, view.getMeasuredWidth(), scrollHeight
+ height);
scrollHeight += height;
}
}

3,在手指按下到移动这个过程中事件在mGestureDetector.onTouchEvent(event)中处理,用ScrollBy(x,y)来让view中的内容跟随手指移动;

class IGestureDetecror implements OnGestureListener {


@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}


@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
return false;
}


@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub


}


@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// TODO Auto-generated method stub
Log.i("getScrollY=", "" + getScrollY());
scrollBy(0, (int) distanceY);
Log.i("AftergetScrollY=", "" + getScrollY());
return false;
}


@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub


}


@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}


}

4,在onTouchEvent(MotionEvent event)中从手指按下到移动的过程我们在mGestureDetector.onTouchEvent(event)中处理,当手指离开时我们在Up中处理,用ScrollTo(x,y)进行处理

@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub


mGestureDetector.onTouchEvent(event);


int action = event.getAction();
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();// 获得VelocityTracker类实例
}
mVelocityTracker.addMovement(event);// 将事件加入到VelocityTracker类实例中
mVelocityTracker.computeCurrentVelocity(1000);


switch (action) {
case MotionEvent.ACTION_DOWN:
firstY = (int) event.getY();
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:


float yVelocity = Math.abs(mVelocityTracker.getYVelocity());
if (yVelocity > mMaximumVelocity) {
yVelocity = mMaximumVelocity;
}


int tmpId = 0;
int currentY = (int) event.getY();
if (currentY - firstY > getHeight() / 2) {
tmpId = currentId - 1;
} else if (firstY - currentY > getHeight() / 2) {
tmpId = currentId + 1;
} else if ((yVelocity > mMinimumVelocity)
&& yVelocity <= mMaximumVelocity) {
if (currentY - firstY > 0) {
tmpId = currentId - 1;
} else {
tmpId = currentId + 1;
}
} else {
tmpId = currentId;
}


int childCount = getChildCount();
currentId = tmpId < 0 ? 0
: ((tmpId > childCount - 1) ? childCount - 1 : tmpId);
mScroller.startScroll(0, getScrollY(), 0, currentId * getHeight()
- getScrollY());
invalidate();
// scrollTo(0, currentId*getHeight());


break;
case MotionEvent.ACTION_CANCEL:
mVelocityTracker.recycle();
break;


default:
break;
}


return true;


}


@Override
public void computeScroll() {
// TODO Auto-generated method stub
super.computeScroll();
if (mScroller.computeScrollOffset()) {
Log.i("======", "=========");
Log.i("getScrollY=", "" + getScrollY());
Log.i("mScroller.getFinalY()=", "" + mScroller.getFinalY());
Log.i("mScroller.getCurrY()=", "" + mScroller.getCurrY());
scrollTo(0, mScroller.getCurrY());
invalidate();
}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值