仿美图秀秀的图片剪切

news/2024/11/18 3:45:49/

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

刚一眼打量过去,吸引我们的就是那四个大点。就从它开始吧,目前看来这个大点是一个图片,当点击下去的时候有加亮的效果,可能这又是一张图片。我们先不要考虑这些,先把它当做一个普通的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()方法里的代码贴上来,大家看一下就会明白了,大笑

/** 接收触屏事件*/@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubint 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) {// moveif (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

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







http://www.ppmy.cn/news/694654.html

相关文章

superset

应用场景 数据进入到数据库中,查询只能看到一行行的数据,最好是可以通过图形的方式将数据形象化的展示出来,通过图形进行组合分析,仪表分析,地图分析,多维分析等等,更加详细的通过图形展示数据,展示规律,展示分析! 操作步骤 # yum install gcc libffi-devel python-d…

Supreme Number

//特别坑 371&#xff0c; 713&#xff0c; 731 都不是素数 /*#include <iostream> #include <math.h> using namespace std; int a[] {1, 2, 3, 5, 7,11, 13, 17, 23, 31, 37, 53, 71, 73, 113, 131, 137, 173, 311, 317, 371, 713, 731}; int isPrime(lon…

SuperSlide图片切换

SuperSlide图片切换 There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. /*SuperSlide图片切换*/jQuery(".focusBox").slide({mainCell: ".pic",effect: "fold",a…

在线生成supreme风格图片

原文链接&#xff1a; https://justforuse.github.io/blog/zh-cn/2018/12/supreme-image/ 最近被本山大叔鬼畜洗脑了?&#xff1a;https://www.bilibili.com/video/av19390801?fromsearch&seid2488280777914879673 supreme风格图片也是土潮土潮的&#xff0c;所以就来做…

P4824 [USACO15FEB] Censoring S

请读者在阅读前充分理解KMP与其失配函数的意义。 题目描述 原题来自&#xff1a;USACO 2015 Feb. Silver 给出两个字符串 S 和 T&#xff0c;每次从前往后找到 S 的一个子串 AT 并将其删除&#xff0c;空缺位依次向前补齐&#xff0c;重复上述操作多次&#xff0c;直到 S 串…

Golang:cannot find main module; see ‘go help modules‘解决

出现这个的原因就是之前在Golang语言介绍、环境搭建以及编译工具&#xff08; CDN 加速代理&#xff09;https://mp.csdn.net/mp_blog/creation/editor/131431492 这个部分配置CDN加速代理的时候&#xff0c;开启了GO111MODULEon后&#xff1b; go会忽略GOPATH和vendor文件夹&…

电脑html接口显示器不亮,VGA接口连接显示器电脑点不亮

我想把电脑与电视连接&#xff0c;我显卡上有15针VGA、DVI、S端子借接口&#xff0c;电视是数字电视&#xff0c;有15针VGA、S端子&#xff0c;我用S端子连接后图象不好&#xff0c;我想用VGA接口连接&#xff0c;怎么样效果好又经济又简单&#xff1f;我想用显示器玩游戏的同时…

新计算机主板不亮,电脑组装完毕之后点不亮怎么办 新电脑组装好开不了机的解决办法...

这些年&#xff0c;IT百科小编也为大家分享了不少电脑组装图文教程&#xff0c;方便喜欢自己动手装机的朋友参考&#xff0c;不过电脑组装完毕之后&#xff0c;并不是每一个用户都可以一次顺利点亮的&#xff0c;或多或少难免会出现一些开不了机的问题。同时我们也收到一些用户…