原理见翻页效果原理实现之翻页的尝试



package com.stone.turnpage.view;import android.content.Context;import android.content.res.Configuration;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.os.Handler;import android.view.MotionEvent;import android.view.View;import android.view.ViewConfiguration;import android.widget.Toast;import java.util.ArrayList;import java.util.List;/** * author : stone * email  : aa86799@163.com * time   : 16/7/8 10 35 */public class HorizonTurnPageView extends View {    private List mBitmaps;    private float mClipX; //裁剪右端点坐标    private float mCurPointX;// 指尖触碰屏幕时点X的坐标值    private float mAutoAreaLeft, mAutoAreaRight; //控件左侧和右侧自动吸附的区域    private boolean mIsLastPage; //是否最后一页    private boolean mIsNextPage; //是否下一页    private int mPageIndex;    private Runnable mMsgCallback;    private Handler mHandler = new Handler();    public HorizonTurnPageView(Context context) {        super(context);//        ViewConfiguration.get(context).getScaledTouchSlop()    }    public void setBitmaps(List bitmaps) {        if (null == bitmaps || bitmaps.size() == 0) return;        this.mBitmaps = bitmaps;        System.out.println("setBitmaps");        invalidate();    }    /**     * 图片倒序:集合中最先加入的图(最后绘制)就能绘制在最上层     */    private void initBitmaps() {        if (mBitmaps == null) {            return;        }        List temp = new ArrayList();        for (int i = mBitmaps.size() - 1; i >= 0; i--) {            Bitmap bitmap = Bitmap.createScaledBitmap(mBitmaps.get(i), getWidth(), getHeight(), true);            temp.add(bitmap);        }        mBitmaps = temp;    }    private void drawBitmaps(Canvas canvas) {/*        for (int i = 0; i < mBitmaps.size(); i++) {//            canvas.save();            if (i == mBitmaps.size() - 1) {//只有最后一位的图片(即原集合中的首图)时才裁剪一次                canvas.clipRect(0, 0, mClipX, getHeight());            }            canvas.drawBitmap(mBitmaps.get(i), 0, 0, null);//            canvas.restore();        }*/        /*        如果图片太多,那么 其实只要绘制上下两张图即可,  而不用 所有都绘制        代码重构如下         */        mIsLastPage = false;        mPageIndex = mPageIndex < 0 ? 0 : mPageIndex;        mPageIndex = mPageIndex > mBitmaps.size() ? mBitmaps.size() : mPageIndex;        // 计算数据起始位置        int start = mBitmaps.size() - 2 - mPageIndex;//mBitmaps.size() - 2 表示倒数第二个        int end = mBitmaps.size() - mPageIndex;   // end - start = 2        /*         * 如果数据起点位置小于0则表示当前已经到了最后一张图片         */        if (start < 0) {            mIsLastPage = true; // 此时mPageIndex = size - 1            showToast("已经最后一页了");            // 强制重置起始位置            start = 0;            end = 1;        }        for (int i = start; i < end; i++) {//end - start = 2   这里最多循环两次            if (!mIsLastPage && i == end - 1) {                canvas.clipRect(0, 0, mClipX, getHeight()); //之后的绘制会相对当前裁剪区            }            canvas.drawBitmap(mBitmaps.get(i), 0, 0, null);        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        mIsNextPage = true;        switch (event.getAction() & MotionEvent.ACTION_MASK) {            case MotionEvent.ACTION_DOWN:                mCurPointX = event.getX();                if (mCurPointX < mAutoAreaLeft) {                    mIsNextPage = false; //上一页                    mPageIndex--;                    mClipX = mCurPointX;                    invalidate();                }                break;            case MotionEvent.ACTION_MOVE:                mClipX = event.getX();                invalidate();                break;            case MotionEvent.ACTION_UP:                judgeSlideAuto();                /*                 * 如果当前页不是最后一页                 * 如果是需要翻下一页                 * 并且上一页已被clip掉,即judgeSlideAuto中执行了向左                 */                if (!mIsLastPage && mIsNextPage && mClipX <= 0) {                    mPageIndex++;                    mClipX = getWidth();                    invalidate();                }                break;        }        return true;    }    /**     * 判断是否要自动滑动: 向左或向右 滑动到底     */    private void judgeSlideAuto() {        if (mClipX < mAutoAreaLeft) {// 小于 1/5 w   向左            while (mClipX > 0) {                mClipX--;                invalidate();            }        } else if (mClipX > mAutoAreaRight) {// 大于 4/5 w  向右            while (mClipX < getWidth()) {                mClipX++;                invalidate();            }        }    }    /*    onMeasure后 调用, 如果是ViewGroup型, 在onLayout时又改变了大小才会 再次调用     */    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        System.out.println("onSizeChanged");        initBitmaps();        mClipX = getWidth();        mAutoAreaLeft = getWidth() / 5f;        mAutoAreaRight = getWidth() / 5f * 4;    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (null == mBitmaps || mBitmaps.size() == 0) {            return;        }        drawBitmaps(canvas);    }    private void showToast(final Object msg) {        mHandler.removeCallbacksAndMessages(null);        mMsgCallback = new Runnable() {            @Override            public void run() {                Toast.makeText(getContext(), msg.toString(), Toast.LENGTH_SHORT).show();            }        };        mHandler.postDelayed(mMsgCallback, 200);    }}

我的自定义View项目地址: https://github.com/aa86799/MyCustomView (欢迎start&fork)

本文地址:https://github.com/aa86799/MyCustomView/tree/master/turnpage

更多相关文章

  1. Android 实现图片轮播的三种方法
  2. android 设置 dialog位置
  3. Android 手势滑动,多点触摸放大缩小图片
  4. android 图片压缩的方法
  5. android中wifi原理及流程分析
  6. ArcGIS for Android 离线数据编辑原理
  7. Android有效解决加载大图片时内存溢出的问题
  8. RelativeLayout里常用的位置属性

随机推荐

  1. Android(安卓)中自定义ContentProvider与
  2. Android(安卓)流式布局(标签效果)
  3. Android(安卓)ISurface PostBuffer 处理
  4. Android的开机流程
  5. 【Android(安卓)Native Code开发系列】二
  6. Android(安卓)linux的休眠和唤醒
  7. Android(安卓)通过Base64上传图片到服务
  8. Android进阶之Mp3项目(五)
  9. adb and App
  10. 安卓加载模式(Android(安卓)LauncherMode)