仿美图秀秀的图片剪切

Posted ihrthk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了仿美图秀秀的图片剪切相关的知识,希望对你有一定的参考价值。

先贴上美图秀秀原作的效果图,右边是我仿的效果图。

刚一眼打量过去,吸引我们的就是那四个大点。就从它开始吧,目前看来这个大点是一个图片,当点击下去的时候有加亮的效果,可能这又是一张图片。我们先不要考虑这些,先把它当做一个普通的Point来处理就好了。正常来讲的话,我们这里需要四个Point,但是考虑到后面我们对这些点进行复杂的运算和事件处理,只要申请两个Point就好了,以便降低问题的复杂度。两个即leftUpPoint和rightDownPoint。(其余两个点只要由这个两点拼一下就可以了)

那么画中间的框就用下面的代码:

        paint.setARGB(255, 255, 255, 255);
        paint.setStrokeWidth(3);
        paint.setStyle(Paint.Style.STROKE);
        Rect frameRect = new Rect(leftUpPoint.x + offsetLeftUpPoint.x,
                leftUpPoint.y + offsetLeftUpPoint.y, rightDownPoint.x
                        + offsetRightDownPoint.x, rightDownPoint.y
                        + offsetRightDownPoint.y);
        canvas.drawRect(frameRect, paint);

offsetLeftUpPoint和offsetRightDownPoint是leftUpPoint和rightDownPoint相对的偏移量,后面事件处理的时候会用到。

然后顺势把里面的线条和数字画出来。代码如下:

// 画内框里线条
        paint.setARGB(90, 255, 255, 255);
        paint.setStrokeWidth(2);
        canvas.drawLine(leftUpPoint.x + this.getDynamicFrameWidth() / 3
                + offsetLeftUpPoint.x, leftUpPoint.y + offsetLeftUpPoint.y,
                leftUpPoint.x + this.getDynamicFrameWidth() / 3
                        + offsetLeftUpPoint.x, rightDownPoint.y
                        + offsetRightDownPoint.y, paint);
        canvas.drawLine(rightDownPoint.x - this.getDynamicFrameWidth() / 3
                + offsetRightDownPoint.x, leftUpPoint.y + offsetLeftUpPoint.y,
                rightDownPoint.x - this.getDynamicFrameWidth() / 3
                        + offsetRightDownPoint.x, rightDownPoint.y
                        + offsetRightDownPoint.y, paint);
        canvas.drawLine(leftUpPoint.x + offsetLeftUpPoint.x, leftUpPoint.y
                + this.getDynamicFrameHeight() / 3 + offsetLeftUpPoint.y,
                rightDownPoint.x + offsetRightDownPoint.x,
                leftUpPoint.y + this.getDynamicFrameHeight() / 3
                        + offsetLeftUpPoint.y, paint);
        canvas.drawLine(leftUpPoint.x + offsetLeftUpPoint.x, rightDownPoint.y
                - this.getDynamicFrameHeight() / 3 + offsetRightDownPoint.y,
                rightDownPoint.x + offsetRightDownPoint.x, rightDownPoint.y
                        - this.getDynamicFrameHeight() / 3
                        + offsetRightDownPoint.y, paint);
        // 画外框里的数字
        paint.setARGB(255, 255, 255, 255);
        paint.setStrokeWidth(0);
        paint.setTextSize(10);
        paint.setTextAlign(Align.CENTER);
        canvas.drawText(
                this.getDynamicFrameWidth() + "*"
                        + this.getDynamicFrameHeight(),
                (leftUpPoint.x + offsetLeftUpPoint.x + rightDownPoint.x + offsetRightDownPoint.x) / 2,
                (leftUpPoint.y + offsetLeftUpPoint.y + rightDownPoint.y
                        + offsetRightDownPoint.y + 10) / 2, paint);

没有什么说的,大家只要注意一下线条和数字与中间框的坐标关系就可以了,代码上提到的:getDynamicFrameWidth()和getDynamicFrameHeight()这两个方法,后面也会说明的。

 

再看仔细看一下中间框的外围的情况,像是有一种透明黒的效果,那就对了,这也是一种效果哦,也需要“画”的哦。

还是注意分析与中间框的坐标关系,代码如下咯:

