今天给大家分享一个使用Scroller滚动类实现的控件,我们知道,viewpager实现的是一种左右切换的效果,使用scroller+事件分发来实现viewpager本身并不是一件特别难的事,因为viewpager其内部的实现原理就是这样。为了跟大家更好地分享下scroller的用法,我实现了一个可以上下切换的效果。下面直接贴该类代码:
1.VDViewPager.class
import android.content.Context;
import android.support.v4.view.ViewConfigurationCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;
/**
* Created by _H_JY on 2016/3/3.
* instruction:A custom viewpager which srcolls to vertical direction.
*/
public class VDViewPager extends ViewGroup{
/*滚动实例*/
private Scroller mScroller;
/*判断是否滑动的最小距离*/
private int mTouchSlop;
/*手指触摸到屏幕时y值*/
private float mYDown;
/*手指在竖直方向上移动的距离*/
private float mYMove;
/*标记最后的位置*/
private float mLastMove;
/*标记上边缘*/
private int mTopBorder;
/*标记下边缘*/
private int mBottomBorder;
public VDViewPager(Context context) {
this(context, null);
}
public VDViewPager(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public VDViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
/*初始化滚动实例*/
mScroller = new Scroller(context);
/*获取最小滑动值,该值用于判断是否可滑*/
ViewConfiguration vc = ViewConfiguration.get(context);
mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(vc);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int cCount = this.getChildCount();
for (int i=0;i<cCount;i++){
View childView = this.getChildAt(i);
/*测量每一个子View*/
measureChild(childView,widthMeasureSpec,heightMeasureSpec);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if(changed){
int cCount = this.getChildCount();
for (int i=0;i<cCount;i++){
View childView = this.getChildAt(i);
/*从上往下布局*/
childView.layout(0,i*childView.getMeasuredHeight(),childView.getMeasuredWidth(),(i+1)*childView.getMeasuredHeight());
}
mTopBorder = this.getChildAt(0).getTop();
mBottomBorder = this.getChildAt(this.getChildCount()-1).getBottom();
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
mYDown = ev.getRawY();
mLastMove = mYDown;
break;
case MotionEvent.ACTION_MOVE:
mYMove = ev.getRawY();
int diff = (int) Math.abs(mYMove - mYDown);
if(diff > mTouchSlop){ //判断是否可滑
return true;
}
mLastMove = mYMove;
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_MOVE:
mYMove = event.getRawY();
int scrolledY = (int) (mLastMove - mYMove);
if(this.getScrollY() + scrolledY < mTopBorder){
/*到第一个子View顶端时不给下滑*/
this.scrollTo(mTopBorder,0);
return true;
}else if(this.getScrollY() + scrolledY + this.getHeight() > mBottomBorder){
/*到最后一个子View底端时不给上滑*/
this.scrollTo(0,mButtomBorder - this.getHeight());
return true;
}
this.scrollBy(0,scrolledY);
mLastMove = mYMove;
break;
case MotionEvent.ACTION_UP:
int targetIndex = (this.getScrollY()+this.getHeight()/2)/this.getHeight();
/*得到应该滑动的距离*/
int dy = targetIndex*this.getHeight() - this.getScrollY();
/*开始滑动*/
mScroller.startScroll(0,this.getScrollY(),0,dy);
invalidate();
break;
default:
break;
}
return super.onTouchEvent(event);
}
@Override
public void computeScroll() {
super.computeScroll();
/*平滑滚动*/
if(mScroller.computeScrollOffset()){
this.scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
invalidate();
}
}
}
上面的注释写得也比较清晰了,相信大家都能看懂。
<?xml version="1.0" encoding="utf-8"?>
<g.scrolltest.view.VDViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="g.scrolltest.MainActivity">
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="One"/>
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Two"/>
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Three"/>
</g.scrolltest.view.VDViewPager>
3.MainActivity.class(主Activity)
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}