android酷炫翻页效果+图形分析

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 StringTAG = " hmg " ;
private int mWidth = 480 ;
private int mHeight = 800 ;
private int mCornerX = 0 ; // 拖拽点对应的页脚
private int mCornerY = 0 ;
private PathmPath0;
private PathmPath1;
BitmapmCurPageBitmap
= null ; // 当前页
BitmapmNextPageBitmap = null ;

PointFmTouch
= new PointF(); // 拖拽点
PointFmBezierStart1 = new PointF(); // 贝塞尔曲线起始点
PointFmBezierControl1 = new PointF(); // 贝塞尔曲线控制点
PointFmBeziervertex1 = new PointF(); // 贝塞尔曲线顶点
PointFmBezierEnd1 = new PointF(); // 贝塞尔曲线结束点

PointFmBezierStart2
= new PointF(); // 另一条贝塞尔曲线
PointFmBezierControl2 = new PointF();
PointFmBeziervertex2
= new PointF();
PointFmBezierEnd2
= new PointF();

float mMiddleX;
float mMiddleY;
float mDegrees;
float mTouchToCornerDis;
ColorMatrixColorFiltermColorMatrixFilter;
MatrixmMatrix;
float []mMatrixArray = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1.0f };

boolean mIsRTandLB; // 是否属于右上左下
float mMaxLength = ( float )Math.hypot(mWidth,mHeight);
int []mBackShadowColors;
int []mFrontShadowColors;
GradientDrawablemBackShadowDrawableLR;
GradientDrawablemBackShadowDrawableRL;
GradientDrawablemFolderShadowDrawableLR;
GradientDrawablemFolderShadowDrawableRL;

GradientDrawablemFrontShadowDrawableHBT;
GradientDrawablemFrontShadowDrawableHTB;
GradientDrawablemFrontShadowDrawableVLR;
GradientDrawablemFrontShadowDrawableVRL;

PaintmPaint;

ScrollermScroller;

public PageWidget(Contextcontext){
super (context);
// TODOAuto-generatedconstructorstub
mPath0 = new Path();
mPath1
= new Path();
createDrawable();

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

ColorMatrixcm
= new ColorMatrix();
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 };
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:hmg25Version:1.0Description:计算拖拽点对应的拖拽脚
*/
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(MotionEventevent){
// TODOAuto-generatedmethodstub
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();
}
// returnsuper.onTouchEvent(event);
return true ;
}

/**
*Author:hmg25Version:1.0Description:求解直线P1P2和直线P3P4的交点坐标
*/
public PointFgetCross(PointFP1,PointFP2,PointFP3,PointFP4){
PointFCrossP
= 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(Canvascanvas,Bitmapbitmap,Pathpath){
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,
0 , 0 , null );
canvas.restore();
}

