电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Android 照片選擇區域功能實現示例

瀏覽:3日期:2022-09-19 09:10:10

實現 Android 的照片選擇區域功能

Android 照片選擇區域功能實現示例

主要有參考 pqpo/SmartCropper

1, 顯示

顯示四條邊和八個點,

八個點: 4 個角和 4 條邊的中點

/* 裁剪區域,0, 左上 -> LeftTop, 1, 右上 -> RightTop,2, 右下 -> RightBottom, 3, 左下 -> LeftBottom*/Point[] mCropPoints;// 4 條邊的中點Point[] mEdgeMidPoints;

繪制

protected void onDrawCropPoint(Canvas canvas) {//繪制蒙版onDrawMask(canvas);//繪制輔助線onDrawGuideLine(canvas);//繪制選區線onDrawLines(canvas);//繪制錨點onDrawPoints(canvas);//繪制放大鏡// ... }

具體繪制部分:

繪制八個點

protected void onDrawPoints(Canvas canvas) {if (!checkPoints(mCropPoints)) { return;}// 繪制 4 個角for (Point point : mCropPoints) { canvas.drawCircle(getViewPointX(point), getViewPointY(point), dp2px(POINT_RADIUS), mPointFillPaint); canvas.drawCircle(getViewPointX(point), getViewPointY(point), dp2px(POINT_RADIUS), mPointPaint);}if (mShowEdgeMidPoint) { setEdgeMidPoints(); // 中間錨點 // 繪制 4 條邊上的中點 for (Point point : mEdgeMidPoints){canvas.drawCircle(getViewPointX(point), getViewPointY(point), dp2px(POINT_RADIUS), mPointFillPaint);canvas.drawCircle(getViewPointX(point), getViewPointY(point), dp2px(POINT_RADIUS), mPointPaint); }} }

繪制 4 條邊上的中點前,

先算出當前 4 條邊上中點的位置

public void setEdgeMidPoints(){// 中點不存在,就新建if (mEdgeMidPoints == null){ mEdgeMidPoints = new Point[4]; for (int i = 0; i < mEdgeMidPoints.length; i++){mEdgeMidPoints[i] = new Point(); }}// 維護 4 個頂點的位置,// 通過頂點的位置,算出邊上中點的位置int len = mCropPoints.length;for (int i = 0; i < len; i++){ // 為了避免極端情況, // 采用 ( 坐標 + 距離的一半 ) 的方式mEdgeMidPoints[i].set(mCropPoints[i].x + (mCropPoints[(i+1)%len].x - mCropPoints[i].x)/2, mCropPoints[i].y + (mCropPoints[(i+1)%len].y - mCropPoints[i].y)/2);} }2, 拖動

拖動分 2 種情況,角點拖拽,中點平移

8 個類型, 4 個角點拖拽,4 個中點平移

enum DragPointType{LEFT_TOP,RIGHT_TOP,RIGHT_BOTTOM,LEFT_BOTTOM,TOP,RIGHT,BOTTOM,LEFT;// 判斷是角點拖拽,不是中點平移public static boolean isEdgePoint(DragPointType type){ return type == TOP || type == RIGHT || type == BOTTOM || type == LEFT;} }

移動的處理

@Override public boolean onTouchEvent(MotionEvent event) {int action = event.getAction();boolean handle = true;switch (action) { case MotionEvent.ACTION_DOWN:// 識別到,當前點mDraggingPoint = getNearbyPoint(event);if (mDraggingPoint == null) { handle = false;}break; case MotionEvent.ACTION_MOVE:// 移動toImagePointSize(mDraggingPoint, event);break; case MotionEvent.ACTION_UP:// 手指抬起,// 操作取消mDraggingPoint = null;break;}// 繪制// 更新完位置后,刷新繪制invalidate();return handle || super.onTouchEvent(event); }

識別到,當前點

private Point getNearbyPoint(MotionEvent event) {// 判斷 4 個角點,可用if (checkPoints(mCropPoints)) { for (Point p : mCropPoints) {// 找出當前的點if (isTouchPoint(p, event)) return p; }}// 判斷 4 個中點可用if (checkPoints(mEdgeMidPoints)) { for (Point p : mEdgeMidPoints){// 找出當前的點if (isTouchPoint(p, event)) return p; }}return null; }

找出當前的點,的方法

private static final float TOUCH_POINT_CATCH_DISTANCE = 15;private boolean isTouchPoint(Point p, MotionEvent event){float x = event.getX();float y = event.getY();float px = getViewPointX(p);float py = getViewPointY(p);double distance = Math.sqrt(Math.pow(x - px, 2) + Math.pow(y - py, 2));// 也就是,判斷距離if (distance < dp2px(TOUCH_POINT_CATCH_DISTANCE)) { return true;}return false; }2.1 ,角點拖拽

先介紹 4 個角點拖拽

private void toImagePointSize(Point dragPoint, MotionEvent event) {if (dragPoint == null) { return;}// 找出當前移動類型,// 是角點拖拽,還是中點平移DragPointType pointType = getPointType(dragPoint);int x = (int) ((Math.min(Math.max(event.getX(), mActLeft), mActLeft + mActWidth) - mActLeft) / mScaleX);int y = (int) ((Math.min(Math.max(event.getY(), mActTop), mActTop + mActHeight) - mActTop) / mScaleY);// 判斷可以移動// ... if (DragPointType.isEdgePoint(pointType)){ // ... // 中點平移} else { // 角點拖拽 // 實現很簡單, // 更新就好了 dragPoint.y = y; dragPoint.x = x;} }

找出當前移動類型,

是角點拖拽,還是中點平移

// 拿采集的點,找出對應的類型private DragPointType getPointType(Point dragPoint){if (dragPoint == null) return null;DragPointType type;// 看,是不是頂點 / 角點if (checkPoints(mCropPoints)) { for (int i = 0; i < mCropPoints.length; i++) {if (dragPoint == mCropPoints[i]) { // 找到了,直接返回 type = DragPointType.values()[i]; return type;} }}// 看,是不是中點if (checkPoints(mEdgeMidPoints)) { for (int i = 0; i < mEdgeMidPoints.length; i++){if (dragPoint == mEdgeMidPoints[i]){ // 找到了,直接返回 type = DragPointType.values()[4+i]; return type;} }}return null; }2.2,中點平移

private void toImagePointSize(Point dragPoint, MotionEvent event) {if (dragPoint == null) { return;}DragPointType pointType = getPointType(dragPoint);int x = // ...int y = // ...// 判斷可以移動// ... if (DragPointType.isEdgePoint(pointType)){ // 中點平移, // 拿到的是,一個偏移向量 int xoff = x - dragPoint.x; int yoff = y - dragPoint.y; moveEdge(pointType, xoff, yoff);} else { // 角點拖拽 // ...} }

拿到偏移向量,修改對應的兩個頂點的坐標

private void moveEdge(DragPointType type, int xoff, int yoff){switch (type){ case TOP:// 這邊的平移,比較簡單// 找到中點,旁邊的兩個焦點// 再移動位置movePoint(mCropPoints[P_LT], 0, yoff);movePoint(mCropPoints[P_RT], 0, yoff);break; case RIGHT:// 右移處理movePoint(mCropPoints[P_RT], xoff, 0);movePoint(mCropPoints[P_RB], xoff, 0);break; case BOTTOM:// 下移處理// ... case LEFT:// 左移處理// ... default: break;} }

簡單的平移代碼

拿到偏移向量, 修改坐標,完事

private void movePoint(Point point, int xoff, int yoff){if (point == null) return;int x = point.x + xoff;int y = point.y + yoff;// 檢查邊界if (x < 0 || x > getDrawable().getIntrinsicWidth()) return;if (y < 0 || y > getDrawable().getIntrinsicHeight()) return;point.x = x;point.y = y; }

中點平移增強

這里的中點平移,拿到平移向量后,

直接添加到中點旁邊的兩個角點上

效果增強為,中點平移,中點旁邊的兩個角點順著兩側邊,做平移計算稍微復雜,

知道中點之前的位置,和中點之后的位置,

知道中點與一角點,所在邊的斜率,

知道此角點的另一邊的斜率

知道角點,平移前的位置,

求解出角點,平移后的位置

這是一個方程式求解網站

變換坐標系,可能簡單些相關 github

demo 的 gradle 配置

到此這篇關于Android 照片選擇區域功能實現示例的文章就介紹到這了,更多相關Android 照片選擇區域內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Android
相關文章:
主站蜘蛛池模板: 正压密封性测试仪-静态发色仪-导丝头柔软性测试仪-济南恒品机电技术有限公司 | 北京开业庆典策划-年会活动策划公司-舞龙舞狮团大鼓表演-北京盛乾龙狮鼓乐礼仪庆典策划公司 | 高低温试验房-深圳高低温湿热箱-小型高低温冲击试验箱-爱佩试验设备 | 金属清洗剂,防锈油,切削液,磨削液-青岛朗力防锈材料有限公司 | 电动卫生级调节阀,电动防爆球阀,电动软密封蝶阀,气动高压球阀,气动对夹蝶阀,气动V型调节球阀-上海川沪阀门有限公司 | Safety light curtain|Belt Sway Switches|Pull Rope Switch|ultrasonic flaw detector-Shandong Zhuoxin Machinery Co., Ltd | 假肢-假肢价格-假肢厂家-河南假肢-郑州市力康假肢矫形器有限公司 | 大型果蔬切片机-水果冬瓜削皮机-洗菜机切菜机-肇庆市凤翔餐饮设备有限公司 | 密集架|电动密集架|移动密集架|黑龙江档案密集架-大量现货厂家销售 | 电机保护器-电动机综合保护器-上海硕吉电器有限公司 | 碎石机设备-欧版反击破-欧版颚式破碎机(站)厂家_山东奥凯诺机械 高低温试验箱-模拟高低温试验箱订制-北京普桑达仪器科技有限公司【官网】 | 艺术涂料_进口艺术涂料_艺术涂料加盟_艺术涂料十大品牌 -英国蒙太奇艺术涂料 | ◆大型吹塑加工|吹塑加工|吹塑代加工|吹塑加工厂|吹塑设备|滚塑加工|滚塑代加工-莱力奇塑业有限公司 | 铝箔-铝板-花纹铝板-铝型材-铝棒管-上海百亚金属材料有限公司 | 篷房|仓储篷房|铝合金篷房|体育篷房|篷房厂家-华烨建筑科技官网 知名电动蝶阀,电动球阀,气动蝶阀,气动球阀生产厂家|价格透明-【固菲阀门官网】 | 贴板式电磁阀-不锈钢-气动上展式放料阀-上海弗雷西阀门有限公司 工业机械三维动画制作 环保设备原理三维演示动画 自动化装配产线三维动画制作公司-南京燃动数字 | 沈阳激光机-沈阳喷码机-沈阳光纤激光打标机-沈阳co2激光打标机 | 河南包装袋厂家_河南真空袋批发价格_河南服装袋定制-恒源达包装制品 | 模型公司_模型制作_沙盘模型报价-中国模型网 | 品牌策划-品牌设计-济南之式传媒广告有限公司官网-提供品牌整合丨影视创意丨公关活动丨数字营销丨自媒体运营丨数字营销 | 隆众资讯-首页_大宗商品资讯_价格走势_市场行情 | 禹城彩钢厂_钢结构板房_彩钢复合板-禹城泰瑞彩钢复合板加工厂 | ZHZ8耐压测试仪-上海胜绪电气有限公司| 臭氧老化试验箱,高低温试验箱,恒温恒湿试验箱,防水试验设备-苏州亚诺天下仪器有限公司 | 复合肥,化肥厂,复合肥批发,化肥代理,复合肥品牌-红四方 | 中药超微粉碎机(中药细胞级微粉碎)-百科 | 丹尼克尔拧紧枪_自动送钉机_智能电批_柔性振动盘_螺丝供料器品牌 | 欧必特空气能-商用空气能热水工程,空气能热水器,超低温空气源热泵生产厂家-湖南欧必特空气能公司 | 陕西视频监控,智能安防监控,安防系统-西安鑫安5A安防工程公司 | 自动焊锡机_点胶机_螺丝机-锐驰机器人 | 带式压滤机_污泥压滤机_污泥脱水机_带式过滤机_带式压滤机厂家-河南恒磊环保设备有限公司 | 工业插头-工业插头插座【厂家】-温州罗曼电气| 次氯酸钠厂家,涉水级次氯酸钠,三氯化铁生产厂家-淄博吉灿化工 | 杰福伦_磁致伸缩位移传感器_线性位移传感器-意大利GEFRAN杰福伦-河南赉威液压科技有限公司 | 苏州西装定制-西服定制厂家-职业装定制厂家-尺品服饰西装定做公司 | 防水套管厂家_刚性防水套管_柔性防水套管_不锈钢防水套管-郑州中泰管道 | SRRC认证_电磁兼容_EMC测试整改_FCC认证_SDOC认证-深圳市环测威检测技术有限公司 | 门禁卡_智能IC卡_滴胶卡制作_硅胶腕带-卡立方rfid定制厂家 | 水冷式工业冷水机组_风冷式工业冷水机_水冷螺杆冷冻机组-深圳市普威机械设备有限公司 | 压力变送器-上海武锐自动化设备有限公司 | 苏州防水公司_厂房屋面外墙防水_地下室卫生间防水堵漏-苏州伊诺尔防水工程有限公司 |