缩放系列(三):一个可以手势缩放、拖拽、旋转的layout

来源:互联网 发布:消失的夫妻 知乎 编辑:程序博客网 时间:2024/06/13 07:23

弄了一个下午,终于搞出来了,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();// 记录双指缩放后的时间        }    }}

旋转效果跟缩放效果的用法类似的,一个用的是RotateGestureDetector 一个用的是ScaleGustureDetector都是手势检测器,在这就不写了。

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

源码地址:https://github.com/Jszgw/ScaleLayout3

0 0
原创粉丝点击