您的位置:首页 > 其它

ViewPager简单实现

2016-08-12 08:48 141 查看
package com.edu.fzu.news.view;

import android.content.Context;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;
/**
* 使用:
*       MyScrollView myScrollView = (MyScrollView) findViewById(R.id.myscrollview);
*       // 添加子View到MyScrollView中
for (int i = 0; i < ids.length; i++) {
ImageView image = new ImageView(this);
image.setBackgroundResource(ids[i]);
myScrollView.addView(image);
}
*
*
*/

/**
* 仿ViewPager:实现ViewPager随着手指的滑动而滑动
* 实现:
* 1.界面:测量,布局(充血onMeasure和onLayout)
* 2.事件:滑动跟随运动(onTouch事件),松手缓慢滑动到指定位置(Scroller类+computeScroll回调)
* 补充:
*  1.控件滑动有三种方式:Scroller,动画,Layoutparams
*  2.如果要实现类似ViewPager的回调,可采用设计回调接口,然后对外暴露
*/
public class MyScrollView extends ViewGroup {
private Scroller mScroller;

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

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

private void initView() {
mScroller = new Scroller(getContext());
}

/*
display:
1.measure
2.layout
3.draw--this is view, so don't draw
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// measure self
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

// measure child
for (int i=0; i<getChildCount(); i++) {
measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
}
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// layout child
for (int i=0; i<getChildCount(); i++) {
View view = getChildAt(i);
view.layout(i*getWidth(), 0, (i+1)*getWidth(), getHeight());
}
}

/*
刷新思路:
1.监听滑动松开(ACTION_UP),调用启动缓慢滑动事件myScroller.startScroll
并刷新当前view,invalidate();
2.调用invalidate();导致computeScroll被回调
3.计算滑动是否完成myScroller.computeScrollOffset,并获取中间位置
myScroller.getCurrX(),跳转到中间位置
4.重新刷新界面(递归上面2-4步骤)
*/

/*
event:
deal the scroll event
scroll distance
*/
private PointF downPoint = new PointF();
@Override
public boolean onTouchEvent(MotionEvent event) {
// mGestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downPoint.set(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
float curX = event.getX();
float disX = -(curX - downPoint.x);
scrollBy((int) disX, 0);
downPoint.x = curX;
break;
case MotionEvent.ACTION_UP:
int nextId = (getScrollX()+getWidth()/2) / getWidth();
moveToDest(nextId);
break;
}

return true;
}

/**
* 移动到指定的屏幕上
* @param nextId   屏幕 的下标
*/
private void moveToDest(int nextId) {
// check nextId between[0, getChildCount())
if (nextId < 0) {
nextId = 0;
}
if (nextId > getChildCount()-1) {
nextId = getChildCount() - 1;
}

//瞬间移动
// scroll direct to distination
// scrollTo(nextId*getWidth(), 0);

//缓慢移动到指定最终位置
int dx = nextId*getWidth() - getScrollX();
mScroller.startScroll(getScrollX(), 0, dx, 0);
/*
* 刷新当前view   onDraw()方法 的执行
*/
invalidate();
}

@Override
/**
* invalidate();  会导致  computeScroll()这个方法的执行
*/
public void computeScroll() {
if(mScroller.computeScrollOffset()){   // 有点类似回调:两个函数循环互相调用
int newX = (int) mScroller.getCurrX();
scrollTo(newX, 0);

invalidate();
};
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: