Android看书软件之零点一层功力——翻页效果01

看书软件都会有很炫的翻页效果。一个好的看书软件,我想,它必须具备这些基本功能:

1、下载书籍

2、直接读取txt文件的内容

3、智能排版

4、智能计算出页数,看书进度

5、绚丽的翻页效果

6、可以拖动翻页和点击翻页

7、可以向前翻页,也可以向后翻页

8、书签功能

9、夜间模式

10、页面背景切换(如粉红浪漫背景,羊皮纸背景,蓝色夜空背景、护目背景等)


我从翻页效果开始研究。

这是第一个翻页效果的demo,非常的简单,只有二个功能:

1、手拖动页面实现垂直翻页

2、点击自动向前翻页和向后翻页


截图:

Android看书软件之零点一层功力——翻页效果01_第1张图片 Android看书软件之零点一层功力——翻页效果01_第2张图片


这个例子翻页的原理很简单,实际上就是在屏幕上绘制三个部分的图片:最上层页的正面部分,上层页的背面部分,底层页的正面部分。当然,因为拖动和自动翻的原因,有些部分显示有些部分不显示,如此就形成了翻页的效果。


代码如下:

入口Activity:MyPageTurnDemo01Activity,它就像一个容器装着PageView

/**
 * 翻页效果的第一个demo
 * @author haozi
 *
 */
public class MyPageTurnDemo01Activity extends Activity {

	private MyPageView mPageView;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // 初始化View
        initMyPageView();
        // 设置界面布局
        setContentView(mPageView);
    }
    
    /**
     * 初始化View
     */
    private void initMyPageView(){
    	
    	Display display = getWindowManager().getDefaultDisplay();
    	int width = display.getWidth();
    	int height = display.getHeight();
    	mPageView = new MyPageView(this, width, height);
    }
}

最重要的PageView,就是在这里动态显示翻页效果的

/**
 * 在上面显示一页一页的翻页
 * @author haozi
 *
 */
public class MyPageView extends View {
	
	private Context context;
	private Bitmap foreBitmap;
	private Bitmap backBitmap;
	private Bitmap foreBitmapBack;
	private int width;
	private int height;
	
	private Paint mPaint;                                      // 画笔
	private PointF touchPointer;                               // 触摸点
	private PointF movePointer;
	private GradientDrawable gradientDrawableRL;               // 阴影从右到左渐变
	private GradientDrawable gradientDrawableLR;               // 阴影从左到右渐变
	private Scroller mScroller;                                // 滚动器
	
	private boolean flag;
	/**
	 * 构造方法
	 * @param context 调用方的上下文
	 * @param width 设备的宽度,单位是像素
	 * @param height 设备的高度,单位是像素
	 */
	public MyPageView(Context context, int width, int height) {
		super(context);
		this.context = context;
		this.width = width;
		this.height = height;
		// 初始化一些必须品
		initSomething();
		// 初始化第一张和第二张的页面
		initForeAndBackPages();
	}

