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(); }; } }
ViewPager简单实现
最新推荐文章于 2024-04-28 22:24:52 发布