一个可以手势缩放layout、拖拽layout的PowerfulLayout

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

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

可以实现以下需求:

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

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

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

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

4.拖拽(平移)layout

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

布局文件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:

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;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int pointerCount = event.getPointerCount(); // 获得多少点
        if (pointerCount > 1) {// 多点触控,让mScaleGestureDetector处理触摸事件
            return mScaleGestureDetector.onTouchEvent(event);
        } else {
            long currentTimeMillis = System.currentTimeMillis();
            if (currentTimeMillis - lastMultiTouchTime > 200) {
                // // 双指触控后要等待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();
        }
    }

}
时间: 2024-10-13 22:56:52

一个可以手势缩放layout、拖拽layout的PowerfulLayout的相关文章

android项目 之 记事本(14) ----- 手势缩放与拖拽图片

本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020 上节实现了查看图片及录音的功能,其中查看图片,可以调用系统的图库来查看图片,也可以自定义Activity来查看图片,今天就在上节的基础上,实现手势缩放与拖拽图片. 想必大家都用过系统的图库,浏览图片时,可以通过手势放大或缩小图片,旋转图片,拖拽图片等功能,我们也为自已定义的查看图片的Activity增加手势缩放与拖拽图片的功能,效果如下图: 上面四幅图中,演示了通过手势(多点触

IOS开发UI篇—手势识别器(拖拽+旋转+缩放)

IOS开发UI篇—手势识别器(拖拽+旋转+缩放) 一.拖拽 示例代码: 1 // 2 // YYViewController.m 3 // 06-拖拽事件 4 // 5 // Created by apple on 14-6-19. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import "YYViewController.h" 10 11 @interface YYViewController ()

猫猫学IOS(三十六)UI之手势事件旋转_缩放_拖拽

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 源码:http://blog.csdn.net/u013357243/article/details/45560213 效果 完成一个图片的捏合缩放,拖拽,旋转动作. 设计思路 拖拽: 首先是最简单的拖拽 //拖拽 -(void)panTest { UIPanGestureRecognizer *pan = [[UIPanGe

(素材源码)猫猫学IOS(三十六)UI之手势事件旋转_缩放_拖拽

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 源码:http://download.csdn.net/detail/u013357243/8671943 效果 完成一个图片的捏合缩放,拖拽,旋转动作. 代码:NYViewController.m // // NYViewController.m // 旋转_缩放_拖拽 // // Created by apple on 1

Android 自定义ImageView支持缩放,拖拽,方便复用

今天刚发了一篇关于ImageView的缩放和拖拽的博客,然后我想了下,将他自定义下,方便我们来复用这个imageView,效果我就不多说了,http://blog.csdn.net/xiaanming/article/details/8827257就是这个效果,我只是把他抽出来自定义了下,代码还是贴上吧,我也将demo上传一下,有疑问大家指出来,大家共同学习,共同进步,呵呵 [java] view plaincopy package com.example.myimageview; import

Android官方开发文档Training系列课程中文版:手势处理之拖拽或缩放

原文地址:https://developer.android.com/training/gestures/scale.html 这节课主要学习如何使用触摸手势来拖动.放大屏幕上的对象. 拖动对象 如果你的重点在Android 3.0以上的版本,那么你可以使用内置的拖拽事件监听器View.OnDragListener. 触摸手势最常见的操作就是使用它来拖动屏幕上的对象.下面的代码允许用户拖动屏幕上的图像.要注意以下几点: 在拖动操作中,APP会一直保持手指拖动的轨迹,就算是另一只手指触到屏幕也是.

Kean专题:拖动一个属性块(JIG拖拽)

原文转载自:http://through-the-interface.typepad.com/through_the_interface/jigs/(该口已无法访问) 可访问转载入口:http://bbs.mjtd.com/thread-75618-1-1.html(转载自明镜通道by雪山飞狐_lzh) 原kean博客已经无法看到,故转载明经通道 雪山飞狐_lzh 老师整理内容     1.kean原文翻译     March 18, 2009 Jigging an AutoCAD block

最近写的一个控件——Well Swipe 拖拽排序实现

如图: >删除过渡动画 >拖拽排序

拖拽碰撞最后一个问题了,就是拖拽之后,点击会变回去,不知道为何

<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8"> <title>可拖拽的照片墙</title> <style type="text/css"> html body { margin:0; } #wrap { list-style:none; padding:0; margin:30p