posts - 495,comments - 227,trackbacks - 0


          package sf.hmg.turntest;

          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.drawable.GradientDrawable;
          import android.view.MotionEvent;
          import android.view.View;
          import android.widget.Scroller;

          public class PageWidget extends View {

              
          private static final String TAG = "hmg";
              
          private int mWidth = 480;
              
          private int mHeight = 800;
              
          private int mCornerX = 0// 拖拽點對應的頁腳
              private int mCornerY = 0;
              
          private Path mPath0;
              
          private Path mPath1;
              Bitmap mCurPageBitmap 
          = null// 當前頁
              Bitmap mNextPageBitmap = null;

              PointF mTouch 
          = new PointF(); // 拖拽點
              PointF mBezierStart1 = new PointF(); // 貝塞爾曲線起始點
              PointF mBezierControl1 = new PointF(); // 貝塞爾曲線控制點
              PointF mBeziervertex1 = new PointF(); // 貝塞爾曲線頂點
              PointF mBezierEnd1 = new PointF(); // 貝塞爾曲線結束點

              PointF mBezierStart2 
          = new PointF(); // 另一條貝塞爾曲線
              PointF mBezierControl2 = new PointF();
              PointF mBeziervertex2 
          = new PointF();
              PointF mBezierEnd2 
          = new PointF();

              
          float mMiddleX;
              
          float mMiddleY;
              
          float mDegrees;
              
          float mTouchToCornerDis;
              ColorMatrixColorFilter mColorMatrixFilter;
              Matrix mMatrix;
              
          float[] mMatrixArray = { 000000001.0f };

              
          boolean mIsRTandLB; // 是否屬于右上左下
              float mMaxLength = (float) Math.hypot(mWidth, mHeight);
              
          int[] mBackShadowColors;
              
          int[] mFrontShadowColors;
              GradientDrawable mBackShadowDrawableLR;
              GradientDrawable mBackShadowDrawableRL;
              GradientDrawable mFolderShadowDrawableLR;
              GradientDrawable mFolderShadowDrawableRL;

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

              Paint mPaint;

              Scroller mScroller;

              
          public PageWidget(Context context) {
                  
          super(context);
                  
          // TODO Auto-generated constructor stub
                  mPath0 = new Path();
                  mPath1 
          = new Path();
                  createDrawable();

                  mPaint 
          = new Paint();
                  mPaint.setStyle(Paint.Style.FILL);

                  ColorMatrix cm 
          = new ColorMatrix();
                  
          float array[] = { 0.55f00080.0f00.55f0080.0f00,
                          
          0.55f080.0f0000.2f0 };
                  cm.set(array);
                  mColorMatrixFilter 
          = new ColorMatrixColorFilter(cm);
                  mMatrix 
          = new Matrix();
                  mScroller 
          = new Scroller(getContext());

                  mTouch.x 
          = 0.01f// 不讓x,y為0,否則在點計算時會有問題
                  mTouch.y = 0.01f;
              }

              
          /**
               * Author : hmg25 Version: 1.0 Description : 計算拖拽點對應的拖拽腳
               
          */
              
          public void calcCornerXY(float x, float y) {
                  
          if (x <= mWidth / 2)
                      mCornerX 
          = 0;
                  
          else
                      mCornerX 
          = mWidth;
                  
          if (y <= mHeight / 2)
                      mCornerY 
          = 0;
                  
          else
                      mCornerY 
          = mHeight;
                  
          if ((mCornerX == 0 && mCornerY == mHeight)
                          
          || (mCornerX == mWidth && mCornerY == 0))
                      mIsRTandLB 
          = true;
                  
          else
                      mIsRTandLB 
          = false;
              }

              
          public boolean doTouchEvent(MotionEvent event) {
                  
          // TODO Auto-generated method stub
                  if (event.getAction() == MotionEvent.ACTION_MOVE) {
                      mTouch.x 
          = event.getX();
                      mTouch.y 
          = event.getY();
                      
          this.postInvalidate();
                  }
                  
          if (event.getAction() == MotionEvent.ACTION_DOWN) {
                      mTouch.x 
          = event.getX();
                      mTouch.y 
          = event.getY();
                      
          // calcCornerXY(mTouch.x, mTouch.y);
                      
          // this.postInvalidate();
                  }
                  
          if (event.getAction() == MotionEvent.ACTION_UP) {
                      
          if (canDragOver()) {
                          startAnimation(
          1200);
                      } 
          else {
                          mTouch.x 
          = mCornerX - 0.09f;
                          mTouch.y 
          = mCornerY - 0.09f;
                      }

                      
          this.postInvalidate();
                  }
                  
          // return super.onTouchEvent(event);
                  return true;
              }

              
          /**
               * Author : hmg25 Version: 1.0 Description : 求解直線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;
              }

              
          private void calcPoints() {
                  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);

                  
          // Log.i("hmg", "mTouchX  " + mTouch.x + "  mTouchY  " + mTouch.y);
                  
          // Log.i("hmg", "mBezierControl1.x  " + mBezierControl1.x
                  
          // + "  mBezierControl1.y  " + mBezierControl1.y);
                  
          // Log.i("hmg", "mBezierControl2.x  " + mBezierControl2.x
                  
          // + "  mBezierControl2.y  " + mBezierControl2.y);

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

                  
          // 當mBezierStart1.x < 0或者mBezierStart1.x > 480時
                  
          // 如果繼續翻頁,會出現BUG故在此限制
                  if (mTouch.x > 0 && mTouch.x < mWidth) {
                      
          if (mBezierStart1.x < 0 || mBezierStart1.x > mWidth) {
                          
          if (mBezierStart1.x < 0)
                              mBezierStart1.x 
          = mWidth - mBezierStart1.x;

                          
          float f1 = Math.abs(mCornerX - mTouch.x);
                          
          float f2 = mWidth * 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);
                          
          // Log.i("hmg", "mTouchX --> " + mTouch.x + "  mTouchY-->  "
                          
          // + mTouch.y);
                          
          // Log.i("hmg", "mBezierControl1.x--  " + mBezierControl1.x
                          
          // + "  mBezierControl1.y -- " + mBezierControl1.y);
                          
          // Log.i("hmg", "mBezierControl2.x -- " + mBezierControl2.x
                          
          // + "  mBezierControl2.y -- " + mBezierControl2.y);
                          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);

                  
          // Log.i("hmg", "mBezierEnd1.x  " + mBezierEnd1.x + "  mBezierEnd1.y  "
                  
          // + mBezierEnd1.y);
                  
          // Log.i("hmg", "mBezierEnd2.x  " + mBezierEnd2.x + "  mBezierEnd2.y  "
                  
          // + mBezierEnd2.y);

                  
          /*
                   * 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;
              }

              
          private void drawCurrentPageArea(Canvas canvas, Bitmap bitmap, Path path) {
                  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(path, Region.Op.XOR);
                  canvas.drawBitmap(bitmap, 
          00null);
                  canvas.restore();
              }

              
          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 (mIsRTandLB) {
                      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, 
          00null);
                  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 setBitmaps(Bitmap bm1, Bitmap bm2) {
                  mCurPageBitmap 
          = bm1;
                  mNextPageBitmap 
          = bm2;
              }

              
          public void setScreen(int w, int h) {
                  mWidth 
          = w;
                  mHeight 
          = h;
              }

              @Override
              
          protected void onDraw(Canvas canvas) {
                  canvas.drawColor(
          0xFFAAAAAA);
                  calcPoints();
                  drawCurrentPageArea(canvas, mCurPageBitmap, mPath0);
                  drawNextPageAreaAndShadow(canvas, mNextPageBitmap);
                  drawCurrentPageShadow(canvas);
                  drawCurrentBackArea(canvas, mCurPageBitmap);
              }

              
          /**
               * Author : hmg25 Version: 1.0 Description : 創建陰影的GradientDrawable
               
          */
              
          private void createDrawable() {
                  
          int[] color = { 0x3333330xb0333333 };
                  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);

                  mBackShadowColors 
          = new int[] { 0xff1111110x111111 };
                  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);

                  mFrontShadowColors 
          = new int[] { 0x801111110x111111 };
                  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);
              }

              
          /**
               * Author : hmg25 Version: 1.0 Description : 繪制翻起頁的陰影
               
          */
              
          public void drawCurrentPageShadow(Canvas canvas) {
                  
          double degree;
                  
          if (mIsRTandLB) {
                      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 = (float25 * 1.414 * Math.cos(degree);
                  
          double d2 = (float25 * 1.414 * Math.sin(degree);
                  
          float x = (float) (mTouch.x + d1);
                  
          float y;
                  
          if (mIsRTandLB) {
                      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 (mIsRTandLB) {
                      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 (mIsRTandLB) {
                      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 - mHeight;
                  
          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);

                  
          // Log.i("hmg", "mBezierControl2.x   " + mBezierControl2.x
                  
          // + "  mBezierControl2.y  " + mBezierControl2.y);
                  mCurrentPageShadow.draw(canvas);
                  canvas.restore();
              }

              
          /**
               * Author : hmg25 Version: 1.0 Description : 繪制翻起頁背面
               
          */
              
          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 (mIsRTandLB) {
                      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);

                  mPaint.setColorFilter(mColorMatrixFilter);

                  
          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();
              }

              
          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 startAnimation(int delayMillis) {
                  
          int dx, dy;
                  
          // dx 水平方向滑動的距離,負值會使滾動向左滾動
                  
          // dy 垂直方向滑動的距離,負值會使滾動向上滾動
                  if (mCornerX > 0) {
                      dx 
          = -(int) (mWidth + mTouch.x);
                  } 
          else {
                      dx 
          = (int) (mWidth - mTouch.x + mWidth);
                  }
                  
          if (mCornerY > 0) {
                      dy 
          = (int) (mHeight - mTouch.y);
                  } 
          else {
                      dy 
          = (int) (1 - mTouch.y); // 防止mTouch.y最終變為0
                  }
                  mScroller.startScroll((
          int) mTouch.x, (int) mTouch.y, dx, dy,
                          delayMillis);
              }

              
          public void abortAnimation() {
                  
          if (!mScroller.isFinished()) {
                      mScroller.abortAnimation();
                  }
              }

              
          public boolean canDragOver() {
                  
          if (mTouchToCornerDis > mWidth / 10)
                      
          return true;
                  
          return false;
              }

              
          /**
               * Author : hmg25 Version: 1.0 Description : 是否從左邊翻向右邊
               
          */
              
          public boolean DragToRight() {
                  
          if (mCornerX > 0)
                      
          return false;
                  
          return true;
              }

          }

          /**
           *  Author :  hmg25
           *  Description :
           
          */
          package sf.hmg.turntest;

          import java.io.File;
          import java.io.IOException;
          import java.io.RandomAccessFile;
          import java.io.UnsupportedEncodingException;
          import java.nio.MappedByteBuffer;
          import java.nio.channels.FileChannel;
          import java.text.DecimalFormat;
          import java.util.Vector;

          import android.graphics.Bitmap;
          import android.graphics.Canvas;
          import android.graphics.Color;
          import android.graphics.Paint;
          import android.graphics.Paint.Align;

          public class BookPageFactory {

              
          private File book_file = null;
              
          private MappedByteBuffer m_mbBuf = null;
              
          private int m_mbBufLen = 0;
              
          private int m_mbBufBegin = 0;
              
          private int m_mbBufEnd = 0;
              
          private String m_strCharsetName = "GBK";
              
          private Bitmap m_book_bg = null;
              
          private int mWidth;
              
          private int mHeight;

              
          private Vector<String> m_lines = new Vector<String>();

              
          private int m_fontSize = 24;
              
          private int m_textColor = Color.BLACK;
              
          private int m_backColor = 0xffff9e85// 背景顏色
              private int marginWidth = 15// 左右與邊緣的距離
              private int marginHeight = 20// 上下與邊緣的距離

              
          private int mLineCount; // 每頁可以顯示的行數
              private float mVisibleHeight; // 繪制內容的寬
              private float mVisibleWidth; // 繪制內容的寬
              private boolean m_isfirstPage,m_islastPage;

              
          // private int m_nLineSpaceing = 5;

              
          private Paint mPaint;

              
          public BookPageFactory(int w, int h) {
                  
          // TODO Auto-generated constructor stub
                  mWidth = w;
                  mHeight 
          = h;
                  mPaint 
          = new Paint(Paint.ANTI_ALIAS_FLAG);
                  mPaint.setTextAlign(Align.LEFT);
                  mPaint.setTextSize(m_fontSize);
                  mPaint.setColor(m_textColor);
                  mVisibleWidth 
          = mWidth - marginWidth * 2;
                  mVisibleHeight 
          = mHeight - marginHeight * 2;
                  mLineCount 
          = (int) (mVisibleHeight / m_fontSize); // 可顯示的行數
              }

              
          public void openbook(String strFilePath) throws IOException {
                  book_file 
          = new File(strFilePath);
                  
          long lLen = book_file.length();
                  m_mbBufLen 
          = (int) lLen;
                  m_mbBuf 
          = new RandomAccessFile(book_file, "r").getChannel().map(
                          FileChannel.MapMode.READ_ONLY, 
          0, lLen);
              }
              

              
          protected byte[] readParagraphBack(int nFromPos) {
                  
          int nEnd = nFromPos;
                  
          int i;
                  
          byte b0, b1;
                  
          if (m_strCharsetName.equals("UTF-16LE")) {
                      i 
          = nEnd - 2;
                      
          while (i > 0) {
                          b0 
          = m_mbBuf.get(i);
                          b1 
          = m_mbBuf.get(i + 1);
                          
          if (b0 == 0x0a && b1 == 0x00 && i != nEnd - 2) {
                              i 
          += 2;
                              
          break;
                          }
                          i
          --;
                      }

                  } 
          else if (m_strCharsetName.equals("UTF-16BE")) {
                      i 
          = nEnd - 2;
                      
          while (i > 0) {
                          b0 
          = m_mbBuf.get(i);
                          b1 
          = m_mbBuf.get(i + 1);
                          
          if (b0 == 0x00 && b1 == 0x0a && i != nEnd - 2) {
                              i 
          += 2;
                              
          break;
                          }
                          i
          --;
                      }
                  } 
          else {
                      i 
          = nEnd - 1;
                      
          while (i > 0) {
                          b0 
          = m_mbBuf.get(i);
                          
          if (b0 == 0x0a && i != nEnd - 1) {
                              i
          ++;
                              
          break;
                          }
                          i
          --;
                      }
                  }
                  
          if (i < 0)
                      i 
          = 0;
                  
          int nParaSize = nEnd - i;
                  
          int j;
                  
          byte[] buf = new byte[nParaSize];
                  
          for (j = 0; j < nParaSize; j++) {
                      buf[j] 
          = m_mbBuf.get(i + j);
                  }
                  
          return buf;
              }


              
          // 讀取上一段落
              protected byte[] readParagraphForward(int nFromPos) {
                  
          int nStart = nFromPos;
                  
          int i = nStart;
                  
          byte b0, b1;
                  
          // 根據編碼格式判斷換行
                  if (m_strCharsetName.equals("UTF-16LE")) {
                      
          while (i < m_mbBufLen - 1) {
                          b0 
          = m_mbBuf.get(i++);
                          b1 
          = m_mbBuf.get(i++);
                          
          if (b0 == 0x0a && b1 == 0x00) {
                              
          break;
                          }
                      }
                  } 
          else if (m_strCharsetName.equals("UTF-16BE")) {
                      
          while (i < m_mbBufLen - 1) {
                          b0 
          = m_mbBuf.get(i++);
                          b1 
          = m_mbBuf.get(i++);
                          
          if (b0 == 0x00 && b1 == 0x0a) {
                              
          break;
                          }
                      }
                  } 
          else {
                      
          while (i < m_mbBufLen) {
                          b0 
          = m_mbBuf.get(i++);
                          
          if (b0 == 0x0a) {
                              
          break;
                          }
                      }
                  }
                  
          int nParaSize = i - nStart;
                  
          byte[] buf = new byte[nParaSize];
                  
          for (i = 0; i < nParaSize; i++) {
                      buf[i] 
          = m_mbBuf.get(nFromPos + i);
                  }
                  
          return buf;
              }

              
          protected Vector<String> pageDown() {
                  String strParagraph 
          = "";
                  Vector
          <String> lines = new Vector<String>();
                  
          while (lines.size() < mLineCount && m_mbBufEnd < m_mbBufLen) {
                      
          byte[] paraBuf = readParagraphForward(m_mbBufEnd); // 讀取一個段落
                      m_mbBufEnd += paraBuf.length;
                      
          try {
                          strParagraph 
          = new String(paraBuf, m_strCharsetName);
                      } 
          catch (UnsupportedEncodingException e) {
                          
          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }
                      String strReturn 
          = "";
                      
          if (strParagraph.indexOf("\r\n"!= -1) {
                          strReturn 
          = "\r\n";
                          strParagraph 
          = strParagraph.replaceAll("\r\n""");
                      } 
          else if (strParagraph.indexOf("\n"!= -1) {
                          strReturn 
          = "\n";
                          strParagraph 
          = strParagraph.replaceAll("\n""");
                      }

                      
          if (strParagraph.length() == 0) {
                          lines.add(strParagraph);
                      }
                      
          while (strParagraph.length() > 0) {
                          
          int nSize = mPaint.breakText(strParagraph, true, mVisibleWidth,
                                  
          null);
                          lines.add(strParagraph.substring(
          0, nSize));
                          strParagraph 
          = strParagraph.substring(nSize);
                          
          if (lines.size() >= mLineCount) {
                              
          break;
                          }
                      }
                      
          if (strParagraph.length() != 0) {
                          
          try {
                              m_mbBufEnd 
          -= (strParagraph + strReturn)
                                      .getBytes(m_strCharsetName).length;
                          } 
          catch (UnsupportedEncodingException e) {
                              
          // TODO Auto-generated catch block
                              e.printStackTrace();
                          }
                      }
                  }
                  
          return lines;
              }

              
          protected void pageUp() {
                  
          if (m_mbBufBegin < 0)
                      m_mbBufBegin 
          = 0;
                  Vector
          <String> lines = new Vector<String>();
                  String strParagraph 
          = "";
                  
          while (lines.size() < mLineCount && m_mbBufBegin > 0) {
                      Vector
          <String> paraLines = new Vector<String>();
                      
          byte[] paraBuf = readParagraphBack(m_mbBufBegin);
                      m_mbBufBegin 
          -= paraBuf.length;
                      
          try {
                          strParagraph 
          = new String(paraBuf, m_strCharsetName);
                      } 
          catch (UnsupportedEncodingException e) {
                          
          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }
                      strParagraph 
          = strParagraph.replaceAll("\r\n""");
                      strParagraph 
          = strParagraph.replaceAll("\n""");

                      
          if (strParagraph.length() == 0) {
                          paraLines.add(strParagraph);
                      }
                      
          while (strParagraph.length() > 0) {
                          
          int nSize = mPaint.breakText(strParagraph, true, mVisibleWidth,
                                  
          null);
                          paraLines.add(strParagraph.substring(
          0, nSize));
                          strParagraph 
          = strParagraph.substring(nSize);
                      }
                      lines.addAll(
          0, paraLines);
                  }
                  
          while (lines.size() > mLineCount) {
                      
          try {
                          m_mbBufBegin 
          += lines.get(0).getBytes(m_strCharsetName).length;
                          lines.remove(
          0);
                      } 
          catch (UnsupportedEncodingException e) {
                          
          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }
                  }
                  m_mbBufEnd 
          = m_mbBufBegin;
                  
          return;
              }

              
          protected void prePage() throws IOException {
                  
          if (m_mbBufBegin <= 0) {
                      m_mbBufBegin 
          = 0;
                      m_isfirstPage
          =true;
                      
          return;
                  }
          else m_isfirstPage=false;
                  m_lines.clear();
                  pageUp();
                  m_lines 
          = pageDown();
              }

              
          public void nextPage() throws IOException {
                  
          if (m_mbBufEnd >= m_mbBufLen) {
                      m_islastPage
          =true;
                      
          return;
                  }
          else m_islastPage=false;
                  m_lines.clear();
                  m_mbBufBegin 
          = m_mbBufEnd;
                  m_lines 
          = pageDown();
              }

              
          public void onDraw(Canvas c) {
                  
          if (m_lines.size() == 0)
                      m_lines 
          = pageDown();
                  
          if (m_lines.size() > 0) {
                      
          if (m_book_bg == null)
                          c.drawColor(m_backColor);
                      
          else
                          c.drawBitmap(m_book_bg, 
          00null);
                      
          int y = marginHeight;
                      
          for (String strLine : m_lines) {
                          y 
          += m_fontSize;
                          c.drawText(strLine, marginWidth, y, mPaint);
                      }
                  }
                  
          float fPercent = (float) (m_mbBufBegin * 1.0 / m_mbBufLen);
                  DecimalFormat df 
          = new DecimalFormat("#0.0");
                  String strPercent 
          = df.format(fPercent * 100+ "%";
                  
          int nPercentWidth = (int) mPaint.measureText("999.9%"+ 1;
                  c.drawText(strPercent, mWidth 
          - nPercentWidth, mHeight - 5, mPaint);
              }

              
          public void setBgBitmap(Bitmap BG) {
                  m_book_bg 
          = BG;
              }
              
              
          public boolean isfirstPage() {
                  
          return m_isfirstPage;
              }
              
          public boolean islastPage() {
                  
          return m_islastPage;
              }
          }

          package sf.hmg.turntest;

          import java.io.IOException;

          import android.app.Activity;
          import android.graphics.Bitmap;
          import android.graphics.BitmapFactory;
          import android.graphics.Canvas;
          import android.graphics.Paint;
          import android.os.Bundle;
          import android.view.MotionEvent;
          import android.view.View;
          import android.view.View.OnTouchListener;
          import android.view.Window;
          import android.view.WindowManager;
          import android.widget.Toast;

          public class turntest extends Activity {
              
          /** Called when the activity is first created. */
              
          private PageWidget mPageWidget;
              Bitmap mCurPageBitmap, mNextPageBitmap;
              Canvas mCurPageCanvas, mNextPageCanvas;
              BookPageFactory pagefactory;

              @Override
              
          public void onCreate(Bundle savedInstanceState) {
                  
          super.onCreate(savedInstanceState);
                  requestWindowFeature(Window.FEATURE_NO_TITLE);
                  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                          WindowManager.LayoutParams.FLAG_FULLSCREEN);
                  mPageWidget 
          = new PageWidget(this);
                  setContentView(mPageWidget);

                  mCurPageBitmap 
          = Bitmap.createBitmap(480800, Bitmap.Config.ARGB_8888);
                  mNextPageBitmap 
          = Bitmap
                          .createBitmap(
          480800, Bitmap.Config.ARGB_8888);

                  mCurPageCanvas 
          = new Canvas(mCurPageBitmap);
                  mNextPageCanvas 
          = new Canvas(mNextPageBitmap);
                  pagefactory 
          = new BookPageFactory(480800);

                  pagefactory.setBgBitmap(BitmapFactory.decodeResource(
                          
          this.getResources(), R.drawable.bg));

                  
          try {
                      pagefactory.openbook(
          "/sdcard/test.txt");
                      pagefactory.onDraw(mCurPageCanvas);
                  } 
          catch (IOException e1) {
                      
          // TODO Auto-generated catch block
                      e1.printStackTrace();
                      Toast.makeText(
          this"電子書不存在,請將《test.txt》放在SD卡根目錄下",
                              Toast.LENGTH_SHORT).show();
                  }

                  mPageWidget.setBitmaps(mCurPageBitmap, mCurPageBitmap);

                  mPageWidget.setOnTouchListener(
          new OnTouchListener() {
                      @Override
                      
          public boolean onTouch(View v, MotionEvent e) {
                          
          // TODO Auto-generated method stub
                          
                          
          boolean ret=false;
                          
          if (v == mPageWidget) {
                              
          if (e.getAction() == MotionEvent.ACTION_DOWN) {
                                  mPageWidget.abortAnimation();
                                  mPageWidget.calcCornerXY(e.getX(), e.getY());

                                  pagefactory.onDraw(mCurPageCanvas);
                                  
          if (mPageWidget.DragToRight()) {
                                      
          try {
                                          pagefactory.prePage();
                                      } 
          catch (IOException e1) {
                                          
          // TODO Auto-generated catch block
                                          e1.printStackTrace();
                                      }                        
                                      
          if(pagefactory.isfirstPage())return false;
                                      pagefactory.onDraw(mNextPageCanvas);
                                  } 
          else {
                                      
          try {
                                          pagefactory.nextPage();
                                      } 
          catch (IOException e1) {
                                          
          // TODO Auto-generated catch block
                                          e1.printStackTrace();
                                      }
                                      
          if(pagefactory.islastPage())return false;
                                      pagefactory.onDraw(mNextPageCanvas);
                                  }
                                  mPageWidget.setBitmaps(mCurPageBitmap, mNextPageBitmap);
                              }
                           
                               ret 
          = mPageWidget.doTouchEvent(e);
                              
          return ret;
                          }
                          
          return false;
                      }

                  });
              }
          }
          posted on 2011-09-21 11:59 SIMONE 閱讀(11112) 評論(2)  編輯  收藏 所屬分類: android

          FeedBack:
          # re: android酷炫翻頁效果+圖形分析
          2011-11-19 15:19 | veallytong
          轉人家的有什么意思?  回復  更多評論
            
          # re: android酷炫翻頁效果+圖形分析[未登錄]
          2015-04-21 14:58 | 123
          @veallytong
          看不出來你自己的分析在哪里。。。。。。。。  回復  更多評論
            
          主站蜘蛛池模板: 和田市| 额尔古纳市| 筠连县| 蓝田县| 阿坝县| 苏尼特右旗| 康乐县| 阿鲁科尔沁旗| 罗平县| 贵德县| 三都| 南宫市| 刚察县| 东丽区| 桃园市| 毕节市| 南澳县| 黄浦区| 达日县| 新晃| 南木林县| 兴宁市| 庄河市| 阿坝| 柘荣县| 镶黄旗| 邵阳市| 莆田市| 福贡县| 清水河县| 永州市| 盐池县| 阜新市| 乐山市| 肃南| 滦南县| 南康市| 永城市| 田林县| 慈利县| 东安县|