// 画内框外围
paint.setARGB(180, 0, 0, 0);
Rect top = new Rect(0, 0, width, leftUpPoint.y + offsetLeftUpPoint.y);
Rect bottom = new Rect(0, rightDownPoint.y + offsetRightDownPoint.y,width, height);
Rect left = new Rect(0, leftUpPoint.y + offsetLeftUpPoint.y,leftUpPoint.x + offsetLeftUpPoint.x, rightDownPoint.y + offsetRightDownPoint.y); 
Rect right = new Rect(rightDownPoint.x + offsetRightDownPoint.x, leftUpPoint.y + offsetLeftUpPoint.y, width, rightDownPoint.y + offsetRightDownPoint.y); 
canvas.drawRect(top, paint);
canvas.drawRect(bottom, paint); 
canvas.drawRect(left, paint); 
canvas.drawRect(right, paint);


静态的问题已经基本处理完了,下面我们要把拖动和放大缩小这两动态问题考虑进来。
那就需要我们重写View的onTouchEvent()这个方法,我们要实现整个效果全在这个方法里呢。
第一步,我要将这个方法的返回值设置成true,否则就接收不到后面的ACTION_MOVE和ACTION_UP这两个事件了。要是这样就悲剧了大哭
第二步,在设置返回值之前,要执行一下this.invalidate();这个方法,因为View的onDraw()方法是被动的,只有当View无效的时候才会执行。
预热一下,说明一下我们需要东西:
a:onTouchEvent()方法的框架,即能处理ACTION_DOWN、ACTION_MOVE和ACTION_UP三种事件。
b:记录leftUpPoint和rightDownPoint两个点的偏移量offsetLeftUpPoint和offsetRightDownPoint
c:记录onTouchEvent()上一次点击的坐标lastPoint,在执行完ACTION_DOWN事件,再执行ACTION_MOVE事件时会用到。
d:六种动作事件的标识符EVENT_NONE = 0, EVENT_MOVE = 1,            EVENT_SCALE_LEFTUP = 2, EVENT_SCALE_LEFTDOWN = 3,            EVENT_SCALE_RIGHTUP = 4, EVENT_SCALE_RIGHTDOWN = 5;及它们的掌控件变量eventType
e:还有那四个取得中间框长和宽和方法

private int getDynamicFrameWidth() 
        return (rightDownPoint.x + offsetRightDownPoint.x)
                - (leftUpPoint.x + offsetLeftUpPoint.x);
    

    private int getDynamicFrameHeight() 
        return (rightDownPoint.y + offsetRightDownPoint.y)
                - (leftUpPoint.y + offsetLeftUpPoint.y);
    

什么是又动态呢?在onDraw()方法用到长和宽就是动态。关于这一点,大家
在仔细想一想就会明白了。不用我多说什么,我把整个onTouchEvent()方法里的代码贴上来,大家看一下就会明白了,

