Android翻頁效果—電子書 – Android移動開發技術文章_手機開發 Android移動開發教學課程

先上個效果圖:


 
效果還是很不錯的,不過與ibook那個效果比起來,還是有差距的。應為這個沒用到openGL做3D效果,隻是用的2d的canvas畫佈去畫的 view,添加瞭陰影效果,還是挺有立體感的。而且比較流暢。openGL實現肯定效果會更好,不過就我目前的技術實力,實現希望還是渺茫的。
廢話少說,還是上代碼吧:
這裡需要兩個UI的view類和一個使用方法的demo 。
第一個pageTurnerView.java :

public class PageTurnerViewP1 extends RelativeLayout{
 
   private static final int CORNER_RIGHT_MASK = 1;
   private static final int CORNER_TOP_MASK = 2;
   public static final int CORNER_BOTTOM_LEFT = 0;
   public static final int CORNER_BOTTOM_RIGHT = 1;
   public static final int CORNER_TOP_LEFT = 2;
   public static final int CORNER_TOP_RIGHT = 3;
   private static final int INVALIDATE = 1;
   private static final int INITIAL_TIME_DELAY = 100;
   private static final int TIME_DELAY = 10;
//   private static final int TIME_STEPS = 30;
   private boolean mPageTurning;
   private boolean mStepping;
   public long mNextTime;
   private int mTimeStep;
   private int mDrawnTimeStep;
   private int mCorner;
   private Drawable mBackPage;
   private Drawable mPageBackground;
   private Path mForegroundPath;
   private Path mBackPagePath;
   private Path mBackgroundPath;
   private float mRotation;
   private Rect mChildRect = new Rect();
   private int mOuterOffsetX;
   private int mOuterOffsetY;
   public float mPivotX;
   private int mPageId;
   private PageViewP1 mPage;
   private PointF mPageTurnCorner = new PointF();
   private PointF mOppositeCorner = new PointF();
   private PointF mPageDim = new PointF();
   private int mStepLen = 1;
   public static final int KEEP = 0;
   public static final int NEXT = 1;
   public static final int LAST = 2;
   public int mWhere = KEEP;
   public boolean isBgInit = true;
   public boolean isBackInit = true;
   private  float ax,ay,bx,by,cx,cy,dx,dy,ex,ey,c0x,c0y;
   private int mMaxStep=30;
   public final Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {
     if (msg.what != 1) { return; }
//     PageTurnerViewP1.this.invalidate();
     refreshUI();
//     PageTurnerViewP1.this.invalidate((int)bx, (int)ay, (int)dx, (int)dy);
     if (PageTurnerViewP1.this.mStepping) { return; }
     msg = obtainMessage(1);
     long current = SystemClock.uptimeMillis();
     if (PageTurnerViewP1.this.mNextTime < current) {       //PageTurnerViewP1.access$102(PageTurnerViewP1.this, current + 10L);      PageTurnerViewP1.this.mNextTime= current + 5L;      }      sendMessageAtTime(msg, PageTurnerViewP1.this.mNextTime);      //PageTurnerViewP1.access$114(PageTurnerViewP1.this, 10L);     PageTurnerViewP1.this.mNextTime+= 5L;     }    };      public PageTurnerViewP1(Context context) {     super(context);     Log.i("==================== PageTurnerViewP1(Context context) =================", "" + this);    }    public PageTurnerViewP1(Context context, AttributeSet attrs) {     super(context, attrs);         this.mPageId = -1;    this.mCorner = -1;    }    protected void onFinishInflate() {     super.onFinishInflate();     if (this.mPageId != -1) {      this.mPage = ((PageViewP1)findViewById(this.mPageId));      if (this.mPage != null)       this.mPage.setPageTurner(this);     }    }    public void setPageId(int pageId) {     this.mPageId = pageId;     this.mPage = ((PageViewP1)findViewById(this.mPageId));     if (this.mPage != null)      this.mPage.setPageTurner(this);    }    public int getPageId() {     return this.mPageId;    }    public void setPage(PageViewP1 pageViewP1) {     this.mPage = pageViewP1;    }    public PageViewP1 getPage() {     return this.mPage;    }    public void setCorner(int corner) {     this.mCorner = corner;    }    public int getCorner() {     return this.mCorner;    }    protected void dispatchDraw(Canvas canvas) {         Log.v("log dispatchDraw:", "drawing back page"+mPageTurning); //    if ((this.mPageTurning) && (this.mPage != null) && (computePageTurn())) {     if ((computePageTurn())&& (this.mPageTurning) && (this.mPage != null) ) {      this.mPage.setClipPath(this.mForegroundPath);     }     super.dispatchDraw(canvas);     if (this.mPageTurning) {      drawBackground(canvas);      drawBackPage(canvas);            if (!updateTimeStep()) {       this.mHandler.removeMessages(1);       if (this.mPage != null) {        this.mPage.onPageTurnFinished(canvas);       }       this.mPageTurning = false;       this.mStepping = false;       invalidate();      }     }    }    public void startPageTurn(int mTimeStep) {     if ((this.mPage == null) && (this.mPageId != -1)) {      this.mPage = ((PageViewP1)findViewById(this.mPageId));     }     if (this.mPage == null) {      return;     }     this.mPage.setPageTurner(this);     Drawable d = this.mPage.getPageBackground();     if (d != null) {      this.mPageBackground = d;     }     d = this.mPage.getBackPage();     if (d != null) {      this.mBackPage = d;     }     int corner = this.mPage.getCorner();     if (corner != -1) {      this.mCorner = corner;     } //    this.mStepping=false;     this.mPageTurning = true;     this.mTimeStep = mTimeStep;     this.mDrawnTimeStep = -1;     Message msg = this.mHandler.obtainMessage(1);     this.mNextTime = (SystemClock.uptimeMillis() + 5L);     this.mHandler.sendMessageAtTime(msg, this.mNextTime);    }    public void stepPageTurn() {     if (!this.mStepping) {      this.mStepping = true;      startPageTurn(this.mTimeStep);     } else { //         refreshUI();     }    }    public void refreshUI(){     computePageTurn(); //        this.invalidate();    }    private void sendUIhandler(){     Message msg = this.mHandler.obtainMessage(1);     this.mNextTime = (SystemClock.uptimeMillis() + 30L);     this.mHandler.sendMessageAtTime(msg, this.mNextTime);    }    private boolean updateTimeStep() {     if (this.mTimeStep >mMaxStep || this.mTimeStepthis.mMaxStep)) {
    if ( (this.mTimeStep this.mMaxStep)) {
     return false;
    }
    if (this.mPage == null) {
     return false;
    }
    this.mDrawnTimeStep = this.mTimeStep;
    View child = this.mPage.getChildAt(0);
    child.getDrawingRect(this.mChildRect);
//    this.mOuterOffsetX = (child.getLeft() – getLeft());
//    this.mOuterOffsetY = (child.getTop() – getTop());
    this.mOuterOffsetX = 0;
    this.mOuterOffsetY = 0;
 
    float width = this.mChildRect.right;
    float height = this.mChildRect.bottom;
    if(!mStepping){
     this.mPivotX = (this.mTimeStep / 30.0f * width);
    }
    this.mForegroundPath = new Path();
    this.mBackPagePath = new Path();
    this.mBackgroundPath = new Path();
    float slope = width / (this.mPivotX – width);
    float y = this.mPivotX * slope;
 
    this.mPageTurnCorner.x = 0.0F;
    this.mPageTurnCorner.y = height;
    this.mOppositeCorner.x = width;
    this.mOppositeCorner.y = 0.0F;
    float x0 = this.mPivotX;
    float cornerIntersect = height * width / (height + width);
    if ((this.mCorner & 0x1) != 0) {
     this.mPageTurnCorner.x = width;
     this.mOppositeCorner.x = 0.0F;
     x0 = width – x0;
    }
 
    if ((this.mCorner & 0x2) != 0) {
     this.mPageTurnCorner.y = 0.0F;
     this.mOppositeCorner.y = height;
    }
 
    this.mPageDim.x = width;
    this.mPageDim.y = height;
    float page_slope;
 
    if (this.mPivotX 2){
   LinearGradient grad = new LinearGradient(
     ex,ey,ex+(dx-ex)/4,ey+(dy-ey)/4,R.color.gray3,Color.TRANSPARENT,Shader.TileMode.CLAMP);
   Paint p=new Paint();
      p.setShader(grad);
//      p.setAlpha(120);
      canvas.drawPath(this.mBackgroundPath,p);
      //end test
     }
    canvas.restore();
 
   }
 
   private void drawBackPage(Canvas canvas) {
    float width = this.mChildRect.right;
    float height = this.mChildRect.bottom;
    canvas.save();
//    canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));
    canvas.clipPath(this.mBackPagePath, Region.Op.INTERSECT);
    float xShift = 2.0F * this.mPivotX – width;
    float xRotate = width – this.mPivotX;
    float yRotate = height;
    if ((this.mCorner & 0x1) != 0) {
     xShift = width – 2.0F * this.mPivotX;
     xRotate = this.mPivotX;
    }
    if ((this.mCorner & 0x2) != 0) {
     yRotate = 0.0F;
    }
    canvas.translate(this.mOuterOffsetX + xShift, this.mOuterOffsetY);
    canvas.rotate(this.mRotation, xRotate, yRotate);
 
    //畫原本的背面
    if (this.mBackPage != null) {
     this.mBackPage.setBounds(0, 0, this.mChildRect.right, this.mChildRect.bottom);
     this.mBackPage.draw(canvas);
    }
    //畫回調函數中的畫背面
    if (this.mPage != null) {
    Log.v("log2 drawBackPage2:", "drawing back page");
     this.mPage.drawBackPage(canvas);
    }
 
    canvas.restore();
    canvas.save();
//
      LinearGradient grad = new LinearGradient(
     ex,ey,ex-(ex-bx)/4,ey-(ey-by)/4,R.color.gray3,0xC9C9C9,Shader.TileMode.CLAMP);
   Paint p=new Paint();
      p.setShader(grad);
//      p.setAlpha(120);
      canvas.drawPath(this.mBackPagePath,p);
      canvas.restore();
      //中間陰影問題,起點藍色-》 白色-》 藍色終點,這樣起點前和終點後的區域也為藍色瞭。
      canvas.save();
//      canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));
      LinearGradient grad1 = new LinearGradient(
        ex-(ex-bx)/4,ey-(ey-by)/4,bx,by,0xC9C9C9,R.color.gray3,Shader.TileMode.CLAMP);
   Paint p1=new Paint();
   p1.setShader(grad1);
//   p1.setAlpha(120);
      canvas.drawPath(this.mBackPagePath,p1);
      canvas.restore();
//    
 
   }
 
   public int getmTimeStep(){
 
    return mTimeStep;
   }
   public void setmTimeStep(int mTimeStep ){
 
    this.mTimeStep= mTimeStep;
   }
   public boolean getmStepping(){
 
    return mStepping;
   }
   public void setmStepping(boolean mStepping ){
 
    this.mStepping= mStepping;
   }
 
   public void setmStepLen(int mStepLen){
    this.mStepLen=mStepLen;
   }
   public int getmStepLen(){
    return this.mStepLen;
   }
 
   public void setmMaxStep(int mMaxStep){
    this.mMaxStep=mMaxStep;
   }
   public int getmMaxStep(){
    return this.mMaxStep;
   }
 
 public void setPreStart(int where)
 {
  switch (where)
  {
   case NEXT:
   case LAST:
    mWhere = where;
    break;
 
   default:
    mWhere = KEEP;
    break;
  }
 
  isBgInit = true;
  isBackInit = true;
 
 }
 
}

 
第二個view類pageView.java :
public

