Android 自定义View :虚线矩形

2023-11-06

预览效果:

 涉及参数:

斜线起点坐标(斜线可以忽略)
斜线终点坐标(斜线可以忽略)
矩形左上角坐标
矩形右下角坐标

其中,前两个参数用于绘制预览效果中矩形上方的斜线,如果不需要可以移除。

本案例涉及视频外一个点指向视频内某块区域,因此参数略微复杂,除斜线起点坐标为实际坐标外,其他三个参数为百分比,例如矩形左上角坐标(0.1,0.1)表示位于相对于视频左上角0.1*weight,0.1*height处。

自定义View代码:

package com.example.movie;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;

public class DashLineView extends View {

    private static final String TAG = "DashLineView";
    private Paint mPaint;
    private Path mPath;
    private int startX;
    private int startY;
    private float endX;
    private float endY;
    private float LUX;
    private float LUY;
    private float RDX;
    private float RDY;
    private int VIDEO_WIDTH = 1200;
    private int VIDEO_MARGIN_LEFT = 350;
    private int VIDEO_MARGIN_TOP = 200;



    public DashLineView(Context context, AttributeSet attrs) {

        super(context, attrs);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mPaint.setColor(Color.GRAY);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(3);
        //线段15px,间隔5px,偏移0
        mPaint.setPathEffect(new DashPathEffect(new float[] {15, 5}, 0));

        mPath = new Path();


        TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.main);
        //从xml中获取参数
        startX = ta.getInteger(R.styleable.main_startX, 0);
        startY = ta.getInteger(R.styleable.main_startY, 0);

        LUX = ta.getFloat(R.styleable.main_rectLUX, 1);
        RDX = ta.getFloat(R.styleable.main_rectRDX, 1);
        endX = ta.getFloat(R.styleable.main_endX, 1);
        LUY = ta.getFloat(R.styleable.main_rectLUY, 1);
        RDY = ta.getFloat(R.styleable.main_rectRDY, 1);
        endY = ta.getFloat(R.styleable.main_endY, 1);
        ta.recycle();
    }


    @Override

    protected void onDraw(Canvas canvas) {
        // 获得视频的真实宽高
        int realWidth = MovieFragment.getVideoWidth();
        int realHeight = MovieFragment.getVideoHeight();
        // 实际视频view的高度计算
        int height = (int) (1.0 * VIDEO_WIDTH / realWidth * realHeight);
        int width = VIDEO_WIDTH;
        //除斜线左上角外,其他坐标由视频view的相对坐标转为实际坐标
        int rectLUX = VIDEO_MARGIN_LEFT + (int) (LUX * width);
        int rectRDX = VIDEO_MARGIN_LEFT + (int) (RDX * width);
        int rectEndX = VIDEO_MARGIN_LEFT + (int) (endX * width);
        int rectLUY = VIDEO_MARGIN_TOP + (int) (LUY * height);
        int rectRDY = VIDEO_MARGIN_TOP + (int) (RDY * height);
        int rectEndY = VIDEO_MARGIN_TOP + (int) (endY * height);
        // 斜线,如果不需要,将这段注释即可
        mPath.reset();
        mPath.moveTo(startX, startY);
        mPath.lineTo(rectEndX, rectEndY);
        canvas.drawPath(mPath, mPaint);
        // 矩形上横线
        mPath.reset();
        mPath.moveTo(rectLUX, rectLUY);
        mPath.lineTo(rectRDX, rectLUY);
        canvas.drawPath(mPath, mPaint);
        // 矩形右竖线
        mPath.reset();
        mPath.moveTo(rectRDX, rectLUY);
        mPath.lineTo(rectRDX, rectRDY);
        canvas.drawPath(mPath, mPaint);
        // 矩形下横线
        mPath.reset();
        mPath.moveTo(rectLUX, rectRDY);
        mPath.lineTo(rectRDX, rectRDY);
        canvas.drawPath(mPath, mPaint);
        // 矩形左竖线
        mPath.reset();
        mPath.moveTo(rectLUX, rectLUY);
        mPath.lineTo(rectLUX, rectRDY);
        canvas.drawPath(mPath, mPaint);

    }
}

对应xml中加载自定义view并设置对应参数:

<com.example.movie.DashLineView
    android:id="@+id/dashline"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:startX="300"
    app:startY="1050"
    app:endX="0.15"
    app:endY="0.9"
    app:rectLUX="0.1"
    app:rectLUY="0.5"
    app:rectRDX="0.2"
    />

