Android 3D Rotation View
Today I saw an article on the internet writing about Android 3D Rotation (http://www.ibm.com/developerworks/cn/opensource/os-cn-android-anmt2/index.html? Ca = drs-), write one out of curiosity, and the running effect is as follows:
Next we will start to finish this step by step.
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. getChi LdAt (2 )). setImageResource (R. drawable. page3) ;}@ Overrideprotected void onLayout (boolean changed, int l, int t, int r, int B) {int childLeft = 0; final int childCount = getChildCount (); 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 (exact size supported only);} final int heightMode = MeasureSpec. getMode (heightMeasureSpec); if (heightMode! = MeasureSpec. EXACTLY) {throw new IllegalStateException (exact size supported only);} final int count = getChildCount (); for (int I = 0; I <count; I ++) {getChildAt (I ). measure (widthMeasureSpec, heightMeasureSpec) ;}} 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 smooth yet. We can judge and process it when the gesture 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; impor T android. widget. scroller; public class Rote3DView extends ViewGroup {private int mCurScreen = 1; // The sliding speed is private static final int SNAP_VELOCITY = 500; private VelocityTracker mVelocityTracker; private int mWidth; private scroler mScroller; private Camera mCamera; private Matrix mMatrix; // rotation angle, which can be modified to observe the effect private float angle = 90; public Rote3DView (Context context, AttributeSet attrs) {super (context, att Rs); mScroller = new Scroller (context); mCamera = new Camera (); mMatrix = new Matrix (); 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. p Age1); (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 = getChildCount (); 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 (exact size supported only);} final int heightMode = MeasureSpec. getMode (heightMeasureSpec); if (heightMode! = MeasureSpec. EXACTLY) {throw new IllegalStateException (exact size supported only);} final int count = getChildCount (); for (int I = 0; I <count; I ++) {getChildAt (I ). measure (widthMeasureSpec, heightMeasureSpec);} scrollTo (mCurScreen * width, 0);} private float mDownX; @ Overridepublic boolean onTouchEvent (MotionEvent event) {if (mVelocityTracker = null) {mVelocityTracker = VelocityTracker. obtain ();} // pass the current touch event to VelocityTrack Er 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 MotionEvent. ACTION_UP: final VelocityTracker velocityTracker = mVelocityTracker; velocityTracker. computeCurrentVelocity (1000); int velocityX = (int) velocityTracker. getXVelocity (); if (velocityX> SNAP_VELOCITY & mCurScreen> 0) {snapToScr Een (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. computescroloffset () {scrollTo (mScroller. getCurrX (), mScroller. getCurrY (); postInvalidate () ;}} public void snapToDestination () {setMWidth (); final int destScreen = (getScrollX () + mWidth/2)/mWidth; snapToScreen (destScreen);} public void snapToScreen (int whichScreen) {w HichScreen = Math. max (0, Math. min (whichScreen, getChildCount ()-1); setMWidth (); int scrollX = getScrollX (); int startWidth = whichScreen * mWidth; if (scrollX! = StartWidth) {int delta = 0; int startX = 0; if (whichScreen> mCurScreen) {setPre (); delta = startWidth-scrollX; startX = mWidth-startWidth + scrollX ;} else if (whichScreen <mCurScreen) {setNext (); delta =-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 ();}}}
Add the following code to implement the stereoscopic effect:
/** When sliding a View, the current View will be invalid. This function is used to re-draw the View and call the drawScreen function */@ Overrideprotected void dispatchDraw (Canvas 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) {// you can get the final int width = getWidth (); final int scrollWidth = Screen * width; final int scrollX = this. getScrollX (); // if (scrollWidth> scrollX + width | scrollWidth + width <scrollX) {return;} final View child = getChildAt (screen ); final int faceIndex = screen; final float currentDegree = getScrollX () * (angle/getMeasuredWidth (); final float faceDegree = currentDegree-faceIndex * angle; if (faceDegree> 90 | 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); drawChild (canvas, child, drawingTime); canvas. restore ();}