Yhzhtk / note

知识代码笔记
https://github.com/Yhzhtk/note/issues
MIT License
108 stars 11 forks source link

Android 翻页特效 EffectReadView #15

Open Yhzhtk opened 9 years ago

Yhzhtk commented 9 years ago
package cn.yicha.tuijian.model.novel.read;

import cn.yicha.tuijian.model.novel.onShowListener;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Region;
import android.graphics.Typeface;
import android.graphics.drawable.GradientDrawable;
import android.view.MotionEvent;
import android.widget.Scroller;

/**
 * 自定义View,实现翻页特效 
 * <br/>改自http://blog.csdn.net/hmg25/article/details/6342539
 * 
 * <br/> 继承自HorizontalReadView,不再实现HorizontalReadView已有的读取设置等方法,只改动与HorizontalReadView不一致的地方。
 *
 * @author gudh
 * @data 2014-1-7
 */
public class EffectReadView extends HorizontalReadView {

    // 阴影相关
    private GradientDrawable mBackShadowDrawableLR;
    private GradientDrawable mBackShadowDrawableRL;
    private GradientDrawable mFolderShadowDrawableLR;
    private GradientDrawable mFolderShadowDrawableRL;

    private GradientDrawable mFrontShadowDrawableHBT;
    private GradientDrawable mFrontShadowDrawableHTB;
    private GradientDrawable mFrontShadowDrawableVLR;
    private GradientDrawable mFrontShadowDrawableVRL;

    private PointF mBezierStart1 = new PointF(); // 贝塞尔曲线起始点
    private PointF mBezierControl1 = new PointF(); // 贝塞尔曲线控制点
    private PointF mBezierVertex1 = new PointF(); // 贝塞尔曲线顶点
    private PointF mBezierEnd1 = new PointF(); // 贝塞尔曲线结束点

    private PointF mBezierStart2 = new PointF(); // 另一条贝塞尔曲线
    private PointF mBezierControl2 = new PointF();
    private PointF mBezierVertex2 = new PointF();
    private PointF mBezierEnd2 = new PointF();

    private float mMaxLength = (float) Math.hypot(screenW, screenH); // 对角线长

    private PointF mTouch = new PointF(); // 拖拽点

    private int mCornerX = 0; // 拖拽点对应的页脚,计算出来的
    private int mCornerY = 0;

    private float mDegrees; // 旋转的角度
    private float mTouchToCornerDis; // 触点到页脚的距离
    private boolean mIsRTOrLB; // 是否属于右上或左下,阴影方向

    private Path mPath0; // 当前页与背面的线
    private Path mPath1; // 背面与下一页的线

    private Paint mPaint; // 画笔,背面颜色处理
    private Scroller mScroller; // 滑动器

    private Bitmap mCurPageBitmap = null; // 当前页
    private Bitmap mNextPageBitmap = null;

    private Matrix mMatrix; // 背面形状
    private float[] mMatrixArray = { 0, 0, 0, 0, 0, 0, 0, 0, 1.0f };

    public EffectReadView(Context context,int fontSize,int[] rgb,Typeface fontFamliy,onShowListener mOnShow){
        super(context, fontSize, rgb, fontFamliy, mOnShow);

        // 创建阴影的GradientDrawable
        createDrawable();

        mPath0 = new Path();
        mPath1 = new Path();

        // 颜色矩阵
        float array[] = { 0.55f, 0, 0, 0, 80.0f, 0, 0.55f, 0, 0, 80.0f, 0, 0,
                0.55f, 0, 80.0f, 0, 0, 0, 0.2f, 0 };
        ColorMatrix cm = new ColorMatrix();
        cm.set(array);
        ColorMatrixColorFilter mColorMatrixFilter = new ColorMatrixColorFilter(
                cm);
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColorFilter(mColorMatrixFilter);

        mMatrix = new Matrix();

        mScroller = new Scroller(getContext());

        resetCorner();
    }

    /**
     * 重置触点
     */
    public void resetCorner(){
        // 初始化触点,不让x,y为0,否则在点计算时会有问题
        mTouch.x = 0.01f;
        mTouch.y = 0.01f;
        calcCornerXY(mTouch.x, mTouch.y);
    }