在values文件夹下对各个参数(属性)进行定义:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="main">
        <attr name="startX" format="integer" />
        <attr name="startY" format="integer" />
        <attr name="endX" format="float" />
        <attr name="endY" format="float" />
        <attr name="rectLUX" format="float" />
        <attr name="rectLUY" format="float" />
        <attr name="rectRDX" format="float" />
        <attr name="rectRDY" format="float" />
    </declare-styleable>
</resources>

最终效果:

PS:由于获取视频尺寸需要prepared才给到,此时 DashLineView已经create和onMeasure,只能在onDraw时才能进行具体坐标的计算。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 自定义View :虚线矩形 的相关文章

  • APK META-INF/library_release.kotlin_module 中复制的重复文件

    我最近通过 JitPack 添加了两个 Android 库 但出现以下错误 Duplicate files copied in APK META INF library release kotlin module 我已经清除了缓存 并尝试使
  • 如何使用 Android 版 Facebook 同步的联系人图片

    我的手机上安装了 Android 版 Facebook 它会自动将联系人列表中人员的 FB 个人资料图片同步到我的手机 我想在我访问的应用程序中使用这些图片ContactsContract PhoneLookup 我真的需要 Faceboo
  • Sqlite 查询检查 - 小于和大于

    return mDb query DATABASE TABLE new String KEY ROWID KEY LEVEL KEY LEVEL gt 3 lt 5 null null null null 我究竟做错了什么 它返回的值全部高
  • 如何使用 (a)smack 在 Android 上保持 XMPP 连接稳定?

    我使用适用于 Android 的 asmack android 7 beem 库 我有一个后台服务正在运行 例如我的应用程序保持活动状态 但 XMPP 连接迟早会在没有任何通知的情况下消失 服务器表示客户端仍然在线 但没有发送或接收数据包
  • Android,让文本切换器成为中心?

    如何集中我的文本切换器 我尝试过设置重力 但似乎不起作用 ts setFactory new ViewFactory public View makeView TextView t new TextView this t setTypefa
  • Android Studio磁盘空间不足如何解决?

    我随机收到此错误 并且不确定为什么 Android Studio 的磁盘空间变低 Android Studio 系统目录分区磁盘空间不足 Update 此应用程序安装在运行 10 10 1 的 Mac 上 具有 251GB 内部存储和占用
  • Android,语言文件不起作用

    我现在正在创建一个 Android 应用程序 并尝试为我的母语添加语言文件 但在某种程度上 这对我不起作用 我尝试在两部不同的手机中加载该应用程序 但结果相同 之前创建过语言文件 效果良好 但这次不行 手机设置为瑞典语 语言文件适用于我创建
  • android studio 底部工具栏的“运行”选项卡消失了

    Android Studio 底部工具栏中曾经有一个 运行 选项卡 但该选项卡不再显示 怎么把它带回来 请检查下图以了解它消失之前的位置 Run 选项卡曾经位于 TODO 选项卡之前的红色圆圈中 查看 gt 工具窗口 gt 运行 Or us
  • 安卓;在 AdapterViewFlipper 上设置输入/输出动画:未知的动画师名称翻译

    我有一些非常简单的动画 可以与 ViewFlipper 完美配合 但如果我尝试在 AdapterViewFlipper 输入 输出上设置它们 我会收到运行时错误 未知的动画师名称翻译 查看每个方法的相应方法 看起来 ViewFlipper
  • NullPointerException org.chromium.android_webview.AwContents$AwViewMethodsImpl.onDragEvent

    大约 10 天前 我的应用程序开始记录此异常 在开发控制台上看到 java lang NullPointerException at org chromium android webview AwContents AwViewMethods
  • 如何在Firebase Android应用程序中分离两个不同的用户?

    我有一个应用程序 有两种不同类型的用户 一种是教师 第二种是普通用户 如果普通会员登录 他会去normal memberActivity如果他是教师会员 他会去Teacher memberActivity 我如何在登录活动中执行此操作 我的
  • 来自外部 XML 的 Android 本地化

    是否可以使用从服务接收到的 XML 在运行时翻译 Android 应用程序 如果可能的话 请有人指出我正确的方向 谢谢 Warning 我读到的所有内容都表明 让您的应用程序更改语言不是一个好主意 因为 Android 框架不支持它 并且可
  • 基于浏览器的IDE? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 对基本适配器类及其功能的疑问

    我正在尝试自定义列表视图 我使用数组列表添加对象列表 并将其发送到扩展基本适配器的类 当我扩展基本适配器类时 它实现了一些方法 例如 getView 等 在 getView 中 我将其发送到将名称 数据 分配给 XML 格式的自定义菜单的类
  • 如何在Android中隐藏应用程序标题? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我想隐藏应用程序标题栏 您可以通过编程来完成 import android app Activity import android os
  • 找不到资源矢量绘图的异常

    我将在某些设备上运行我的应用程序 其崩溃日志如下 01 04 16 54 02 206 7466 7466 com lawnmowers E AndroidRuntime FATAL EXCEPTION main Process com l
  • 如何用 XML 制作双渐变(类似 iphone)

    如何使用 XML 制作这种可绘制渐变 我可以做一个从颜色 A 到颜色 B 的简单渐变 但我不知道如何在同一个可绘制对象中组合两个渐变 我终于找到了一个带有图层列表的解决方案 这对我来说已经足够好了
  • 如何手动添加Android Studio依赖

    我多次尝试向我的项目添加依赖项 但每次都会出现错误 我想添加它们的依赖项是 de hdodenhof circleimageview 1 3 0 and com github bumptech glide glide 3 6 1 所以我想下
  • Android:列“_id”不存在

    我收到这个错误 IllegalArgumentException 列 id 不存在 当使用SimpleCursorAdapter从我的数据库中检索 该表确实有这个 id柱子 注意到这是一个常见问题 我尝试根据网上的一些解决方案来解决它 但它
  • 将 firebase 消息传递添加到 flutter android 项目时出现依赖错误

    我已将 firebase 消息传递添加到我的 Flutter 项目中 在 iOS 上运行良好 在 Android 上运行时出现错误 Android dependency androidx localbroadcastmanager loca