	public MyPageView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}

	public MyPageView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}
	
	/**
	 * 初始化画笔工具
	 */
	private void initSomething(){
		
		// 点击时候View能够获取焦点
		setFocusableInTouchMode(true);
		
		// 初始化画笔
		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		
		// 初始化触摸点
		touchPointer = new PointF();
		movePointer = new PointF();
		
		// 初始化阴影渐变,由亮到暗
		int[] gradientColor = new int[]{0x00333333, 0xb0333333};
		gradientDrawableLR = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, gradientColor);
		gradientDrawableRL = new GradientDrawable(GradientDrawable.Orientation.RIGHT_LEFT, gradientColor);
		
		// 初始化滚动器,利用滚动条来实现接触点放开后的动画效果
		mScroller = new Scroller(context);
	}
	
	/**
	 * 初始化第一张和第二张的页面
	 */
	private void initForeAndBackPages(){
		
		// 第一张页面
		Bitmap firstBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.first_page);
		foreBitmap = Bitmap.createScaledBitmap(firstBitmap, width, height, false);
		// 第二张页面
		Bitmap secondBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.second_page);
		backBitmap = Bitmap.createScaledBitmap(secondBitmap, width, height, false);		
		// 翻页的背面
		Matrix m = new Matrix();
		m.preScale(-1, 1);
		foreBitmapBack = Bitmap.createBitmap(foreBitmap, 0, 0, foreBitmap.getWidth(), foreBitmap.getHeight(), m, true);
	}
	
	@Override
	public void computeScroll() {
		
		if(mScroller.computeScrollOffset()){
			movePointer.set(mScroller.getCurrX(), mScroller.getCurrY());
			postInvalidate();
		}
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		
		// 设置画笔,无锯齿
		Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
		// 画前一页
		canvas.drawBitmap(foreBitmap, 0, 0, mPaint);
		
		if(flag){// 触碰屏幕了
			// 计算出对折点
			float halfCut = movePointer.x + (width - movePointer.x)*4/10;

			// 画翻页的背面
			canvas.save();
			canvas.clipRect(movePointer.x, 0, halfCut, height);
			paint.setColorFilter(null);
			canvas.drawBitmap(foreBitmapBack, movePointer.x, 0, paint);
			canvas.restore();
			
			// 画后一页翻开露出的部分
			canvas.save();
			canvas.clipRect(0, 0, halfCut, height);
			canvas.clipRect(halfCut, 0, width, height, Region.Op.REVERSE_DIFFERENCE);
			paint.setColorFilter(null);
			canvas.drawBitmap(backBitmap, 0, 0, paint);
			canvas.restore();
			
			// 画出翻页对折处投下的阴影
			// 对折处画左侧阴影
			if((halfCut - movePointer.x) > 70){
				gradientDrawableLR.setBounds((int)halfCut-70, 0, (int)halfCut, (int)height);
			}else{
				gradientDrawableLR.setBounds((int)movePointer.x, 0, (int)halfCut, (int)height);
			}
			gradientDrawableLR.draw(canvas);
			// 对折处画右侧阴影
			if((halfCut - movePointer.x) > 30){
				gradientDrawableRL.setBounds((int)halfCut, 0, (int)halfCut + 30, (int)height);
			}else{
				gradientDrawableRL.setBounds((int)halfCut, 0, (int)(2*halfCut - movePointer.x), (int)height);
			}
			gradientDrawableRL.draw(canvas);
		}	
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		
		if(event.getAction() == MotionEvent.ACTION_DOWN){
			
			flag = true;
			// 得到点击屏幕按下时候的触摸点坐标
			touchPointer.x = event.getX();
			touchPointer.y = event.getY();
			
		}else if(event.getAction() == MotionEvent.ACTION_MOVE){
			
			// 得到点击屏幕按下时候的触摸点坐标
			float x = event.getX();
			float y = event.getY();
			movePointer.set(x, y);
			movePointer.set(x, y);
			postInvalidate();
			
		}else if(event.getAction() == MotionEvent.ACTION_UP){
			
			float endX = event.getX();
			float endY = event.getY();
			if(touchPointer.x > endX){ // 向左翻页
				mScroller.startScroll((int)movePointer.x, (int)movePointer.y, (int)(-width-movePointer.x), 0, 1000);
			}else if(touchPointer.x < endX){ // 向右翻页
				mScroller.startScroll((int)movePointer.x, (int)movePointer.y, (int)(width-movePointer.x), 0, 1000);
			}else if(touchPointer.x == endX && touchPointer.y == endY){// 点击翻页
				if(touchPointer.x < width/2){// 向右翻
					mScroller.startScroll((int)-width, (int)touchPointer.y, (int)2*width, 0, 1000);
				}else{// 向左翻
					mScroller.startScroll((int)width, (int)touchPointer.y, (int)-2*width, 0, 1000);
				}
			}
			postInvalidate();
		}
		
		return true;
	}
}

对于这个例子,需要熟悉的技术是:View   clip    明暗渐变的画法   负责自动滚动的Scroller   postInvalidate




你可能感兴趣的:(android,null,Class,float,Constructor,Matrix)