安卓仿iphone-ibooks的反转视图特效

iphone-ibooks的书橱界面和商城界面是两个背靠背的视图,可以通过左右伪3D旋转切换前后界面,我现在写了一个安卓版本的rollbackview,效果如下:

如下:

源代码如下:

import android.content.Context;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.Scroller;

public class rollbackview extends RelativeLayout{
     Context mContext;int mwidth,mheight,zdistance;float radius;Scroller ms;
     Camera mc;Matrix mm;float lastx,lasty;Boolean intercepyed,handled,hadcharged;
    View child1,child2;
     View aboveview,startView;
	public rollbackview(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO 自动生成的构造函数存根
		mContext=context;intercepyed=false;handled=false;hadcharged=false;
		ms=new Scroller(context);
		mc=new Camera();mm=new Matrix();
	}
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		// TODO 自动生成的方法存根
		
		if(ev.getAction()==0){lastx=ev.getX();lasty=ev.getY();intercepyed=false;hadcharged=false;handled=false;startView=aboveview;}
		if(ev.getAction()==2){float movex=ev.getX();float movey=ev.getY();
		float offdx=movex-lastx;float dy=movey-lasty;
		if(!hadcharged){
			if(Math.abs(offdx)<10&&Math.abs(dy)<10){
				return true;
			}else{hadcharged=true;}
		}
		if(!handled){
			handled=true;
		if(Math.abs(offdx)>Math.abs(dy)){intercepyed=true;}else{
			intercepyed=false;
		}}}
		if(intercepyed){
			float offdx=ev.getX()-lastx;
			
		if(ev.getAction()==1){
			//currentView=aboveview;
			MotionEvent cancel=MotionEvent.obtain(ev);
			cancel.setAction(3);
			startView.dispatchTouchEvent(cancel);
			cancel.recycle();
			int time=(int) (mwidth/2-Math.abs((mwidth/2-Math.abs(offdx))));
			if(Math.abs(offdx)>mwidth/2){
				if(offdx<0){ms.startScroll((int)offdx, 0, -mwidth-(int)(offdx), 0, time);}else{
				ms.startScroll((int)offdx, 0, mwidth-(int)(offdx), 0, time);
			    }}
			else{
				ms.startScroll((int)offdx, 0, -(int)(offdx), 0, time);}
			invalidate();return true;
		}setpercent(offdx/mwidth,(int)offdx);
		}else{
			startView.dispatchTouchEvent(ev);
		}
		return true;//super.dispatchTouchEvent(ev);
	}
	private void setpercent(float percent,int offx) {
		// TODO 自动生成的方法存根
         //mm.reset();
		radius=percent*180;
         mc.save();
         mc.translate(0, 0, (float) (zdistance*(0.5f-Math.abs(0.5-Math.abs(percent)))));
         if(Math.abs(radius)>90){
        	 aboveview=startView==child1?child2:child1;
        	 mc.rotateY(radius-180);
         }else{
        	 aboveview=startView;
        	 mc.rotateY(radius);}
         mc.getMatrix(mm);
         mm.preTranslate(-mwidth/2,-mheight/2);
 		 mm.postTranslate(mwidth/2,mheight/2);
         mc.restore();
         invalidate();
	}
	@Override
	public void computeScroll() {
		// TODO 自动生成的方法存根
		super.computeScroll();
		if(ms.computeScrollOffset()){
			int x=ms.getCurrX();
			setpercent((float)x/mwidth,x);
		}
	}
    @Override
    protected void onFinishInflate() {
    	// TODO 自动生成的方法存根
    	super.onFinishInflate();
    	child1=getChildAt(0);child2=getChildAt(1);
    	aboveview=startView=child2;
    }
    @Override
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
    	// TODO 自动生成的方法存根
    	if(child!=aboveview){return false;}else{
    		canvas.save();
        	canvas.concat(mm);
        	boolean draw=super.drawChild(canvas, aboveview,getDrawingTime());
        	canvas.restore();
        	return draw;
    	}
    }
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		// TODO 自动生成的方法存根
		super.onLayout(changed, l, t, r, b);
		mwidth=r-l;mheight=b-t;zdistance=mwidth/2;
	}

}
主要思路就是:重写了drawchild函数,在绘图前反转canvas,矩阵由滑动距离决定,


下载源码 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值