    /**
     * 处理拖动和弹起的操作事件
     * 
     * @param event
     * @return
     */
    public boolean doTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_MOVE) {
            mTouch.x = event.getX();
            mTouch.y = event.getY();
            this.postInvalidate();
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            if (canDragOver()) {
                startAnimation(1200);
            } else {
                mTouch.x = mCornerX - 0.09f;
                mTouch.y = mCornerY - 0.09f;
            }
            this.postInvalidate();
        }
        return true;
    }

    /**
     * 画当前页区域
     * 
     * @param canvas
     * @param bitmap
     * @param path
     */
    private void drawCurrentPageArea(Canvas canvas, Bitmap bitmap) {
        mPath0.reset();
        mPath0.moveTo(mBezierStart1.x, mBezierStart1.y);
        mPath0.quadTo(mBezierControl1.x, mBezierControl1.y, mBezierEnd1.x,
                mBezierEnd1.y);
        mPath0.lineTo(mTouch.x, mTouch.y);
        mPath0.lineTo(mBezierEnd2.x, mBezierEnd2.y);
        mPath0.quadTo(mBezierControl2.x, mBezierControl2.y, mBezierStart2.x,
                mBezierStart2.y);
        mPath0.lineTo(mCornerX, mCornerY);
        mPath0.close();

        canvas.save();
        canvas.clipPath(mPath0, Region.Op.XOR);
        canvas.drawBitmap(bitmap, 0, 0, null);
        canvas.restore();
    }

    /**
     * 画下一页和背景页
     * 
     * @param canvas
     * @param bitmap
     */
    private void drawNextPageAreaAndShadow(Canvas canvas, Bitmap bitmap) {
        mPath1.reset();
        mPath1.moveTo(mBezierStart1.x, mBezierStart1.y);
        mPath1.lineTo(mBezierVertex1.x, mBezierVertex1.y);
        mPath1.lineTo(mBezierVertex2.x, mBezierVertex2.y);
        mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);
        mPath1.lineTo(mCornerX, mCornerY);
        mPath1.close();

        mDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl1.x
                - mCornerX, mBezierControl2.y - mCornerY));
        int leftx;
        int rightx;
        GradientDrawable mBackShadowDrawable;
        if (mIsRTOrLB) {
            leftx = (int) (mBezierStart1.x);
            rightx = (int) (mBezierStart1.x + mTouchToCornerDis / 4);
            mBackShadowDrawable = mBackShadowDrawableLR;
        } else {
            leftx = (int) (mBezierStart1.x - mTouchToCornerDis / 4);
            rightx = (int) mBezierStart1.x;
            mBackShadowDrawable = mBackShadowDrawableRL;
        }
        canvas.save();
        canvas.clipPath(mPath0);
        canvas.clipPath(mPath1, Region.Op.INTERSECT);
        canvas.drawBitmap(bitmap, 0, 0, null);

        // 绘阴影
        canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);
        mBackShadowDrawable.setBounds(leftx, (int) mBezierStart1.y, rightx,
                (int) (mMaxLength + mBezierStart1.y));
        mBackShadowDrawable.draw(canvas);
        canvas.restore();
    }

    /**
     * 绘制翻起页的阴影
     */
    public void drawCurrentPageShadow(Canvas canvas) {
        double degree;
        if (mIsRTOrLB) {
            degree = Math.PI
                    / 4
                    - Math.atan2(mBezierControl1.y - mTouch.y, mTouch.x
                            - mBezierControl1.x);
        } else {
            degree = Math.PI
                    / 4
                    - Math.atan2(mTouch.y - mBezierControl1.y, mTouch.x
                            - mBezierControl1.x);
        }
        // 翻起页阴影顶点与touch点的距离
        double d1 = (float) 25 * 1.414 * Math.cos(degree);
        double d2 = (float) 25 * 1.414 * Math.sin(degree);
        float x = (float) (mTouch.x + d1);
        float y;
        if (mIsRTOrLB) {
            y = (float) (mTouch.y + d2);
        } else {
            y = (float) (mTouch.y - d2);
        }
        mPath1.reset();
        mPath1.moveTo(x, y);
        mPath1.lineTo(mTouch.x, mTouch.y);
        mPath1.lineTo(mBezierControl1.x, mBezierControl1.y);
        mPath1.lineTo(mBezierStart1.x, mBezierStart1.y);
        mPath1.close();
        float rotateDegrees;

        canvas.save();
        canvas.clipPath(mPath0, Region.Op.XOR);
        canvas.clipPath(mPath1, Region.Op.INTERSECT);
        int leftx;
        int rightx;
        GradientDrawable mCurrentPageShadow;
        if (mIsRTOrLB) {
            leftx = (int) (mBezierControl1.x);
            rightx = (int) mBezierControl1.x + 25;
            mCurrentPageShadow = mFrontShadowDrawableVLR;
        } else {
            leftx = (int) (mBezierControl1.x - 25);
            rightx = (int) mBezierControl1.x + 1;
            mCurrentPageShadow = mFrontShadowDrawableVRL;
        }

        rotateDegrees = (float) Math.toDegrees(Math.atan2(mTouch.x
                - mBezierControl1.x, mBezierControl1.y - mTouch.y));
        canvas.rotate(rotateDegrees, mBezierControl1.x, mBezierControl1.y);
        mCurrentPageShadow.setBounds(leftx,
                (int) (mBezierControl1.y - mMaxLength), rightx,
                (int) (mBezierControl1.y));
        mCurrentPageShadow.draw(canvas);
        canvas.restore();

        mPath1.reset();
        mPath1.moveTo(x, y);
        mPath1.lineTo(mTouch.x, mTouch.y);
        mPath1.lineTo(mBezierControl2.x, mBezierControl2.y);
        mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);
        mPath1.close();
        canvas.save();
        canvas.clipPath(mPath0, Region.Op.XOR);
        canvas.clipPath(mPath1, Region.Op.INTERSECT);
        if (mIsRTOrLB) {
            leftx = (int) (mBezierControl2.y);
            rightx = (int) (mBezierControl2.y + 25);
            mCurrentPageShadow = mFrontShadowDrawableHTB;
        } else {
            leftx = (int) (mBezierControl2.y - 25);
            rightx = (int) (mBezierControl2.y + 1);
            mCurrentPageShadow = mFrontShadowDrawableHBT;
        }
        rotateDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl2.y
                - mTouch.y, mBezierControl2.x - mTouch.x));
        canvas.rotate(rotateDegrees, mBezierControl2.x, mBezierControl2.y);
        float temp;
        if (mBezierControl2.y < 0)
            temp = mBezierControl2.y - screenH;
        else
            temp = mBezierControl2.y;

        int hmg = (int) Math.hypot(mBezierControl2.x, temp);
        if (hmg > mMaxLength)
            mCurrentPageShadow
                    .setBounds((int) (mBezierControl2.x - 25) - hmg, leftx,
                            (int) (mBezierControl2.x + mMaxLength) - hmg,
                            rightx);
        else
            mCurrentPageShadow.setBounds(
                    (int) (mBezierControl2.x - mMaxLength), leftx,
                    (int) (mBezierControl2.x), rightx);

        mCurrentPageShadow.draw(canvas);
        canvas.restore();
    }

    /**
     * 绘制翻起页背面
     */
    private void drawCurrentBackArea(Canvas canvas, Bitmap bitmap) {
        int i = (int) (mBezierStart1.x + mBezierControl1.x) / 2;
        float f1 = Math.abs(i - mBezierControl1.x);
        int i1 = (int) (mBezierStart2.y + mBezierControl2.y) / 2;
        float f2 = Math.abs(i1 - mBezierControl2.y);
        float f3 = Math.min(f1, f2);
        mPath1.reset();
        mPath1.moveTo(mBezierVertex2.x, mBezierVertex2.y);
        mPath1.lineTo(mBezierVertex1.x, mBezierVertex1.y);
        mPath1.lineTo(mBezierEnd1.x, mBezierEnd1.y);
        mPath1.lineTo(mTouch.x, mTouch.y);
        mPath1.lineTo(mBezierEnd2.x, mBezierEnd2.y);
        mPath1.close();
        GradientDrawable mFolderShadowDrawable;
        int left;
        int right;
        if (mIsRTOrLB) {
            left = (int) (mBezierStart1.x - 1);
            right = (int) (mBezierStart1.x + f3 + 1);
            mFolderShadowDrawable = mFolderShadowDrawableLR;
        } else {
            left = (int) (mBezierStart1.x - f3 - 1);
            right = (int) (mBezierStart1.x + 1);
            mFolderShadowDrawable = mFolderShadowDrawableRL;
        }
        canvas.save();
        canvas.clipPath(mPath0);
        canvas.clipPath(mPath1, Region.Op.INTERSECT);

        float dis = (float) Math.hypot(mCornerX - mBezierControl1.x,
                mBezierControl2.y - mCornerY);
        float f8 = (mCornerX - mBezierControl1.x) / dis;
        float f9 = (mBezierControl2.y - mCornerY) / dis;
        mMatrixArray[0] = 1 - 2 * f9 * f9;
        mMatrixArray[1] = 2 * f8 * f9;
        mMatrixArray[3] = mMatrixArray[1];
        mMatrixArray[4] = 1 - 2 * f8 * f8;
        mMatrix.reset();
        mMatrix.setValues(mMatrixArray);
        mMatrix.preTranslate(-mBezierControl1.x, -mBezierControl1.y);
        mMatrix.postTranslate(mBezierControl1.x, mBezierControl1.y);
        canvas.drawBitmap(bitmap, mMatrix, mPaint);
        // canvas.drawBitmap(bitmap, mMatrix, null);
        // mPaint.setColorFilter(null);

        canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);
        mFolderShadowDrawable.setBounds(left, (int) mBezierStart1.y, right,
                (int) (mBezierStart1.y + mMaxLength));
        mFolderShadowDrawable.draw(canvas);
        canvas.restore();
    }

    /**
     * 在指定时间内滑动出去
     * 
     * @param delayMillis
     */
    private void startAnimation(int delayMillis) {
        int dx, dy;
        // dx 水平方向滑动的距离,负值会使滚动向左滚动
        // dy 垂直方向滑动的距离,负值会使滚动向上滚动
        if (mCornerX > 0) {
            dx = -(int) (screenW + mTouch.x);
        } else {
            dx = (int) (screenW - mTouch.x + screenW);
        }
        if (mCornerY > 0) {
            dy = (int) (screenH - mTouch.y);
        } else {
            dy = (int) (1 - mTouch.y); // 防止mTouch.y最终变为0
        }
        mScroller.startScroll((int) mTouch.x, (int) mTouch.y, dx, dy,
                delayMillis);
    }

    /**
     * 滑动过程处理
     */
    public void computeScroll() {
        super.computeScroll();
        if (mScroller.computeScrollOffset()) {
            float x = mScroller.getCurrX();
            float y = mScroller.getCurrY();
            mTouch.x = x;
            mTouch.y = y;
            postInvalidate();
        }
    }

    /**
     * 计算各个点
     */
    private void calcPoints() {
        // 触电到页脚的中点
        float mMiddleX = (mTouch.x + mCornerX) / 2;
        float mMiddleY = (mTouch.y + mCornerY) / 2;

        mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY)
                * (mCornerY - mMiddleY) / (mCornerX - mMiddleX);
        mBezierControl1.y = mCornerY;

        mBezierControl2.x = mCornerX;
        mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)
                * (mCornerX - mMiddleX) / (mCornerY - mMiddleY);

        mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x)
                / 2;
        mBezierStart1.y = mCornerY;

        // 当mBezierStart1.x < 0或者mBezierStart1.x > 480时
        // 如果继续翻页,会出现BUG故在此限制
        if (mTouch.x > 0 && mTouch.x < screenW) {
            if (mBezierStart1.x < 0 || mBezierStart1.x > screenW) {
                if (mBezierStart1.x < 0) {
                    mBezierStart1.x = screenW - mBezierStart1.x;
                }

                float f1 = Math.abs(mCornerX - mTouch.x);
                float f2 = screenW * f1 / mBezierStart1.x;
                mTouch.x = Math.abs(mCornerX - f2);

                float f3 = Math.abs(mCornerX - mTouch.x)
                        * Math.abs(mCornerY - mTouch.y) / f1;
                mTouch.y = Math.abs(mCornerY - f3);

                mMiddleX = (mTouch.x + mCornerX) / 2;
                mMiddleY = (mTouch.y + mCornerY) / 2;

                mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY)
                        * (mCornerY - mMiddleY) / (mCornerX - mMiddleX);
                mBezierControl1.y = mCornerY;

                mBezierControl2.x = mCornerX;
                mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)
                        * (mCornerX - mMiddleX) / (mCornerY - mMiddleY);

                mBezierStart1.x = mBezierControl1.x
                        - (mCornerX - mBezierControl1.x) / 2;
            }
        }
        mBezierStart2.x = mCornerX;
        mBezierStart2.y = mBezierControl2.y - (mCornerY - mBezierControl2.y)
                / 2;

        mTouchToCornerDis = (float) Math.hypot((mTouch.x - mCornerX),
                (mTouch.y - mCornerY));

        mBezierEnd1 = getCross(mTouch, mBezierControl1, mBezierStart1,
                mBezierStart2);
        mBezierEnd2 = getCross(mTouch, mBezierControl2, mBezierStart1,
                mBezierStart2);

        /*
         * mBeziervertex1.x 推导
         * ((mBezierStart1.x+mBezierEnd1.x)/2+mBezierControl1.x)/2 化简等价于
         * (mBezierStart1.x+ 2*mBezierControl1.x+mBezierEnd1.x) / 4
         */
        mBezierVertex1.x = (mBezierStart1.x + 2 * mBezierControl1.x + mBezierEnd1.x) / 4;
        mBezierVertex1.y = (2 * mBezierControl1.y + mBezierStart1.y + mBezierEnd1.y) / 4;
        mBezierVertex2.x = (mBezierStart2.x + 2 * mBezierControl2.x + mBezierEnd2.x) / 4;
        mBezierVertex2.y = (2 * mBezierControl2.y + mBezierStart2.y + mBezierEnd2.y) / 4;
    }

    /**
     * 如果没有停止,则终止滑动
     */
    public void abortAnimation() {
        if (!mScroller.isFinished()) {
            mScroller.abortAnimation();
        }
    }

    /**
     * 判断是否需要继续自动翻页至结束
     * 
     * @return
     */
    public boolean canDragOver() {
        // 拖动距离超过宽度十分之一,则需要翻页,否则不需要
        if (mTouchToCornerDis > screenW / 10) {
            return true;
        }
        return false;
    }

    /**
     * 是否从左边翻向右边
     */
    public boolean DragToRight() {
        return mCornerX == 0;
    }

    /**
     * 计算拖拽点对应的拖拽脚
     */
    public void calcCornerXY(float x, float y) {
        mTouch.x = x;
        mTouch.y = y;

        if (x <= screenW / 2) {
            mCornerX = 0;
        } else {
            mCornerX = screenW;
        }
        if (y <= screenH / 2) {
            mCornerY = 0;
        } else {
            mCornerY = screenH;
        }
        if ((mCornerX == 0 && mCornerY == screenH)
                || (mCornerX == screenW && mCornerY == 0)) {
            mIsRTOrLB = true; // corner在左下角或者右上角
        } else {
            mIsRTOrLB = false;
        }
    }

    /**
     * 创建阴影的GradientDrawable
     */
    private void createDrawable() {
        int[] color = { 0x333333, 0xb0333333 };
        mFolderShadowDrawableRL = new GradientDrawable(
                GradientDrawable.Orientation.RIGHT_LEFT, color);
        mFolderShadowDrawableRL
                .setGradientType(GradientDrawable.LINEAR_GRADIENT);

        mFolderShadowDrawableLR = new GradientDrawable(
                GradientDrawable.Orientation.LEFT_RIGHT, color);
        mFolderShadowDrawableLR
                .setGradientType(GradientDrawable.LINEAR_GRADIENT);

        int[] mBackShadowColors = new int[] { 0xff111111, 0x111111 };
        mBackShadowDrawableRL = new GradientDrawable(
                GradientDrawable.Orientation.RIGHT_LEFT, mBackShadowColors);
        mBackShadowDrawableRL.setGradientType(GradientDrawable.LINEAR_GRADIENT);

        mBackShadowDrawableLR = new GradientDrawable(
                GradientDrawable.Orientation.LEFT_RIGHT, mBackShadowColors);
        mBackShadowDrawableLR.setGradientType(GradientDrawable.LINEAR_GRADIENT);

        int[] mFrontShadowColors = new int[] { 0x80111111, 0x111111 };
        mFrontShadowDrawableVLR = new GradientDrawable(
                GradientDrawable.Orientation.LEFT_RIGHT, mFrontShadowColors);
        mFrontShadowDrawableVLR
                .setGradientType(GradientDrawable.LINEAR_GRADIENT);
        mFrontShadowDrawableVRL = new GradientDrawable(
                GradientDrawable.Orientation.RIGHT_LEFT, mFrontShadowColors);
        mFrontShadowDrawableVRL
                .setGradientType(GradientDrawable.LINEAR_GRADIENT);

        mFrontShadowDrawableHTB = new GradientDrawable(
                GradientDrawable.Orientation.TOP_BOTTOM, mFrontShadowColors);
        mFrontShadowDrawableHTB
                .setGradientType(GradientDrawable.LINEAR_GRADIENT);

        mFrontShadowDrawableHBT = new GradientDrawable(
                GradientDrawable.Orientation.BOTTOM_TOP, mFrontShadowColors);
        mFrontShadowDrawableHBT
                .setGradientType(GradientDrawable.LINEAR_GRADIENT);
    }

    /**
     * 求解直线P1P2和直线P3P4的交点坐标
     */
    public PointF getCross(PointF P1, PointF P2, PointF P3, PointF P4) {
        PointF CrossP = new PointF();
        // 二元函数通式: y=ax+b
        float a1 = (P2.y - P1.y) / (P2.x - P1.x);
        float b1 = ((P1.x * P2.y) - (P2.x * P1.y)) / (P1.x - P2.x);

        float a2 = (P4.y - P3.y) / (P4.x - P3.x);
        float b2 = ((P3.x * P4.y) - (P4.x * P3.y)) / (P3.x - P4.x);
        CrossP.x = (b2 - b1) / (a1 - a2);
        CrossP.y = a1 * CrossP.x + b1;
        return CrossP;
    }

    /**
     * 绘图方法
     */
    @Override
    protected void onDraw(Canvas canvas) {
        if(mNextPageBitmap == mCurPageBitmap){
            this.resetCorner();
        }

        // 计算各个点
        calcPoints();

        canvas.drawColor(0xFFAAAAAA);
        drawCurrentPageArea(canvas, mCurPageBitmap);
        drawCurrentPageShadow(canvas);
        drawNextPageAreaAndShadow(canvas, mNextPageBitmap);
        drawCurrentBackArea(canvas, mCurPageBitmap);

        // 绘制title
        if (title != null) {
            canvas.drawText(title, super.screenW / 2
                    - (titlePaint.measureText(title) / 2), this.titleH,
                    titlePaint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            showMenu=false;
            touchStartX = event.getX();
            touchStartY = event.getY();
            // 记录 指针指向恢复使用
            charStartPosTmp = charStartPos;
            charEndPosTmp = charEndPos;

            touchType = parseEvent(event.getX(), event.getY());
            if(touchType == 0){
                // 如果为弹框,则重设按点
                this.resetCorner();
            }else{
                this.abortAnimation();
                this.calcCornerXY(touchStartX, touchStartY);
            }

            switch (touchType) {
            case -1:// prv
                if (touchLock)
                    return false;
                this.oldX = event.getX();
                oldHideStepX = 20;
                getPrvBitmap();
                break;
            case 0:// menu
                // 当前置为最新
                mCurPageBitmap = mNextPageBitmap;
                showMenu=true;
                break;
            case 1:// next
                if (touchLock)
                    return false;
                this.oldX = event.getX();
                oldHideStepX = -20;
                getNextBitmap();
                break;
            }

            break;
        case MotionEvent.ACTION_MOVE:
            if(showMenu){break;}
            endX = event.getX();
            endY = event.getY();
            if (Math.abs(endX - touchStartX) > maxX)
                maxX = Math.abs(endX - touchStartX);
            this.oldX = endX;

            //invalidate();
            this.doTouchEvent(event);

            break;
        case MotionEvent.ACTION_UP:
            if (showMenu&&mOnShow != null){
                mOnShow.onShowBar();
                break;
                }
            this.endX = -1;
            this.oldX = event.getX();
            if ((event.getX() - touchStartX) < maxX * 2 / 5 && oldHideStepX > 0) {// 取消往右滑动
                oldHideStepX = -20;
                mNextPageBitmap = mCurPageBitmap;
                this.resetCorner();
                // 回滚标记点
                charStartPos = charStartPosTmp;
                charEndPos = charEndPosTmp;
                mOnShow.markReadPos(charStartPos);
            } else if (oldHideStepX < 0
                    && (touchStartX - event.getX()) < maxX * 3 / 5) {// 取消往左滑行
                oldHideStepX = 20;
                mNextPageBitmap = mCurPageBitmap;
                this.resetCorner();
                // 回滚标记点
                charStartPos = charStartPosTmp;
                charEndPos = charEndPosTmp;
                mOnShow.markReadPos(charStartPos);
            }
            maxX = 0;

            //invalidate();
            this.doTouchEvent(event);
            break;
        }
        return true;
    }

    @Override
    public void getPrvBitmap() {
        if(charStartPos <= 0) {//需要加载数据
            this.lor=-1;
            this.isButtonAction=false;
            this.charStartPos=this.charEndPos=0;
            mOnShow.getPrvChapter();

            mCurPageBitmap = mNextPageBitmap;
            return ;
        }
        charEndPos = charStartPos;
        charStartPos = 0;// 上届标记为起始
        getLinesToDraw(charStartPos, charEndPos, false);

        // 修改real和now的关系
        mCurPageBitmap = mNextPageBitmap;
        mNextPageBitmap = getBitmap();
    }

    @Override
    public void getNextBitmap() {
        if (charEndPos >= this.textCharArr.length - 1) {// 需要加载下一章内容
            this.lor=1;
            this.isButtonAction=false;
            mOnShow.getNextChapter();

            mCurPageBitmap = mNextPageBitmap;
            return;
        }
        charStartPos = charEndPos;
        charEndPos = this.textCharArr.length - 1;
        getLinesToDraw(charStartPos, charEndPos, true);

        // 修改real和now的关系
        mCurPageBitmap = mNextPageBitmap;
        mNextPageBitmap = getBitmap();
        if(mCurPageBitmap == null){
            mCurPageBitmap = mNextPageBitmap;
        }
    }

    @Override
    public void setFontSize(int size) {
        fontSize=size;
        paint.setTextSize(size);
        this.rebuildEnvironment();
        paint.getTextWidths(textCharArr, 0, textCharArr.length,textCharArrWidth);
        getLinesToDraw(charStartPos, textCharArr.length-1, true);

        // 修改now也为当前,及时更新
        mNextPageBitmap = getBitmap();
        mCurPageBitmap = mNextPageBitmap;
        invalidate();
    }

    @Override
    public void setFontColor(int r,int g,int b) {
        this.r = r;
        this.g = g;
        this.b = b;
        setTextFrontColor(r, g, b);

        // 修改now也为当前,及时更新
        mNextPageBitmap = getBitmap();
        mCurPageBitmap = mNextPageBitmap;
        invalidate();
    }
}
xzwszl commented 8 years ago

Where is HorizontalReadView

Yhzhtk commented 8 years ago

去原始博客上下源码看下有木有? 这个我是模仿的,好久不写 Android了 http://download.csdn.net/detail/hmg25/3278901