永发信息网

求助,怎么用android实现控件的3D立体旋转效果

答案:4  悬赏:50  手机版
解决时间 2021-02-19 16:42
求助,怎么用android实现控件的3D立体旋转效果
最佳答案
  • 实现水平滑动,所以可在手势抬起的时候进行判断并处理,是滑动显得流畅,代码如下:
    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;  
        // 滑动的速度  
        private static final int SNAP_VELOCITY = 500;  
        private VelocityTracker mVelocityTracker;  
        private int mWidth;  
        private Scroller mScroller;  
        private Camera mCamera;  
        private Matrix mMatrix;  
        // 旋转的角度,可以进行修改来观察效果  
        private float angle = 90;  
        public Rote3DView(Context context, AttributeSet attrs) {  
            super(context, attrs);  
            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.page1);   
             ((ImageView)this.getChildAt(1)).setImageResource(R.drawable.page2);   
             ((ImageView)this.getChildAt(2)).setImageResource(R.drawable.page3);   
        }  

        @Override  
        protected 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;  
                }  
            }  
        }  

        @Override  
        protected 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("仅支持精确尺寸");  
            }  
            final int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
            if(heightMode != MeasureSpec.EXACTLY){  
                throw new IllegalStateException("仅支持精确尺寸");  
            }  
            final int count = getChildCount();  
            for(int i = 0; i < count; i++){  
                getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);  
            }  
            scrollTo(mCurScreen * width, 0);  
        }  

        private float mDownX;  
        @Override  
        public boolean onTouchEvent(MotionEvent event) {  
            if(mVelocityTracker == null){  
                mVelocityTracker = VelocityTracker.obtain();  
            }  
            //将当前的触摸事件传递给VelocityTracker对象  
            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){  
                    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;  
        }  

        @Override  
        public void computeScroll() {  
            if (mScroller.computeScrollOffset()) {  
                scrollTo(mScroller.getCurrX(), mScroller.getCurrY());  
                postInvalidate();  
            }  
        }  

        public void snapToDestination(){  
            setMWidth();  
            final int destScreen = (getScrollX() + mWidth / 2) / mWidth;  
            snapToScreen(destScreen);  
        }  

        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 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();  
            }  
        }  
    }
  • 实现立体效果,添加如下代码:
      
    @Override  
    protected 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) {  
        // 得到当前子View的宽度  
        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();  
    }
  • 全部回答
    下面我们就开始一步步完成这个效果吧。 实现水平滑动 [java] view plaincopyprint? 01.package com.example.rotation3dview; 02. 03.import android.content.Context; 04.import android.util.AttributeSet; 05.import android.view.MotionEvent; 06.import android.view.View; 07.import android.view.ViewDebug.HierarchyTraceType; 08.import android.view.ViewGroup; 09.import android.widget.ImageView; 10. 11.public class Rote3DView extends ViewGroup{ 12. 13. public Rote3DView(Context context, AttributeSet attrs) { 14. super(context, attrs); 15. initScreens(); 16. } 17. 18. public void initScreens(){ 19. ViewGroup.LayoutParams p = new ViewGroup.LayoutParams( 20. ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT); 21. for (int i = 0; i < 3; i++) { 22. this.addView(new ImageView(this.getContext()), i, p); 23. } 24. ((ImageView)this.getChildAt(0)).setImageResource(R.drawable.page1); 25. ((ImageView)this.getChildAt(1)).setImageResource(R.drawable.page2); 26. ((ImageView)this.getChildAt(2)).setImageResource(R.drawable.page3); 27. } 28. 29. @Override 30. protected void onLayout(boolean changed, int l, int t, int r, int b) { 31. int childLeft = 0; 32. final int childCount = getChildCount(); 33. for(int i = 0; i< childCount; i++){ 34. final View childView = getChildAt(i); 35. if(childView.getVisibility() != View.GONE){ 36. final int childWidth = childView.getMeasuredWidth(); 37. childView.layout(childLeft, 0, childLeft + childWidth, childView.getMeasuredHeight()); 38. childLeft += childWidth; 39. } 40. } 41. } 42. 43. @Override 44. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 45. super.onMeasure(widthMeasureSpec, heightMeasureSpec); 46. final int width = MeasureSpec.getSize(widthMeasureSpec); 47. final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 48. if(widthMode != MeasureSpec.EXACTLY){ 49. throw new IllegalStateException("仅支持精确尺寸"); 50. } 51. final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 52. if(heightMode != MeasureSpec.EXACTLY){ 53. throw new IllegalStateException("仅支持精确尺寸"); 54. } 55. final int count = getChildCount(); 56. for(int i = 0; i < count; i++){ 57. getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); 58. } 59. } 60. 61. private float mDownX; 62. @Override 63. public boolean onTouchEvent(MotionEvent event) { 64. float x = event.getX(); 65. switch (event.getAction()) { 66. case MotionEvent.ACTION_DOWN: 67. mDownX = x; 68. break; 69. case MotionEvent.ACTION_MOVE: 70. int disX = (int)(mDownX - x); 71. mDownX = x; 72. scrollBy(disX, 0); 73. break; 74. case MotionEvent.ACTION_UP: 75. 76. break; 77. 78. default: 79. break; 80. } 81. 82. return true; 83. } 84. 85.} 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); } @Override protected 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; } } } @Override protected 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("仅支持精确尺寸"); } final int heightMode = MeasureSpec.getMode(heightMeasureSpec); if(heightMode != MeasureSpec.EXACTLY){ throw new IllegalStateException("仅支持精确尺寸"); } final int count = getChildCount(); for(int i = 0; i < count; i++){ getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); } } private float mDownX; @Override public 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; } }
    下面我们就开始一步步完成这个效果吧。 实现水平滑动 [java] view plaincopyprint? 01.package com.example.rotation3dview; 02. 03.import android.content.Context; 04.import android.util.AttributeSet; 05.import android.view.MotionEvent; 06.import android.view.View; 07.import android.view.ViewDebug.HierarchyTraceType; 08.import android.view.ViewGroup; 09.import android.widget.ImageView; 10. 11.public class Rote3DView extends ViewGroup{ 12. 13. public Rote3DView(Context context, AttributeSet attrs) { 14. super(context, attrs); 15. initScreens(); 16. } 17. 18. public void initScreens(){ 19. ViewGroup.LayoutParams p = new ViewGroup.LayoutParams( 20. ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT); 21. for (int i = 0; i < 3; i++) { 22. this.addView(new ImageView(this.getContext()), i, p); 23. } 24. ((ImageView)this.getChildAt(0)).setImageResource(R.drawable.page1); 25. ((ImageView)this.getChildAt(1)).setImageResource(R.drawable.page2); 26. ((ImageView)this.getChildAt(2)).setImageResource(R.drawable.page3); 27. } 28. 29. @Override 30. protected void onLayout(boolean changed, int l, int t, int r, int b) { 31. int childLeft = 0; 32. final int childCount = getChildCount(); 33. for(int i = 0; i< childCount; i++){ 34. final View childView = getChildAt(i); 35. if(childView.getVisibility() != View.GONE){ 36. final int childWidth = childView.getMeasuredWidth(); 37. childView.layout(childLeft, 0, childLeft + childWidth, childView.getMeasuredHeight()); 38. childLeft += childWidth; 39. } 40. } 41. } 42. 43. @Override 44. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 45. super.onMeasure(widthMeasureSpec, heightMeasureSpec); 46. final int width = MeasureSpec.getSize(widthMeasureSpec); 47. final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 48. if(widthMode !
    下面我们就开始一步步完成这个效果吧。 实现水平滑动 [java] view plaincopyprint? 01.package com.example.rotation3dview; 02. 03.import android.content.Context; 04.import android.util.AttributeSet; 05.import android.view.MotionEvent; 06.import android.view.View; 07.import android.view.ViewDebug.HierarchyTraceType; 08.import android.view.ViewGroup; 09.import android.widget.ImageView; 10. 11.public class Rote3DView extends ViewGroup{ 12. 13. public Rote3DView(Context context, AttributeSet attrs) { 14. super(context, attrs); 15. initScreens(); 16. } 17. 18. public void initScreens(){ 19. ViewGroup.LayoutParams p = new ViewGroup.LayoutParams( 20. ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT); 21. for (int i = 0; i < 3; i++) { 22. this.addView(new ImageView(this.getContext()), i, p); 23. } 24. ((ImageView)this.getChildAt(0)).setImageResource(R.drawable.page1); 25. ((ImageView)this.getChildAt(1)).setImageResource(R.drawable.page2); 26. ((ImageView)this.getChildAt(2)).setImageResource(R.drawable.page3); 27. } 28. 29. @Override 30. protected void onLayout(boolean changed, int l, int t, int r, int b) { 31. int childLeft = 0; 32. final int childCount = getChildCount(); 33. for(int i = 0; i< childCount; i++){ 34. final View childView = getChildAt(i); 35. if(childView.getVisibility() != View.GONE){ 36. final int childWidth = childView.getMeasuredWidth(); 37. childView.layout(childLeft, 0, childLeft + childWidth, childView.getMeasuredHeight()); 38. childLeft += childWidth; 39. } 40. } 41. } 42. 43. @Override 44. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 45. super.onMeasure(widthMeasureSpec, heightMeasureSpec); 46. final int width = MeasureSpec.getSize(widthMeasureSpec); 47. final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 48. if(widthMode != MeasureSpec.EXACTLY){ 49. throw new IllegalStateException("仅支持精确尺寸"); 50. } 51. final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 52. if(heightMode != MeasureSpec.EXACTLY){ 53. throw new IllegalStateException("仅支持精确尺寸"); 54. } 55. final int count = getChildCount(); 56. for(int i = 0; i < count; i++){ 57. getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); 58. } 59. } 60. 61. private float mDownX; 62. @Override 63. public boolean onTouchEvent(MotionEvent event) { 64. float x = event.getX(); 65. switch (event.getAction()) { 66. case MotionEvent.ACTION_DOWN: 67. mDownX = x; 68. break; 69. case MotionEvent.ACTION_MOVE: 70. int disX = (int)(mDownX - x); 71. mDownX = x; 72. scrollBy(disX, 0); 73. break; 74. case MotionEvent.ACTION_UP: 75. 76. break; 77. 78. default: 79. break; 80. } 81. 82. return true; 83. } 84. 85.} 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); } @Override protected 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; } } } @Override protected 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("仅支持精确尺寸"); } final int heightMode = MeasureSpec.getMode(heightMeasureSpec); if(heightMode != MeasureSpec.EXACTLY){ throw new IllegalStateException("仅支持精确尺寸"); } final int count = getChildCount(); for(int i = 0; i < count; i++){ getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); } } private float mDownX; @Override public 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; } }
    我要举报
    如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
    大家都在看
    欣宇自动化设备有限公司这个地址在什么地方,
    怀柔开发区属于郊区还是城区?京东送货怎么填
    泡温泉后全身发热原因
    烟酸缺乏时引起A.脚气病B.佝偻病C.周围神经炎
    有人说子女是天空中的风筝父母的思念就是前者
    安装固定电话找谁啊 ?
    【byebye中文歌词】Lovestoned的ByeByeBye中
    春风咋起什么意思
    天姿名妆这个地址在什么地方,我要处理点事
    我休息睡眠不好 每天晚上都做梦 该怎么办
    陇运驾校(报名处)在哪里啊,我有事要去这个地
    win10系统克隆到新硬盘,求助
    公司治理主要是根据权力机构、决策机构、执行
    金额管理专业是什么
    工具,螺丝螺帽等,怎样做会计分录
    推荐资讯
    中国电信号段哪个最好
    VV22-0.6/1KV-2*4电缆不是屏蔽电缆吗?
    老台门总店这个地址在什么地方,我要处理点事
    葫芦咀地址有知道的么?有点事想过去
    工人运送1000个玻璃杯,每个运费0,3元,但如有
    【3.6251251251.混循环小数,可简写为什么?3.6
    吃清火栀麦片对哺乳期的宝宝有没有影响
    一块商住用地容积率4.7,应该盖多少层?
    遇见美美容养生馆在哪里啊,我有事要去这个地
    轻骑摩托(郭磊庄中心卫生院西)地址在什么地方
    台电P85不能连接电脑
    求 《铁道飞虎》百度云链接
    正方形一边上任一点到这个正方形两条对角线的
    阴历怎么看 ?