Read an article online today to write about Android 3D rotation (http://www.ibm.com/developerworks/cn/opensource/os-cn-android-anmt2/index.html?ca= drs-), out of Curiosity wrote one, the operation effect is as follows:
Let's start by stepping through the effect.
Achieve horizontal sliding
Package Com.example.rotation3dview;import Android.content.context;import Android.util.attributeset;import Android.view.motionevent;import Android.view.view;import Android.view.viewdebug.hierarchytracetype;import Android.view.viewgroup;import Android.widget.imageview;public class Rote3dview extends Viewgroup{public Rote3DView ( Context context, AttributeSet Attrs) {Super (context, attrs); Initscreens ();} public void Initscreens () {viewgroup.layoutparams p = new Viewgroup.layoutparams (ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); for (int i = 0; i < 3; i++) {This.addview (New ImageView (This.getcontext ()), I, p); } ((ImageView) this.getchildat (0)). Setimageresource (R.drawable.page1); ((ImageView) This.getchildat (1)). Setimageresource (R.drawable.page2); ((ImageView) This.getchildat (2)). Setimageresource (R.drawable.page3); } @Overrideprotected void OnLayout (Boolean changed, int l, int t, int r, int b) {int childleft = 0;final int childCount = g Etchildcount (); for (iNT i = 0; i< ChildCount; i++) {final View Childview = Getchildat (i); if (childview.getvisibility ()! = View.gone) {Final int childwidth = Childview.getmeasuredwidth (); Childview.layout (childleft, 0, Childleft + childwidth, childview.getmeasuredheight ()); Childleft + = Childwidth;}}} @Overrideprotected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespec, HEIGHTMEASURESPEC); final int width = measurespec.getsize (widthmeasurespec); final int widthmode = Measurespec.getmode ( WIDTHMEASURESPEC); if (widthmode! = measurespec.exactly) {throw new IllegalStateException ("only supports exact dimensions");} Final int heightmode = Measurespec.getmode (Heightmeasurespec), if (heightmode! = measurespec.exactly) {throw new IllegalStateException ("only supports exact dimensions");} Final int count = Getchildcount (); for (int i = 0; i < count; i++) {Getchildat (i). Measure (Widthmeasurespec, heightmeasures PEC);}} private float Mdownx; @Overridepublic boolean ontouchevent (Motionevent event) {float x = event.getx (); switch (Event.getaCtion ()) {Case MotionEvent.ACTION_DOWN:mDownX = x;break;case MotionEvent.ACTION_MOVE:int disx = (int) (mdownx-x); mdownx = X;scrollby (DISX, 0); break;case motionevent.action_up:break;default:break;} return true;}}The slide above is not very smooth, we judge and process the gesture when it is lifted, the code is as follows:
Package Com.example.rotation3dview;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.velocitytracker;import Android.view.view;import Android.view.viewdebug.hierarchytracetype;import Android.view.viewgroup;import Android.widget.ImageView;import Android.widget.scroller;public class Rote3dview extends viewgroup{private int mcurscreen = 1;//sliding speed private static final int snap_velocity = 500;private velocitytracker mvelocitytracker;private int mwidth;private Scroller mScroller;private C Amera mcamera;private Matrix mmatrix;//rotation angle, can be modified to observe the effect of private float angle = 90;public rote3dview (context context, Attr Ibuteset attrs) {Super (context, attrs); mscroller = new Scroller (context); Mcamera = new Camera (); Mmatrix = new Matrix (); INI Tscreens ();} public void Initscreens () {viewgroup.layoutparams p = new Viewgroup.layoutparams (Viewgroup.layoutparaMs. Match_parent,viewgroup.layoutparams.match_parent); for (int i = 0; i < 3; i++) {This.addview (New ImageView (This.getcontext ()), I, p); } ((ImageView) this.getchildat (0)). Setimageresource (R.drawable.page1); ((ImageView) This.getchildat (1)). Setimageresource (R.drawable.page2); ((ImageView) This.getchildat (2)). Setimageresource (R.drawable.page3); } @Overrideprotected void OnLayout (Boolean changed, int l, int t, int r, int b) {int childleft = 0;final int childCount = g Etchildcount (); for (int i = 0; i< childCount; i++) {final View Childview = Getchildat (i); if (childview.getvisibility ()! = View.gone) {final int childwidth = Childview.getmeasuredwidth (); Childview.layout (childleft, 0, Childleft + childWidth, Childview.getmeasuredheight ()); Childleft + = Childwidth;}} @Overrideprotected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespec, HEIGHTMEASURESPEC); final int width = measurespec.getsize (widthmeasurespec); final int widthmode = MEASURESPEC.GEtmode (WIDTHMEASURESPEC); if (widthmode! = measurespec.exactly) {throw new IllegalStateException ("only supports exact dimensions");} Final int heightmode = Measurespec.getmode (Heightmeasurespec), if (heightmode! = measurespec.exactly) {throw new IllegalStateException ("only supports exact dimensions");} Final int count = Getchildcount (); for (int i = 0; i < count; i++) {Getchildat (i). Measure (Widthmeasurespec, heightmeasures PEC);} ScrollTo (mcurscreen * width, 0);} private float Mdownx; @Overridepublic boolean ontouchevent (Motionevent event) {if (Mvelocitytracker = = null) { Mvelocitytracker = Velocitytracker.obtain ();} Passes the current touch event to the Velocitytracker object Mvelocitytracker.addmovement (event); float x = Event.getx (); switch (Event.getaction () {Case MotionEvent.ACTION_DOWN:if (!mscroller.isfinished ()) {mscroller.abortanimation ();} Mdownx = x;break;case MotionEvent.ACTION_MOVE:int disx = (int) (mdownx-x); mdownx = X;scrollby (disx, 0); Break;case motione Vent. action_up:final Velocitytracker velocitytracker = mvelocitytracker;velocitytracker.computecurrentvelocity (10int Velocityx = (int) velocitytracker.getxvelocity (); if (Velocityx > snap_velocity && mcurscreen > 0) { Snaptoscreen (mCurScreen-1);} else if (Velocityx <-snap_velocity && Mcurscreen < Getchildcount ()-1) {Snaptoscreen (mcurscreen + 1);} Else{snaptodestination ();} if (mvelocitytracker! = null) {mvelocitytracker.recycle (); mvelocitytracker = null;} break;} return true;} @Overridepublic void Computescroll () {if (Mscroller.computescrolloffset ()) {ScrollTo (Mscroller.getcurrx ()), Mscroller.getcurry ());p ostinvalidate ();}} public void Snaptodestination () {setmwidth (); final int destscreen = (GETSCROLLX () + MWIDTH/2)/Mwidth;snaptoscreen (dests Creen);} public void Snaptoscreen (int whichscreen) {whichscreen = Math.max (0, Math.min (Whichscreen, Getchildcount ()-1)); Setmwidth (); int scrollx = GETSCROLLX (); int startwidth = Whichscreen * MWIDTH;IF (scrollx! = startwidth) {int delta = 0;int s Tartx = 0;if (Whichscreen > Mcurscreen) {setpre ();d elta = Startwidth-scrollx;startx = Mwidth-Startwidth + scrollx;} else if (Whichscreen < Mcurscreen) {Setnext ();d elta =-scrollx;startx = Scrollx + mwidth;} Else{startx = Scrollx;delta = Startwidth-scrollx;} Mscroller.startscroll (StartX, 0, Delta, 0, Math.Abs (Delta) * 2); invalidate ();}} private void Setnext () {int count = This.getchildcount (); View view = Getchildat (count-1); Removeviewat (count-1); AddView (view, 0);} private void Setpre () {int count = This.getchildcount (); View view = Getchildat (0); Removeviewat (0); AddView (view, count-1);} private void Setmwidth () {if (Mwidth = = 0) {mwidth = GetWidth ();}}}To achieve a stereoscopic effect, add the following code:
/* * When a view swipe occurs, it causes the current view to be invalid, and the function is to redraw the view call Drawscreen function/@Overrideprotected void Dispatchdraw (canvas canvas) { Final Long drawingtime = Getdrawingtime (); final int count = Getchildcount (); for (int i = 0; i < count; i++) {Drawscreen (Canvas, I, Drawingtime);}} public void Drawscreen (canvas canvas, int screen, long drawingtime) {//Gets the width of the current child view final int width = getwidth (); final int scrollwidth = screen * width;final int scrollx = THIS.GETSCROLLX ()///offset insufficient if (ScrollWidth > scrollx + width | | scro Llwidth + Width < scrollx) {return;} Final View child = getchildat (screen), final int faceindex = screen;final float Currentdegree = GETSCROLLX () * (angle/get Measuredwidth ()); final float facedegree = Currentdegree-faceindex * angle;if (Facedegree > | | Facedegree <-90) {return;} Final float CenterX = (ScrollWidth < SCROLLX)? ScrollWidth + width:scrollwidth;final Float centery = getheight ()/2;final camera camera = mcamera;final Matrix matrix = Mmatrix;canvas.save ();Camera.save (); Camera.rotatey (-facedegree); Camera.getmatrix (matrix); Camera.restore (); Matrix.pretranslate (- CenterX,-centery), Matrix.posttranslate (CenterX, CenterY), Canvas.concat (matrix);d rawchild (canvas, child, Drawingtime); Canvas.restore ();}
Project full source code download: Https://code.csdn.net/lxq_xsyu/rotation3dviewgit:[email protected]:lxq_xsyu/rotation3dview.git