private void drawNextPageAreaAndShadow(Canvascanvas,Bitmapbitmap){
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;
GradientDrawablemBackShadowDrawable;
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,
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 setBitmaps(Bitmapbm1,Bitmapbm2){
mCurPageBitmap
= bm1;
mNextPageBitmap
= bm2;
}

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

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

/**
*Author:hmg25Version:1.0Description:创建阴影的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);

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

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

/**
*Author:hmg25Version:1.0Description:绘制翻起页的阴影
*/
public void drawCurrentPageShadow(Canvascanvas){
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 = ( 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 (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;
GradientDrawablemCurrentPageShadow;
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:hmg25Version:1.0Description:绘制翻起页背面
*/
private void drawCurrentBackArea(Canvascanvas,Bitmapbitmap){
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();
GradientDrawablemFolderShadowDrawable;
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:hmg25Version:1.0Description:是否从左边翻向右边
*/
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 Filebook_file = null ;
private MappedByteBufferm_mbBuf = null ;
private int m_mbBufLen = 0 ;
private int m_mbBufBegin = 0 ;
private int m_mbBufEnd = 0 ;
private Stringm_strCharsetName = " GBK " ;
private Bitmapm_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;

// privateintm_nLineSpaceing=5;

private PaintmPaint;

public BookPageFactory( int w, int h){
// TODOAuto-generatedconstructorstub
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(StringstrFilePath) 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(){
StringstrParagraph
= "" ;
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 (UnsupportedEncodingExceptione){
// TODOAuto-generatedcatchblock
e.printStackTrace();
}
StringstrReturn
= "" ;
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 (UnsupportedEncodingExceptione){
// TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
}
return lines;
}

protected void pageUp(){
if (m_mbBufBegin < 0 )
m_mbBufBegin
= 0 ;
Vector
< String > lines = new Vector < String > ();
StringstrParagraph
= "" ;
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 (UnsupportedEncodingExceptione){
// TODOAuto-generatedcatchblock
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 (UnsupportedEncodingExceptione){
// TODOAuto-generatedcatchblock
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(Canvasc){
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,
0 , 0 , null );
int y = marginHeight;
for (StringstrLine:m_lines){
y
+= m_fontSize;
c.drawText(strLine,marginWidth,y,mPaint);
}
}
float fPercent = ( float )(m_mbBufBegin * 1.0 / m_mbBufLen);
DecimalFormatdf
= new DecimalFormat( " #0.0 " );
StringstrPercent
= df.format(fPercent * 100 ) + " % " ;
int nPercentWidth = ( int )mPaint.measureText( " 999.9% " ) + 1 ;
c.drawText(strPercent,mWidth
- nPercentWidth,mHeight - 5 ,mPaint);
}

public void setBgBitmap(BitmapBG){
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{
/** Calledwhentheactivityisfirstcreated. */
private PageWidgetmPageWidget;
BitmapmCurPageBitmap,mNextPageBitmap;
CanvasmCurPageCanvas,mNextPageCanvas;
BookPageFactorypagefactory;

@Override
public void onCreate(BundlesavedInstanceState){
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( 480 , 800 ,Bitmap.Config.ARGB_8888);
mNextPageBitmap
= Bitmap
.createBitmap(
480 , 800 ,Bitmap.Config.ARGB_8888);

mCurPageCanvas
= new Canvas(mCurPageBitmap);
mNextPageCanvas
= new Canvas(mNextPageBitmap);
pagefactory
= new BookPageFactory( 480 , 800 );

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

try {
pagefactory.openbook(
" /sdcard/test.txt " );
pagefactory.onDraw(mCurPageCanvas);
}
catch (IOExceptione1){
// TODOAuto-generatedcatchblock
e1.printStackTrace();
Toast.makeText(
this , " 电子书不存在,请将《test.txt》放在SD卡根目录下 " ,
Toast.LENGTH_SHORT).show();
}

mPageWidget.setBitmaps(mCurPageBitmap,mCurPageBitmap);

mPageWidget.setOnTouchListener(
new OnTouchListener(){
@Override
public boolean onTouch(Viewv,MotionEvente){
// TODOAuto-generatedmethodstub

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 (IOExceptione1){
// TODOAuto-generatedcatchblock
e1.printStackTrace();
}
if (pagefactory.isfirstPage()) return false ;
pagefactory.onDraw(mNextPageCanvas);
}
else {
try {
pagefactory.nextPage();
}
catch (IOExceptione1){
// TODOAuto-generatedcatchblock
e1.printStackTrace();
}
if (pagefactory.islastPage()) return false ;
pagefactory.onDraw(mNextPageCanvas);
}
mPageWidget.setBitmaps(mCurPageBitmap,mNextPageBitmap);
}

ret
= mPageWidget.doTouchEvent(e);
return ret;
}
return false ;
}

});
}
}

更多相关文章

  1. Android(安卓)三角标签(自定义Textview控件)
  2. android 图形开发实例
  3. Android直播系统平台搭建之图片实现阴影效果的方法小结
  4. Android实现图表绘制和展示
  5. Android之——自己定义TextView
  6. Android绘图之绘制太极图
  7. Android(安卓)中的 OpenGL 简单入门 (下)
  8. Android(安卓)开发Rect
  9. Android(安卓)Drawable

随机推荐

  1. Android中Dialog
  2. Android平台架构介绍和源码下载
  3. Qt on Android: Qt 5.3.0 发布,针对 Andro
  4. Android入门(4) 布局、JUnit、日志与数据
  5. Android(安卓)NDK 开发教程一:安装NDK
  6. Android(安卓)PreferenceActivity介绍
  7. 【android】GridView几个比较实用的属性
  8. Android中程序与Service交互的方式
  9. Android(安卓)开发艺术探索笔记(十五) 之 A
  10. eclipse下安装android 插件过程