/*
     * 接收触屏事件
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) 
        // TODO Auto-generated method stub
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) 
        case MotionEvent.ACTION_DOWN:
            handleActionDown(x, y);
            break;
        case MotionEvent.ACTION_MOVE:
            handleActionMove(x, y);
            break;
        case MotionEvent.ACTION_UP:
            handleActionUp();
            break;
        
        this.invalidate();
        return true;
    
/**
     * 得到eventType事件类型的值和lastPoint坐标点
     * 
     * @param x
     *            x坐标
     * @param y
     *            y坐标
     */
    private void handleActionDown(int x, int y) 
        // move
        if (leftUpPoint.x < x && x < rightDownPoint.x && leftUpPoint.y < y
                && y < rightDownPoint.y) 
            lastPoint = new Point(x, y);
            eventType = EVENT_MOVE;
            // leftup
         else if (Math.abs(x - leftUpPoint.x) < DOT_RADIO
                && Math.abs(y - leftUpPoint.y) < DOT_RADIO) 
            lastPoint = new Point(x, y);
            eventType = EVENT_SCALE_LEFTUP;
            // leftdown
         else if (Math.abs(x - leftUpPoint.x) < DOT_RADIO
                && Math.abs(y - rightDownPoint.y) < DOT_RADIO) 
            lastPoint = new Point(x, y);
            eventType = EVENT_SCALE_LEFTDOWN;
            // rightup
         else if (Math.abs(x - rightDownPoint.x) < DOT_RADIO
                && Math.abs(y - leftUpPoint.y) < DOT_RADIO) 
            lastPoint = new Point(x, y);
            eventType = EVENT_SCALE_RIGHTUP;
            // rightdown
         else if (Math.abs(x - rightDownPoint.x) < DOT_RADIO
                && Math.abs(y - rightDownPoint.y) < DOT_RADIO) 
            lastPoint = new Point(x, y);
            eventType = EVENT_SCALE_RIGHTDOWN;

         else 
            eventType = EVENT_NONE;
        
    

    /**
     * 根据eventType进行处理
     * 
     * @param x
     *            x坐标
     * @param y
     *            y坐标
     */
    private void handleActionMove(int x, int y) 
        switch (eventType) 
        case EVENT_MOVE:
            offsetLeftUpPoint.x = x - lastPoint.x;
            offsetLeftUpPoint.y = y - lastPoint.y;
            moveRestriction();
            offsetRightDownPoint.x = offsetLeftUpPoint.x;
            offsetRightDownPoint.y = offsetLeftUpPoint.y;
            break;
        case EVENT_SCALE_LEFTUP:
            offsetLeftUpPoint.x = x - lastPoint.x;
            offsetLeftUpPoint.y = y - lastPoint.y;
            leftUpScaleRestriction();
            offsetRightDownPoint.x = 0;
            offsetRightDownPoint.y = 0;
            break;
        case EVENT_SCALE_LEFTDOWN:
            offsetLeftUpPoint.x = x - lastPoint.x;
            offsetRightDownPoint.y = y - lastPoint.y;
            leftDownScaleRestriction();
            offsetLeftUpPoint.y = 0;
            offsetRightDownPoint.x = 0;
            break;
        case EVENT_SCALE_RIGHTUP:
            offsetRightDownPoint.x = x - lastPoint.x;
            offsetLeftUpPoint.y = y - lastPoint.y;
            rightUpScaleRestriction();
            offsetRightDownPoint.y = 0;
            offsetLeftUpPoint.x = 0;
            break;
        case EVENT_SCALE_RIGHTDOWN:
            offsetRightDownPoint.x = x - lastPoint.x;
            offsetRightDownPoint.y = y - lastPoint.y;
            rightDownScaleRestriction();
            offsetLeftUpPoint.x = 0;
            offsetLeftUpPoint.y = 0;
            break;
        case EVENT_NONE:
            break;
        

    

    /**
     * 进行复位
     */
    private void handleActionUp() 
        leftUpPoint.x += offsetLeftUpPoint.x;
        leftUpPoint.y += offsetLeftUpPoint.y;
        rightDownPoint.x += offsetRightDownPoint.x;
        rightDownPoint.y += offsetRightDownPoint.y;

        offsetLeftUpPoint.x = 0;
        offsetLeftUpPoint.y = 0;
        offsetRightDownPoint.x = 0;
        offsetRightDownPoint.y = 0;
        eventType = EVENT_NONE;
    

    /**
     * 移动限制
     */
    private void moveRestriction() 
        if (leftUpPoint.x + offsetLeftUpPoint.x < 0) 
            offsetLeftUpPoint.x = -leftUpPoint.x;
         else if (leftUpPoint.x + offsetLeftUpPoint.x > this.getWidth()
                - (rightDownPoint.x - leftUpPoint.x)) 
            offsetLeftUpPoint.x = this.getWidth()
                    - (rightDownPoint.x - leftUpPoint.x) - leftUpPoint.x;
        
        if (leftUpPoint.y + offsetLeftUpPoint.y < 0) 
            offsetLeftUpPoint.y = -leftUpPoint.y;
         else if (leftUpPoint.y + offsetLeftUpPoint.y > this.getHeight()
                - (rightDownPoint.y - leftUpPoint.y)) 
            offsetLeftUpPoint.y = this.getHeight()
                    - (rightDownPoint.y - leftUpPoint.y) - leftUpPoint.y;
        
    

    /**
     * 左上缩放限制
     */
    private void leftUpScaleRestriction() 
        if (leftUpPoint.x + offsetLeftUpPoint.x < 0) 
            offsetLeftUpPoint.x = -leftUpPoint.x;
        
        if (rightDownPoint.x - (leftUpPoint.x + offsetLeftUpPoint.x) < FRAME_MIN_WIDTH) 
            offsetLeftUpPoint.x = rightDownPoint.x - leftUpPoint.x
                    - FRAME_MIN_WIDTH;
        

        if (leftUpPoint.y + offsetLeftUpPoint.y < 0) 
            offsetLeftUpPoint.y = -leftUpPoint.y;
        
        if (rightDownPoint.y - (leftUpPoint.y + offsetLeftUpPoint.y) < FRAME_MIN_HEIGHT) 
            offsetLeftUpPoint.y = rightDownPoint.y - leftUpPoint.y
                    - FRAME_MIN_HEIGHT;
        
    

    /**
     * 左下缩放限制
     */
    private void leftDownScaleRestriction() 
        if (leftUpPoint.x + offsetLeftUpPoint.x < 0) 
            offsetLeftUpPoint.x = -leftUpPoint.x;
        
        if (rightDownPoint.x - (leftUpPoint.x + offsetLeftUpPoint.x) < FRAME_MIN_WIDTH) 
            offsetLeftUpPoint.x = rightDownPoint.x - leftUpPoint.x
                    - FRAME_MIN_WIDTH;
        
        if (rightDownPoint.y + offsetRightDownPoint.y > this.getHeight()) 
            offsetRightDownPoint.y = this.getHeight() - rightDownPoint.y;
        
        if ((rightDownPoint.y + offsetRightDownPoint.y) - leftUpPoint.y < FRAME_MIN_HEIGHT) 
            offsetRightDownPoint.y = FRAME_MIN_HEIGHT + leftUpPoint.y
                    - rightDownPoint.y;
        
    

    /**
     * 右上缩放限制
     */
    private void rightUpScaleRestriction() 
        if (rightDownPoint.x + offsetRightDownPoint.x > this.getWidth()) 
            offsetRightDownPoint.x = this.getWidth() - rightDownPoint.x;
        
        if ((rightDownPoint.x + offsetRightDownPoint.x) - leftUpPoint.x < FRAME_MIN_WIDTH) 
            offsetRightDownPoint.x = FRAME_MIN_WIDTH + leftUpPoint.x
                    - rightDownPoint.x;
        
        if (leftUpPoint.y + offsetLeftUpPoint.y < 0) 
            offsetLeftUpPoint.y = -leftUpPoint.y;
        
        if (rightDownPoint.y - (leftUpPoint.y + offsetLeftUpPoint.y) < FRAME_MIN_HEIGHT) 
            offsetLeftUpPoint.y = rightDownPoint.y - leftUpPoint.y
                    - FRAME_MIN_HEIGHT;
        
    

    /**
     * 右下缩放限制
     */
    private void rightDownScaleRestriction() 

        if (rightDownPoint.x + offsetRightDownPoint.x > this.getWidth()) 
            offsetRightDownPoint.x = this.getWidth() - rightDownPoint.x;

        

        if ((rightDownPoint.x + offsetRightDownPoint.x) - leftUpPoint.x < FRAME_MIN_WIDTH) 
            offsetRightDownPoint.x = FRAME_MIN_WIDTH + leftUpPoint.x
                    - rightDownPoint.x;
        

        if (rightDownPoint.y + offsetRightDownPoint.y > this.getHeight()) 
            offsetRightDownPoint.y = this.getHeight() - rightDownPoint.y;
        

        if ((rightDownPoint.y + offsetRightDownPoint.y) - leftUpPoint.y < FRAME_MIN_HEIGHT) 
            offsetRightDownPoint.y = FRAME_MIN_HEIGHT + leftUpPoint.y
                    - rightDownPoint.y;
        
     

奉上源码下载地址:http://download.csdn.net/detail/ihrthk/4509509

费话不多说了,有什么看不懂的,也可以在博客下面留言:






以上是关于仿美图秀秀的图片剪切的主要内容,如果未能解决你的问题,请参考以下文章

Android绘图机制 Demo(简单完成美图秀秀的滤镜)

安卓怎么用美图秀秀将图片的四个角做成的圆角?

美图秀秀api实现图片的裁剪及美化

怎么从视频中提取一张照片

怎么用美图秀秀将图片的四个角做成这样的圆角?

为啥图片经过美图秀秀修改以后就变大了? 我的图片上上水印之后就 超过1M了