IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 创造一款安卓自定义控件_任意4顶点裁剪框 -> 正文阅读

[移动开发]创造一款安卓自定义控件_任意4顶点裁剪框

最终效果:

一种可以不规则截取图片的自定义控件

规则描述:

1、 要有三点之间构成了两个线段所组成的角度判断能力,不允许超过180度的角度出现,以免导致出现凹进去的形状。

2、不允许构成线段的端点两年交换导致线条出现相交。

实际构成:

1、裁剪框由4个端点所组成,在这里我使用了顺时针的方向排布了这4个点。

2、对规则1的实施,使用了代码:

其中first到middle是第一条线段端点,middle到end是第二条线条的端点:

    private double linesAngle(PointF first, PointF middle, PointF end) {
        double x1 = first.x - middle.x;
        double x2 = end.x - middle.x;
        double y1 = first.y - middle.y;
        double y2 = end.y - middle.y;
        double dot = x1 * x2 + y1 * y2;
        double det = x1 * y2 - y1 * x2;
        double angle = Math.atan2(det, dot) / Math.PI * 180f;
        return angle;
    }

3、对规则2的实现,使用了简单的判断添加移动偏移值后是否依然满足4个端点依然依次按照顺时针排序即可。结合2的调用,检查代码如下:

   //禁止越界导致线条交叉:
                    switch (mSelectedPoint) {
                        case 0:
                            if (!(mVectorPoint[0].x + dx < mVectorPoint[1].x && mVectorPoint[0].y + dy < mVectorPoint[2].y
                                    && mVectorPoint[0].y + dy < mVectorPoint[3].y)) {
                                return true;
                            }
                            //不允许形成超过180度的角
                            double angle = linesAngle(mVectorPoint[1],
                                    new PointF(mVectorPoint[0].x + dx, mVectorPoint[0].y + dy),
                                    mVectorPoint[3]);
                            if (angle < 0f) {
                                return true;
                            }
                            break;
                        case 1:
                            if (!(mVectorPoint[1].x + dx > mVectorPoint[0].x && mVectorPoint[1].y + dy < mVectorPoint[2].y
                                    && mVectorPoint[1].y + dy < mVectorPoint[3].y)) {
                                return true;
                            }
                            //不允许形成超过180度的角
                            angle = linesAngle(mVectorPoint[0],
                                    new PointF(mVectorPoint[1].x + dx, mVectorPoint[1].y + dy),
                                    mVectorPoint[2]);
                            if (angle > 0f) {
                                return true;
                            }
                            break;
                        case 2:
                            if (!(mVectorPoint[2].x + dx > mVectorPoint[3].x && mVectorPoint[2].y + dy > mVectorPoint[0].y
                                    && mVectorPoint[2].y + dy > mVectorPoint[1].y)) {
                                return true;
                            }
                            angle = linesAngle(mVectorPoint[1],
                                    new PointF(mVectorPoint[2].x + dx, mVectorPoint[2].y + dy),
                                    mVectorPoint[3]);
                            if (angle > 0f) {
                                return true;
                            }
                            break;
                        case 3:
                            if (!(mVectorPoint[3].x + dx < mVectorPoint[2].x && mVectorPoint[3].y + dy > mVectorPoint[0].y
                                    && mVectorPoint[3].y + dy > mVectorPoint[1].y)) {
                                return true;
                            }
                            angle = linesAngle(mVectorPoint[2],
                                    new PointF(mVectorPoint[3].x + dx, mVectorPoint[3].y + dy),
                                    mVectorPoint[0]);
                            if (angle > 0f) {
                                return true;
                            }
                            break;
                    }

4、绘制:

? ? ? ? 4.1、先把图片移动到中间(即控件中点减去图片宽的一半、控件中点减去图片高的一半这对坐标为图片左上角的虚拟(0,0)点,即绘制图片的起始点),并使用较大的透明度绘制它:

            //移动到图片到控件中间并贴图
            Matrix matrix = new Matrix();
            matrix.setTranslate(mWidth / 2f - mBitmap.getWidth() / 2f,
                    mHeight / 2f - mBitmap.getHeight() / 2f);
            matrix.postScale(mScale, mScale, mWidth / 2f, mHeight / 2f);
            mSelectorRectPointPaint.setAlpha(100);
            canvas.drawBitmap(mBitmap, matrix, mSelectorRectPointPaint);
            mSelectorRectPointPaint.setAlpha(255);

? ? ? ? 4.2、绘制选择框后,使用clipPath把选择框的封闭区域作为填充图片的限制区域,再绘制不透明的图片,即可使得选择区域的图片变得更“亮”:

 //绘制选择框:
            if (null != mSelectorRectPointPaint) {
                mSelectorRectPointPaint.setStyle(Paint.Style.FILL);
                Path path = new Path();
                for (int i = 0; i < mVectorPoint.length; i++) {
                    PointF pointF = mVectorPoint[i];
                    if (i == 0) {
                        path.moveTo(pointF.x, pointF.y);
                    } else {
                        path.lineTo(pointF.x, pointF.y);
                    }
                }
                path.lineTo(mVectorPoint[0].x, mVectorPoint[0].y);
                //选择框内的图片透明度为0:
                canvas.save();
                canvas.clipPath(path);
                canvas.drawBitmap(mBitmap, matrix, mSelectorRectPointPaint);
                canvas.restore();
                //绘制选择器边框:
                mSelectorRectPointPaint.setStyle(Paint.Style.STROKE);
                canvas.drawPath(path, mSelectorRectPointPaint);
                mSelectorRectPointPaint.setStyle(Paint.Style.FILL);
                for (PointF pointF : mVectorPoint) {
                    //绘制选择器端点
                    canvas.drawCircle(pointF.x, pointF.y, 30, mSelectorRectPointPaint);
                }
            }

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-04-26 11:52:02  更:2022-04-26 11:52:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 23:43:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码