zoukankan      html  css  js  c++  java
  • 缩放系列(三):一个可以手势缩放、拖拽、旋转的layout

    弄了一个下午,终于搞出来了,PowerfulLayout

    下面是一个功能强大的改造的例子:

    可以实现以下需求:

    1.两个手指进行缩放布局

    2.所有子控件也随着缩放,

    3.子控件该有的功能不能丢失(像button有可被点击的功能,缩放后不能丢失该功能)

    相对上个例子,多了一个功能---

    4.拖拽(平移)layout

     运行效果图:http://pan.baidu.com/s/1geIoG8r

    图片太大就不贴出来了。

    布局文件test.xml、超级简单的

    <?xml version="1.0" encoding="utf-8"?>
    <com.example.testbitmapscale.PowerfulLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
    <FrameLayout
        android:background="@drawable/home_tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
            <ImageButton
                android:id="@+id/imageButton2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/selector_button1" />
    </FrameLayout>
    
    
    </com.example.testbitmapscale.PowerfulLayout>

    java代码:

    MainActivity也是超级简单

    public class MainActivity extends ActionBarActivity {
    
    
        private View view;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // setContentView(R.layout.test);
            view = View.inflate(this, R.layout.test, null);
            setContentView(view);
    
            
        }
    
    //    @Override
    //    public boolean onTouchEvent(MotionEvent event) {
    //        if (event.getPointerCount() > 1) {
    //            // 多点触控
    //            // 返回给ScaleGestureDetector来处理
    //            return mScaleGestureDetector.onTouchEvent(event);
    //        } else {
    //            // 单点触控
    //            switch (event.getAction()) {
    //            case MotionEvent.ACTION_DOWN:
    //                downX = (int) event.getX();
    //                downY = (int) event.getY();
    //                newHeight = view.getLayoutParams().height;
    //                newWidth = view.getLayoutParams().width;
    ////                 int widthMeasureSpec =
    ////                 View.MeasureSpec.makeMeasureSpec(2000,View.MeasureSpec.AT_MOST);
    ////                
    ////                 int heightMeasureSpec
    ////                 =View.MeasureSpec.makeMeasureSpec(2000,View.MeasureSpec.AT_MOST);
    ////                
    ////                 view.measure(widthMeasureSpec,heightMeasureSpec);
    ////                
    ////                 newHeight = view.getMeasuredHeight();
    ////                
    ////                 newWidth = view.getMeasuredWidth();
    //                break;
    //            case MotionEvent.ACTION_MOVE:
    //                long currentTimeMillis = System.currentTimeMillis();
    //                if (currentTimeMillis - lastMultiTouchTime > 200) {
    //                    // 双指触控后要等待200毫秒才能执行单指触控的操作,避免双指触控后出现颤抖的情况
    //                    int moveX = (int) event.getX();// 移动手指的时候手指的x
    //                    int moveY = (int) event.getY();// 移动手指的时候手指的y
    //                    int deltaX = (int) (moveX - downX);
    //                    int deltaY = (int) (moveY - downY);
    //                    int newLeft = left + deltaX;// view的新left
    //                    int newTop = top + deltaY;// view的新top
    //                    int newRight = right + deltaX;// view的新right
    //                    int newBottom = bottom + deltaY;// view的新bottom
    ////                    int newWidth = (int) (preScale * originalWidth);
    ////                    int newHeight = (int) (preScale * originalHeight);
    ////                    if (deltaX>(newWidth-originalHeight)/2||deltaY>(newHeight-originalHeight)/2) {
    ////                        return false;
    ////                    }
    //                    // int newWidth = view.getWidth();
    //                    // int newHeight = view.getHeight();
    //                    System.out.println("newWidth:" + newWidth + "newHeight:"
    //                            + newHeight);
    ////                    System.out.println(preScale);
    //                    if (newLeft < originalWidth - newWidth) {
    //                        newLeft = originalWidth - newWidth;
    //                        newRight = newLeft + newWidth;
    //                    }
    //                    // if (newTop < originalHeight - newHeight){
    //                    // newTop = originalHeight - newHeight;
    //                    // newBottom= newTop+newHeight;
    //                    // }
    //                    // if(newRight>originalWidth){
    //                    // newRight=originalWidth;
    //                    // newLeft=newRight-newWidth;
    //                    // }
    //                    // if(newBottom>originalHeight){
    //                    // newBottom=originalHeight;
    //                    // newTop=newBottom-newHeight;
    //                    // }
    //                    view.layout(newLeft, newTop, newRight, newBottom);// 重新摆放view的位置
    //                } else {
    //                    return false;
    //                }
    //
    //                break;
    //            case MotionEvent.ACTION_UP:
    //                // 更新位置信息
    //                left = view.getLeft();
    //                top = view.getTop();
    //                right = view.getRight();
    //                bottom = view.getBottom();
    //                break;
    //
    //            default:
    //                break;
    //            }
    //            return true;// 代表消费了事件
    //        }
    //    }
    
    
    }

    PowerfulLayout.java:

    package com.example.testbitmapscale;
    
    import android.content.Context;
    import android.support.v4.widget.ViewDragHelper;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.ScaleGestureDetector;
    import android.view.View;
    import android.widget.FrameLayout;
    
    import com.nineoldandroids.view.ViewHelper;
    
    public class PowerfulLayout extends FrameLayout {
        // 屏幕宽高
        private int screenHeight;
        private int screenWidth;
        private ViewDragHelper mDragHelper;
        private long lastMultiTouchTime;// 记录多点触控缩放后的时间
        private int originalWidth;// view宽度
        private int originalHeight;// view高度
        private ScaleGestureDetector mScaleGestureDetector = null;
        // private View view;
        private int downX;// 手指按下的x坐标值
        private int downY;// 手指按下的y坐标值
        private int left;// view的左坐标值
        private int top;// view的上坐标值
        private int right;// view的右坐标值
        private int bottom;// view的下坐标值
        private int newHeight;
        private int newWidth;
    
        private float scale;
        private float preScale = 1;// 默认前一次缩放比例为1
    
        public PowerfulLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context);
        }
    
        public PowerfulLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }
    
        public PowerfulLayout(Context context) {
            super(context);
            init(context);
        }
    
        private void init(Context context) {
            mDragHelper = ViewDragHelper.create(this, callback);
            mScaleGestureDetector = new ScaleGestureDetector(context,
                    new ScaleGestureListener());
    
            // view.post(new Runnable() {
            //
            // @Override
            // public void run() {
            // left = view.getLeft();
            // top = view.getTop();
            // right = view.getRight();
            // bottom = view.getBottom();
            // originalWidth = view.getWidth();
            // originalHeight = view.getHeight();
            // }
            // });
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            screenWidth = getMeasuredWidth();
            screenHeight = getMeasuredHeight();
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            super.onInterceptTouchEvent(ev);
            boolean b = mDragHelper.shouldInterceptTouchEvent(ev);// 由mDragHelper决定是否拦截事件,并传递给onTouchEvent
            return b;
        }
    
        private boolean needToHandle=true;
        @Override
        public boolean onTouchEvent(MotionEvent event) {
    
            int pointerCount = event.getPointerCount(); // 获得多少点
            if (pointerCount > 1) {// 多点触控,
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    needToHandle=false;
                    break;
                case MotionEvent.ACTION_MOVE:
                    
                    break;
                case MotionEvent.ACTION_POINTER_2_UP://第二个手指抬起的时候
                    needToHandle=true;
                    break;
    
                default:
                    break;
                }
                return mScaleGestureDetector.onTouchEvent(event);//让mScaleGestureDetector处理触摸事件
            } else {
                long currentTimeMillis = System.currentTimeMillis();
                if (currentTimeMillis - lastMultiTouchTime > 200&&needToHandle) {
    //                  多点触控全部手指抬起后要等待200毫秒才能执行单指触控的操作,避免多点触控后出现颤抖的情况
                    try {
                        mDragHelper.processTouchEvent(event);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return true;
                }
    //            }
            }
            return false;
        }
    
        private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
            /**
             * 用于判断是否捕获当前child的触摸事件
             * 
             * @param child
             *            当前触摸的子view
             * @param pointerId
             * @return true就捕获并解析;false不捕获
             */
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                if (preScale > 1)
                    return true;
                return false;
            }
    
            /**
             * 控制水平方向上的位置
             */
            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
    
                if (left < (screenWidth - screenWidth * preScale) / 2)
                    left = (int) (screenWidth - screenWidth * preScale) / 2;// 限制mainView可向左移动到的位置
                if (left > (screenWidth * preScale - screenWidth) / 2)
                    left = (int) (screenWidth * preScale - screenWidth) / 2;// 限制mainView可向右移动到的位置
                return left;
            }
    
            public int clampViewPositionVertical(View child, int top, int dy) {
    
                if (top < (screenHeight - screenHeight * preScale) / 2) {
                    top = (int) (screenHeight - screenHeight * preScale) / 2;// 限制mainView可向上移动到的位置
                }
                if (top > (screenHeight * preScale - screenHeight) / 2) {
                    top = (int) (screenHeight * preScale - screenHeight) / 2;// 限制mainView可向上移动到的位置
                }
                return top;
            }
    
        };
    
        public class ScaleGestureListener implements
                ScaleGestureDetector.OnScaleGestureListener {
    
            @Override
            public boolean onScale(ScaleGestureDetector detector) {
    
                float previousSpan = detector.getPreviousSpan();// 前一次双指间距
                float currentSpan = detector.getCurrentSpan();// 本次双指间距
                if (currentSpan < previousSpan) {
                    // 缩小
                    // scale = preScale-detector.getScaleFactor()/3;
                    scale = preScale - (previousSpan - currentSpan) / 1000;
                } else {
                    // 放大
                    // scale = preScale+detector.getScaleFactor()/3;
                    scale = preScale + (currentSpan - previousSpan) / 1000;
                }
                // 缩放view
                if (scale > 0.5) {
                    ViewHelper.setScaleX(PowerfulLayout.this, scale);// x方向上缩放
                    ViewHelper.setScaleY(PowerfulLayout.this, scale);// y方向上缩放
                }
                return false;
            }
    
            @Override
            public boolean onScaleBegin(ScaleGestureDetector detector) {
                // 一定要返回true才会进入onScale()这个函数
                return true;
            }
    
            @Override
            public void onScaleEnd(ScaleGestureDetector detector) {
                preScale = scale;// 记录本次缩放比例
                lastMultiTouchTime = System.currentTimeMillis();// 记录双指缩放后的时间
            }
        }
    
    }

    可以手势缩放、拖拽、旋转的layout应用场景,例子:qq侧滑菜单。侧滑的时候菜单中所有子控件跟随父控件从小变大,不过它不支持双指缩放,只是单指操作。链接:http://blog.csdn.net/qq_30948129/article/details/52282451

  • 相关阅读:
    【架构】如何设计支持多租户的数据库?
    maven的仓库:本地和远程
    maven私服
    MSA(微服务简介)
    json数据的格式
    shiro的原理理解
    异构的概念?大数据量的异构处理?
    面试之多线程通信
    面试之并发的解决方案
    进程与线程的简单理解
  • 原文地址:https://www.cnblogs.com/johnsonwei/p/5831925.html
Copyright © 2011-2022 走看看