 class

 PageViewP1 extends

 RelativeLayout {


 public

 static

 final

 int

 CORNER_BOTTOM_LEFT =

 0

;


 public

 static

 final

 int

 CORNER_BOTTOM_RIGHT =

 1

;


 public

 static

 final

 int

 CORNER_TOP_LEFT =

 2

;


 public

 static

 final

 int

 CORNER_TOP_RIGHT =

 3

;


 private

 Path mClipPath;


 private

 PageTurnerViewP1 mPageTurner;


 private

 Callback mCallback;


 private

 int

 mCorner;


 private

 Drawable mBackPage;


 private

 Drawable mPageBackground;


 
 public

 PageViewP1(

Context

 context)

 {


  super

(

context)

;


 }


 
 public

 PageViewP1(

Context

 context, AttributeSet

 attrs )

 {


  super

(

context, attrs )

;


 
  this

.mBackPage

 =

this

.getBackground

(

)

;


  this

.mCorner

 =

 –

1

;


 }


 
 void

 setPageTurner(

PageTurnerViewP1 pageTurnerViewP1)

 {


  this

.mPageTurner

 =

 pageTurnerViewP1;


 }


 
 void

 setClipPath(

Path clipPath)

 {


  this

.mClipPath

 =

 clipPath;


 }


 
 public

 void

 setCallback(

Callback callback)

  {


  this

.mCallback

 =

 callback;


 }


 
 void

 drawBackPage(

Canvas

 canvas)

 {


    if

 (

this

.mCallback

 !=

 null

)


     this

.mCallback

.onDrawBackPage

(

canvas)

;


 }


 
 void

 drawBackground(

Canvas

 canvas)

 {


  if

 (

this

.mCallback

 !=

 null

)


   this

.mCallback

.onDrawBackground

(

canvas)

;


 }


 
 public

 void

 startPageTurn(

)

 {


  if

 (

this

.mPageTurner

 !=

 null

)


   this

.mPageTurner

.startPageTurn

(

0

)

;


 }


 
 void

 onPageTurnFinished(

Canvas

 canvas)

 {


  this

.mCallback

.onPageTurnFinished

(

canvas)

;


  this

.mClipPath

 =

 null

;


 }


 
 protected

 void

 dispatchDraw(

Canvas

 canvas)

 {


  if

 (

this

.mClipPath

 !=

 null

)

 {


   canvas.save

(

)

;


   canvas.clipPath

(

this

.mClipPath

, Region.Op

.INTERSECT

)

;


  }


  super

.dispatchDraw

(

canvas)

;


  if

 (

this

.mClipPath

 !=

 null

)


   canvas.restore

(

)

;


 }


 
 public

 void

 setCorner(

int

 corner)

 {


  this

.mCorner

 =

 corner;


 }


 
 public

 int

 getCorner(

)

 {


  return

 this

.mCorner

;


 }


 
 public

 void

 setBackPage(

Drawable backPage)

 {


  this

.mBackPage

 =

 backPage;


 }


 
 public

 Drawable getBackPage(

)

 {


  return

 this

.mBackPage

;


 }


 
 public

 void

 setPageBackground(

Drawable background)

 {


  this

.mPageBackground

 =

 background;


 }


 
 public

 Drawable getPageBackground(

)

 {


  return

 this

.mPageBackground

;


 }


 
 public

 static

 abstract

 class

 Callback {


  public

 void

 onDrawBackPage(

Canvas

 canvas)

 {


   Log.v

(

"Callback"

, "drawing back page"

)

;


  }


  public

 void

 onDrawBackground(

Canvas

 canvas)

 {


   Log.v

(

"Callback2"

, "drawing back page"

)

;


  }


  public

 void

 onPageTurnFinished(

Canvas

 canvas)

 {


   Log.v

(

"Callback3"

, "drawing back page"

)

;


  }


 }


}

發佈留言