随机推荐

  • spring事件发布

    最近一个需求 接口监控异常 需要进行一连串逻辑处理 又新加需要给运维人员发短信 异步处理 不能影响源代码逻辑 因此用到事件发布器 在事件驱动中有三个比较重要的组件 Event 发布的事件对象 EventPublisher 事件发布对象 Ev
  • 姓名 抽奖 ppt 模板_PPT中制作姓名滚动抽奖小动画

    想看视频教程的直接拉到文章尾部观看 本次教程教大家如何简单制作姓名滚动抽奖的小动画 效果如下 进入幻灯片播放界面后 在页面任意位置单击鼠标即可开始抽奖 再单击一次鼠标暂停 再单击一次鼠标还可以重新开始 下面来看一下如何制作 制作过程中主要使
  • k8s之Ingress篇七层代理

    Ingress介绍 Ingress官网定义 Ingress可以把进入到集群内部的请求转发到集群中的一些服务上 从而可以把服务映射到集群外部 Ingress 能把集群内Service 配置成外网能够访问的 URL 流量负载均衡 提供基于域名访
  • Unity 连接WebSocket(ws://)服务器

    Unity 连接ws 不用任何插件 忙活了一天终于搞定了 一直连接不上 原来是没有添加header 代码比较简单 直接贴出来普度众生 using System using System Net WebSockets using System
  • 爬虫学习心得

    在python环境中对小说进行爬取 一般需要安装爬虫所需的第三方库 目前我所使用的为BS4和Requests BS4库安装 Beautiful Soup 简称 BS4 其中 4 表示版本号 是一个 Python 第三方库 它可以从 HTML
  • 图解通信原理与案例分析-13:无线对讲机案例--频率调制实现语音点对点无线通信

    前言 在 无线调幅广播案例 中 拆解了通过幅度调制AM实现点对多点广播通信的基本原理 本文 将通过无线对讲机的案例 拆解了通过频率调制FM实现点对多点广播通信的基本原理 本文的重点在 1 频率调制与解调的基本原理 2 频率调制与幅度调制的本
  • nvm常用命令有哪些?nvm如何切换node版本?nvm如何下载node?nvm安装包

    之前公司有很多老项目 需要切换node低版本才能正常使用 但是还有使用node高版本新项目 总不能每次更换项目就卸载重装对应版本的node 所以就使用了nvm来管理node版本 每次使用时 nvm命令就记得很清楚 可是长时间不使用 就会有点
  • Java方法的重载

    方法的重载 函数名相同 形式参数不同 方法重载的规则 1 方法名称必须相同 2 参数列表必须不同 个数 或者 参数类型 或者 排列顺序 3 方法的返回类型可以相同也可以不相同 4 仅仅返回类型不同不足以成为方法的重载 方法名称相同时 编译器
  • C++实践之Qt学习(五):Qt设计器介绍、信号和槽机制

    文章目录 Qt设计器 对象树 信号和槽 信号和槽机制 设计器上添加信号与槽 方式1 方式2 Qt设计器 分为几个区域 控件 部件区 界面编辑区 动作编辑 信号槽编辑区 对象区 对象属性区 部件区又分为几类 Layouts 布局 Spacer
  • 图像综合处理小设计实验—opencv背景分割,硬币检测

    图像综合处理小设计 opencv背景分割 硬币检测 一 机器视觉图像的目标与背景的分割与提取 1 主要要求 对输入图像可以达到目标和背景的分割 建议方法 1 将已知图像进行消噪处理 2 对彩色图像进行目标和背景分析 3 通过阈值法将图像进行
  • 【Vue2.0源码学习】模板编译篇-模板解析(代码生成阶段)

    文章目录 1 前言 2 如何根据AST生成render函数 3 回归源码 3 1 元素节点 3 2 文本节点 3 3 注释节点 4 总结 1 前言 经过前几篇文章 我们把用户所写的模板字符串先经过解析阶段解析生成对应的抽象语法树AST 接着
  • VMware Workstation 17 Pro的下载&&安装&&使用

    目录 一 下载 二 安装 三 检查网络连接 方式一 简便版 方式二 麻烦版 四 使用 创建虚拟机 使用命令 快照的使用 拍摄快照 恢复快照 克隆虚拟机 移除虚拟机 一 下载 下载地址 Windows 虚拟机 Workstation Pro
  • 14-堆排序

    堆 Heap 是一种常见的数据结构 常用于存储数据 其本质上是一棵完全二叉树 下面我们来看看如何用数组实现堆结构及其相关功能 堆的定义 首先来看一下堆的存储结构 堆可以看成是一颗完全二叉树 首先什么是二叉树 借助百度中的解释 二叉树 bin
  • arXiv是个什么东西?

    arXiv只是个提交论文预印本 preprint 的平台 而且里面的论文都没有经过同行评审 peer review 所以文章质量参差不齐 比较有名的计算机检索数据库DBLP数据库可以检索arXiv里的文章 DBLP把arXiv归类为非正式发
  • opencv 学习:reshape函数

    在opencv中 reshape函数比较有意思 它既可以改变矩阵的通道数 又可以对矩阵元素进行序列化 非常有用的一个函数 函数原型 C Mat Mat reshape int cn int rows 0 const 参数比较少 但设置的时候
  • BUAA_C程序括号匹配检查

    问题描述 编写一程序检查C源程序文件中 等括号是否匹配 并输出第一个检测到的不匹配的括号及所对应括号所在的行号 程序中只有一个括号不匹配 注意 1 除了括号可能不匹配外 输入的C源程序无其它语法错误 2 字符常量 字符串常量及注释中括号不应
  • 基于近半年Twitter与Github趋势分析_12大分类500+ChatGPT最新开源GitHub存储库(涵盖ChatGPT开发全框架、全编程语言及教程)——每周更新

    目录 前言 令人惊叹的开源ChatGPT资源 Awesome lists 提示工程 聊天机器人 浏览器扩展及插件 CLIs命令行界面标准应用程序 Reimplementations重实现模型 教程 NLP自然语言处理 Langchain U
  • Vue-自定义指令

    Vue 自定义指令 1 什么是自定义指令 vue 官方提供了 v text v for v model v if 等常用的指令 除此之外vue 还允许开发者自定义指令 2 自定义指令的分类 私有自定义指令 在每个vue 组件中 可以在dir
  • Safari开发者工具

    Safari开发者工具 1 开发者功能 2 开发者功能可以干什么 2 1 捕获模拟器的请求 1 开发者功能 Safari gt 首选项 gt 高级 gt 开启 在菜单栏中显示 开发 菜单 2 开发者功能可以干什么 2 1 捕获模拟器的请求
  • Android 自定义View :虚线矩形

    预览效果 涉及参数 斜线起点坐标 斜线可以忽略 斜线终点坐标 斜线可以忽略 矩形左上角坐标 矩形右下角坐标 其中 前两个参数用于绘制预览效果中矩形上方的斜线 如果不需要可以移除 本案例涉及视频外一个点指向视频内某块区域 因此参数略微复杂 除