Android 自定义View可拖动移动位置及边缘拉伸放大缩小
一.首先说一下定义这样一个View有什么用?在一些app中,需要设置头像,而用户选择的图片可能是使用摄像头拍摄,也可能是选择的相册里面的图片,总之,这样的图片大小不一,就比如在使用某个聊天软件的时候,设置头像,需要对图片进行截取.
要实现这样一个功能,首先,需要分析用户的操作,即用户所点击的View的位置,如下图,我把View分为9个区域,
- 当ACTION_DOWN时如果坐标为1.2.3.4四个区域,则对View进行相应的左上/右上/左下/右下拉伸;
- 当ACTION_DOWN时如果坐标为5.6.7.8四个区域,则分别对上/右/下/左四个方向进行拉伸;
- 当ACTION_DOWN时如果坐标为9这个区域,则对View进行移动;
理论分析完成,下面来看具体实现;
在下面的类中,有五个方法center/left/top/bottom/right分别对应移动/向左拉伸/向上拉伸/向下拉伸/向右拉伸,当Action_down为1-4所在的区域时,组合前面的对应的两个拉伸方法即可,如左上角拉伸则对应执行left+top方法,这也是把四个单独一条边的边缘拉伸独立出来的原因;
在View中,我设定了View的最小宽度和高度,都是200,所以当用户点击边缘进行缩小操作时,能缩小的最小值也就是200;分别在left/top/bottom/right中体现;
/*** @see http://www.cnblogs.com/a284628487/* @author Cj* */ public class DragScaleView extends View implements OnTouchListener {protected int screenWidth;protected int screenHeight;protected int lastX;protected int lastY;private int oriLeft;private int oriRight;private int oriTop;private int oriBottom;private int dragDirection;private static final int TOP = 0x15;private static final int LEFT = 0x16;private static final int BOTTOM = 0x17;private static final int RIGHT = 0x18;private static final int LEFT_TOP = 0x11;private static final int RIGHT_TOP = 0x12;private static final int LEFT_BOTTOM = 0x13;private static final int RIGHT_BOTTOM = 0x14;private static final int CENTER = 0x19;private int offset = 20;protected Paint paint = new Paint();/*** 初始化获取屏幕宽高*/protected void initScreenW_H() {screenHeight = getResources().getDisplayMetrics().heightPixels - 40;screenWidth = getResources().getDisplayMetrics().widthPixels;}public DragScaleView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);setOnTouchListener(this);initScreenW_H();}public DragScaleView(Context context, AttributeSet attrs) {super(context, attrs);setOnTouchListener(this);initScreenW_H();}public DragScaleView(Context context) {super(context);setOnTouchListener(this);initScreenW_H();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);paint.setColor(Color.RED);paint.setStrokeWidth(4.0f);paint.setStyle(Style.STROKE);canvas.drawRect(offset, offset, getWidth() - offset, getHeight()- offset, paint);}@Overridepublic boolean onTouch(View v, MotionEvent event) {int action = event.getAction();if (action == MotionEvent.ACTION_DOWN) {oriLeft = v.getLeft();oriRight = v.getRight();oriTop = v.getTop();oriBottom = v.getBottom();lastY = (int) event.getRawY();lastX = (int) event.getRawX();dragDirection = getDirection(v, (int) event.getX(),(int) event.getY());}// 处理拖动事件 delDrag(v, event, action);invalidate();return false;}/*** 处理拖动事件* * @param v* @param event* @param action*/protected void delDrag(View v, MotionEvent event, int action) {switch (action) {case MotionEvent.ACTION_MOVE:int dx = (int) event.getRawX() - lastX;int dy = (int) event.getRawY() - lastY;switch (dragDirection) {case LEFT: // 左边缘 left(v, dx);break;case RIGHT: // 右边缘 right(v, dx);break;case BOTTOM: // 下边缘 bottom(v, dy);break;case TOP: // 上边缘 top(v, dy);break;case CENTER: // 点击中心-->>移动 center(v, dx, dy);break;case LEFT_BOTTOM: // 左下 left(v, dx);bottom(v, dy);break;case LEFT_TOP: // 左上 left(v, dx);top(v, dy);break;case RIGHT_BOTTOM: // 右下 right(v, dx);bottom(v, dy);break;case RIGHT_TOP: // 右上 right(v, dx);top(v, dy);break;}if (dragDirection != CENTER) {v.layout(oriLeft, oriTop, oriRight, oriBottom);}lastX = (int) event.getRawX();lastY = (int) event.getRawY();break;case MotionEvent.ACTION_UP:dragDirection = 0;break;}}/*** 触摸点为中心->>移动* * @param v* @param dx* @param dy*/private void center(View v, int dx, int dy) {int left = v.getLeft() + dx;int top = v.getTop() + dy;int right = v.getRight() + dx;int bottom = v.getBottom() + dy;if (left < -offset) {left = -offset;right = left + v.getWidth();}if (right > screenWidth + offset) {right = screenWidth + offset;left = right - v.getWidth();}if (top < -offset) {top = -offset;bottom = top + v.getHeight();}if (bottom > screenHeight + offset) {bottom = screenHeight + offset;top = bottom - v.getHeight();}v.layout(left, top, right, bottom);}/*** 触摸点为上边缘* * @param v* @param dy*/private void top(View v, int dy) {oriTop += dy;if (oriTop < -offset) {oriTop = -offset;}if (oriBottom - oriTop - 2 * offset < 200) {oriTop = oriBottom - 2 * offset - 200;}}/*** 触摸点为下边缘* * @param v* @param dy*/private void bottom(View v, int dy) {oriBottom += dy;if (oriBottom > screenHeight + offset) {oriBottom = screenHeight + offset;}if (oriBottom - oriTop - 2 * offset < 200) {oriBottom = 200 + oriTop + 2 * offset;}}/*** 触摸点为右边缘* * @param v* @param dx*/private void right(View v, int dx) {oriRight += dx;if (oriRight > screenWidth + offset) {oriRight = screenWidth + offset;}if (oriRight - oriLeft - 2 * offset < 200) {oriRight = oriLeft + 2 * offset + 200;}}/*** 触摸点为左边缘* * @param v* @param dx*/private void left(View v, int dx) {oriLeft += dx;if (oriLeft < -offset) {oriLeft = -offset;}if (oriRight - oriLeft - 2 * offset < 200) {oriLeft = oriRight - 2 * offset - 200;}}/*** 获取触摸点flag* * @param v* @param x* @param y* @return*/protected int getDirection(View v, int x, int y) {int left = v.getLeft();int right = v.getRight();int bottom = v.getBottom();int top = v.getTop();if (x < 40 && y < 40) {return LEFT_TOP;}if (y < 40 && right - left - x < 40) {return RIGHT_TOP;}if (x < 40 && bottom - top - y < 40) {return LEFT_BOTTOM;}if (right - left - x < 40 && bottom - top - y < 40) {return RIGHT_BOTTOM;}if (x < 40) {return LEFT;}if (y < 40) {return TOP;}if (right - left - x < 40) {return RIGHT;}if (bottom - top - y < 40) {return BOTTOM;}return CENTER;}/*** 获取截取宽度* * @return*/public int getCutWidth() {return getWidth() - 2 * offset;}/*** 获取截取高度* * @return*/public int getCutHeight() {return getHeight() - 2 * offset;} }
二.使用View,如果想要对View进行移动,需要在xml中配置android:clickable="true"属性;
<xxx.DragScaleViewandroid:id="@+id/ds"android:layout_width="180dip"android:layout_height="180dip"android:clickable="true" />
三.效果图,右图是拉伸后的效果
四.关于MotionEvent.getX()和MotionEvent.getRawX()的区别
getX表示触摸点距离View的左边缘的距离,而getRawX表示触摸点距离手机屏幕左侧的距离;
转载于:https://www.cnblogs.com/a284628487/p/3367228.html
Android 自定义View可拖动移动位置及边缘拉伸放大缩小相关推荐
- android 自定义view实现拖动放大缩小_自定义itemClickView
和你一起终身学习,这里是程序员Android 经典好文推荐,通过阅读本文,您将收获以下知识点: 一.自定义View类实现 二.自定义View标签 三.自定义View 布局 四.自定义View 选择器 ...
- android 自定义view实现拖动放大缩小_自定义itemCheckView
阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: 自定义View类实现 自定义View标签 ...
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
首先呢,还是一贯作风,我们先来看看众多应用中的示例:(这种效果是很常见的,可以说应用的必须品.) 搜狐客户端 ...
- android 自定义view滚动条,Android自定义View实现等级滑动条的实例
Android自定义View实现等级滑动条的实例 实现效果图: 思路: 首先绘制直线,然后等分直线绘制点: 绘制点的时候把X值存到集合中. 然后绘制背景图片,以及图片上的数字. 点击事件down的时候 ...
- android 自定义View 视差动画
本系列自定义View全部采用kt **系统: **mac android studio: 4.1.3 **kotlin version:**1.5.0 gradle: gradle-6.5-bin.z ...
- Android自定义View之七色环颜色采集器: 续我未完的大学梦 !
Android自定义View之七色环颜色采集器:续我未完的大学梦!! 一.前言. 在大学期间,看到机智云开源的这个rgb灯,蛮好奇的,这么漂亮的颜色采集,并且可以同步到设备rbg灯颜色,甚是不解!这个 ...
- android自定义View: 九宫格解锁
本系列自定义View全部采用kt 系统:mac android studio: 4.1.3 kotlin version1.5.0 gradle: gradle-6.5-bin.zip 废话不多说,先 ...
- Android自定义View —— TypedArray
在上一篇中Android 自定义View Canvas -- Bitmap写到了TypedArray 这个属性 下面也简单的说一下TypedArray的使用 TypedArray 的作用: 用于从该结 ...
- android自定义view获取控件,android 自定义控件View在Activity中使用findByViewId得到结果为null...
转载:http://blog.csdn.net/xiabing082/article/details/48781489 1. 大家常常自定义view,,然后在xml 中添加该view 组件..如果在 ...
- Android自定义View:ViewGroup(三)
自定义ViewGroup本质是什么? 自定义ViewGroup本质上就干一件事--layout. layout 我们知道ViewGroup是一个组合View,它与普通的基本View(只要不是ViewG ...
最新文章
- DIV+CSS规范命名大全集合
- 高斯混合模型GMM、核心参数、高斯混合模型GMM的数学形式
- spring boot中SpringBootCondition框架
- 如何成为一个合格的 Java程序员
- tomcat 显示访问的ip白名单
- python 速度 memmap_使用python测量文件的读写速度
- Jquery中$(document).ready(function(){ })函数的使用详解
- 2912: 奇怪的加法问题(XOR的加法写法)
- 图:智能手机Android系统的评委专用的比赛打分客户端,开发进行中...
- 92套AE抖音快闪模板(精品)
- word使用技巧---插入图片显示不全的解决方案
- 《算法基础》线性枚举(一)——最值算法
- NLPCC-2019 依存句法分析领域移植评测技术分享(封闭情况下双第一)
- 【赚钱应跟Apple,做大不忘Google】移动开发时代的开发者选择
- openoffice相关命令
- vue 点击打开pdf
- 如何批量压缩pdf文件到最小
- 网易WEB白帽子-WEB安全体系建设
- 找不到 cl.exe 解决办法
- RecyclerView布局中解决edittext监听错乱