Android视频播放暂停动效的按钮

上来直接给大家搂代码

 

class PlayButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :View(context, attrs, defStyleAttr) {companion object {/** 播放状态 */const val STATE_PLAY: Int = 0/** 暂停状态 */const val STATE_PAUSE: Int = 1}/** 当前状态 */private var currentState: Int = STATE_PAUSE/** 动画时间 */private var animDuration: Intprivate val paint: Paintprivate var viewWidth: Int = 0private var viewHeight: Int = 0private var centerX: Int = 0private var centerY: Int = 0private var circleRadius: Int = 0private var rectF: RectF? = nullprivate var bgRectF: RectF? = nullprivate var fraction: Float = 1fprivate val path: Pathprivate val dstPath: Pathprivate val pathMeasure: PathMeasureprivate var pathLength: Float = 0finit {val typedArray: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.PlayButton)val lineColor: Int = typedArray.getColor(R.styleable.PlayButton_pb_lineColor, Color.WHITE)val lineSize: Int = typedArray.getInteger(R.styleable.PlayButton_pb_lineSize,resources.getDimension(R.dimen.dp_4).toInt())animDuration = typedArray.getInteger(R.styleable.PlayButton_pb_animDuration, 200)typedArray.recycle()// 关闭硬件加速setLayerType(LAYER_TYPE_SOFTWARE, null)paint = Paint(Paint.ANTI_ALIAS_FLAG)paint.style = Paint.Style.STROKEpaint.strokeCap = Paint.Cap.ROUNDpaint.color = lineColorpaint.strokeWidth = lineSize.toFloat()paint.pathEffect = CornerPathEffect(1f)path = Path()dstPath = Path()pathMeasure = PathMeasure()}override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) {super.onSizeChanged(width, height, oldWidth, oldHeight)viewWidth = width * 9 / 10viewHeight = height * 9 / 10circleRadius = width / resources.getDimension(R.dimen.dp_4).toInt()centerX = width / 2centerY = height / 2rectF = RectF((centerX - circleRadius).toFloat(), centerY + 0.6f * circleRadius,(centerX + circleRadius).toFloat(), centerY + 2.6f * circleRadius)bgRectF = RectF(centerX - viewWidth / 2f, centerY - viewHeight / 2f,centerX + viewWidth / 2f, centerY + viewHeight / 2f)path.moveTo((centerX - circleRadius).toFloat(), centerY + 1.8f * circleRadius)path.lineTo((centerX - circleRadius).toFloat(), centerY - 1.8f * circleRadius)path.lineTo((centerX + circleRadius).toFloat(), centerY.toFloat())path.close()pathMeasure.setPath(path, false)pathLength = pathMeasure.length}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {var finalWidthMeasureSpec: Int = widthMeasureSpecvar finalHeightMeasureSpec: Int = heightMeasureSpecwhen (MeasureSpec.getMode(finalWidthMeasureSpec)) {MeasureSpec.AT_MOST, MeasureSpec.UNSPECIFIED ->finalWidthMeasureSpec = MeasureSpec.makeMeasureSpec(resources.getDimension(R.dimen.dp_60).toInt(), MeasureSpec.EXACTLY)MeasureSpec.EXACTLY -> {}}when (MeasureSpec.getMode(finalHeightMeasureSpec)) {MeasureSpec.AT_MOST, MeasureSpec.UNSPECIFIED ->finalHeightMeasureSpec = MeasureSpec.makeMeasureSpec(resources.getDimension(R.dimen.dp_60).toInt(), MeasureSpec.EXACTLY)MeasureSpec.EXACTLY -> {}}setMeasuredDimension(finalWidthMeasureSpec, finalHeightMeasureSpec)}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)canvas.drawCircle(centerX.toFloat(), centerY.toFloat(), viewWidth / 2f, paint)when {fraction < 0 -> {// 弹性部分canvas.drawLine((centerX + circleRadius).toFloat(),centerY - 1.6f * circleRadius + 10 * circleRadius * fraction, (centerX + circleRadius).toFloat(),centerY + (1.6f * circleRadius) + (10 * circleRadius * fraction), paint)canvas.drawLine((centerX - circleRadius).toFloat(), centerY - 1.6f * circleRadius, (centerX - circleRadius).toFloat(), centerY + 1.6f * circleRadius, paint)canvas.drawArc(bgRectF!!, -105f, 360f, false, paint)}fraction <= 0.3 -> {// 右侧直线和下方曲线canvas.drawLine((centerX + circleRadius).toFloat(),centerY - 1.6f * circleRadius + circleRadius * 3.2f / 0.3f * fraction, (centerX + circleRadius).toFloat(),centerY + 1.6f * circleRadius, paint)canvas.drawLine((centerX - circleRadius).toFloat(), centerY - 1.6f * circleRadius, (centerX - circleRadius).toFloat(), centerY + 1.6f * circleRadius, paint)if (fraction != 0f) {canvas.drawArc(rectF!!, 0f, 180f / 0.3f * fraction, false, paint)}canvas.drawArc(bgRectF!!, -105 + 360 * fraction, 360 * (1 - fraction), false, paint)}fraction <= 0.6 -> {// 下方曲线和三角形canvas.drawArc(rectF!!, 180f / 0.3f * (fraction - 0.3f),180 - 180f / 0.3f * (fraction - 0.3f), false, paint)dstPath.reset()pathMeasure.getSegment(0.02f * pathLength,0.38f * pathLength + 0.42f * pathLength / 0.3f * (fraction - 0.3f),dstPath, true)canvas.drawPath(dstPath, paint)canvas.drawArc(bgRectF!!, -105 + 360 * fraction, 360 * (1 - fraction), false, paint)}fraction <= 0.8 -> {// 三角形dstPath.reset()pathMeasure.getSegment(0.02f * pathLength + 0.2f * pathLength / 0.2f * (fraction - 0.6f),0.8f * pathLength + 0.2f * pathLength / 0.2f * (fraction - 0.6f), dstPath, true)canvas.drawPath(dstPath, paint)canvas.drawArc(bgRectF!!, -105 + 360 * fraction, 360 * (1 - fraction), false, paint)}else -> {// 弹性部分dstPath.reset()pathMeasure.getSegment(10 * circleRadius * (fraction - 1), pathLength, dstPath, true)canvas.drawPath(dstPath, paint)}}}/*** 播放状态*/fun play() {if (currentState == STATE_PLAY) {return}currentState = STATE_PLAYval valueAnimator: ValueAnimator = ValueAnimator.ofFloat(1f, 100f)valueAnimator.duration = animDuration.toLong()valueAnimator.interpolator = AnticipateInterpolator()valueAnimator.addUpdateListener { animation: ValueAnimator ->fraction = 1 - animation.animatedFractioninvalidate()}valueAnimator.start()}/*** 暂停状态*/fun pause() {if (currentState == STATE_PAUSE) {return}currentState = STATE_PAUSEval valueAnimator: ValueAnimator = ValueAnimator.ofFloat(1f, 100f)valueAnimator.duration = animDuration.toLong()valueAnimator.interpolator = AnticipateInterpolator()valueAnimator.addUpdateListener { animation: ValueAnimator ->fraction = animation.animatedFractioninvalidate()}valueAnimator.start()}/*** 获取当前状态*/fun getCurrentState(): Int {return currentState}/*** 设置动画时间*/fun setAnimDuration(duration: Int) {animDuration = duration}/*** 设置线条颜色*/fun setLineColor(color: Int) {paint.color = colorinvalidate()}/*** 设置线条大小*/fun setLineSize(size: Int) {paint.strokeWidth = size.toFloat()invalidate()}
}

xml给大家也展示下,图片的话暂不上传了,自己替换

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/black"android:orientation="vertical"><VideoViewandroid:id="@+id/vv_player_view_video"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center"android:keepScreenOn="true" /><FrameLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"android:orientation="vertical"><com.hjq.shape.layout.ShapeFrameLayoutandroid:id="@+id/ll_player_view_top"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="top"android:orientation="horizontal"android:visibility="invisible"app:shape="rectangle"app:shape_angle="270"app:shape_centerColor="@color/black20"app:shape_endColor="@color/transparent"app:shape_startColor="#AA000000"tools:visibility="visible"><androidx.appcompat.widget.AppCompatImageViewandroid:id="@+id/iv_player_view_left"android:layout_width="@dimen/dp_50"android:layout_height="@dimen/dp_50"android:layout_gravity="center_vertical"android:padding="@dimen/dp_10"android:visibility="invisible"app:srcCompat="@drawable/arrows_left_ic"app:tint="@color/white"tools:visibility="visible" /><androidx.appcompat.widget.AppCompatTextViewandroid:id="@+id/tv_player_view_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginHorizontal="@dimen/dp_50"android:ellipsize="marquee"android:gravity="center_horizontal"android:singleLine="true"android:textColor="@color/white"android:textSize="@dimen/sp_17"tools:text="我是视频标题" /></com.hjq.shape.layout.ShapeFrameLayout><com.hjq.widget.view.PlayButtonandroid:id="@+id/iv_player_view_control"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:visibility="invisible"tools:visibility="visible" /><com.hjq.shape.view.ShapeImageViewandroid:id="@+id/iv_player_view_lock"android:layout_width="@dimen/dp_45"android:layout_height="@dimen/dp_45"android:layout_gravity="start|center_vertical"android:layout_marginStart="@dimen/dp_5"android:padding="@dimen/dp_10"android:visibility="invisible"app:shape="oval"app:shape_solidColor="@color/black30"app:shape_solidPressedColor="@color/black60"app:srcCompat="@drawable/video_lock_open_ic"tools:visibility="visible" /><com.hjq.shape.layout.ShapeLinearLayoutandroid:id="@+id/ll_player_view_bottom"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="bottom"android:gravity="center_vertical"android:orientation="horizontal"android:paddingHorizontal="@dimen/dp_15"android:visibility="invisible"app:shape="rectangle"app:shape_angle="90"app:shape_centerColor="@color/black20"app:shape_endColor="@color/transparent"app:shape_startColor="#AA000000"tools:visibility="visible"><androidx.appcompat.widget.AppCompatTextViewandroid:id="@+id/tv_player_view_play_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="@color/white"android:textSize="@dimen/sp_14"tools:text="00:00" /><androidx.appcompat.widget.AppCompatSeekBarandroid:id="@+id/sb_player_view_progress"android:layout_width="0px"android:layout_height="wrap_content"android:layout_weight="1"android:foreground="@null"android:maxHeight="@dimen/dp_2"android:paddingVertical="@dimen/dp_10"android:progressDrawable="@drawable/video_progress_bg"android:thumb="@drawable/video_progress_ball_bg"tools:max="100"tools:progress="50"tools:secondaryProgress="80"tools:targetApi="m" /><androidx.appcompat.widget.AppCompatTextViewandroid:id="@+id/tv_player_view_total_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="@color/white"android:textSize="@dimen/sp_14"tools:text="10:00" /></com.hjq.shape.layout.ShapeLinearLayout></FrameLayout><androidx.cardview.widget.CardViewandroid:id="@+id/cv_player_view_message"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:gravity="center"android:orientation="vertical"android:visibility="gone"app:cardBackgroundColor="@color/black85"app:cardCornerRadius="@dimen/dp_15"app:cardElevation="0px"tools:visibility="visible"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:minWidth="@dimen/dp_110"android:minHeight="@dimen/dp_110"android:orientation="vertical"android:padding="@dimen/dp_10"><com.airbnb.lottie.LottieAnimationViewandroid:id="@+id/lav_player_view_lottie"android:layout_width="@dimen/dp_70"android:layout_height="@dimen/dp_70"app:lottie_autoPlay="false"app:lottie_loop="true"app:lottie_rawRes="@raw/progress" /><com.hjq.widget.view.SmartTextViewandroid:id="@+id/tv_player_view_message"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginHorizontal="@dimen/dp_15"android:layout_marginTop="@dimen/dp_5"android:maxLines="3"android:textColor="@color/white"android:textSize="@dimen/sp_14"tools:text="@string/common_loading" /></LinearLayout></androidx.cardview.widget.CardView></FrameLayout>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/27405.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构初阶】 --- 单链表

关于链表你应该先了解这些 下图描述了物理模型和逻辑模型&#xff0c;大多数常见的其实是逻辑模型&#xff0c;但这对初学者或者掌握不扎实的同学不太友好&#xff0c;所以这里我重点讲解物理模型&#xff0c;当了解了这些细节&#xff0c;以后做题或是什么就直接画逻辑模型就…

Java优雅统计耗时【工具类】

任务耗时如何优雅的打印&#xff0c;看完本文你就明白了&#xff01;~ import cn.hutool.core.date.StopWatch; import cn.hutool.core.lang.Console;/*** 优雅打印出任务耗时*/ public class Main {public static void main(String[] args) throws Exception{StopWatch stopW…

macOS Sequoia 开发者测试版下载和安装教程

macOS Sequoia 于 2024年6月10日在WWDC 2024 上发布&#xff0c;里面添加了AI、窗口排列、操控iPhone等功能&#xff0c;目前发布的为测试版本&#xff0c;可能很多人不知道怎么去下载安装&#xff0c;现在小编教一下大家怎么安装最新的 macOS Sequoia 开发者测试版。 下载 mac…

2024 年最新使用 Node 搭建QQ开放平台官方 QQ 频道机器人详细教程(更新中)

注册 QQ 开放平台账号 QQ 开放平台是腾讯应用综合开放类平台&#xff0c;包含 QQ 机器人、QQ 小程序、QQ 小游戏 等集成化管理&#xff0c;也就是说你注册了QQ 开放平台&#xff0c;你开发 QQ 机器人还是 QQ 小程序都是在这个平台进行部署上线和管理。 如何注册 QQ 开放平台账…

JAVAEE值之网络原理(1)_用户数据报协议(UDP)、概念、特点、结构、代码实例

前言 在前两节中我们介绍了UDP数据报套接字编程&#xff0c;但是并没有对UDP进行详细介绍&#xff0c;本节中我们将会详细介绍传输层中的UDP协议。 一、什么是UDP&#xff1f; UDP工作在传输层&#xff0c;用于程序之间传输数据的。数据一般包含&#xff1a;文件类型&#xff0…

算法刷题笔记 区间和(离散化二分查找难题,带超详细注释的C++实现)详细解析

文章目录 题目描述详细思路C实现代码 题目描述 假定有一个无限长的数轴&#xff0c;数轴上每个坐标上的数都是0。现在&#xff0c;我们首先进行n次操作&#xff0c;每次操作将某一位置x上的数加c。接下来&#xff0c;进行m次询问&#xff0c;每个询问包含两个整数l和r&#xf…

超图制作栅格数据集专题图示例

之前写过一两篇专题图的博文&#xff0c;是制作的矢量数据集的专题图&#xff1b; 有一个栅格数据集如下&#xff0c;不知是干嘛的&#xff0c;可能是一个地形&#xff0c;或水系&#xff1b; 看一下对栅格数据集制作专题图&#xff1b;能制作的专题图类型少些&#xff0c; 先…

R 文件优化插件:Binary XML file in layout Error inflating class

场景一&#xff1a;构造函数缺失 问题 自定义布局&#xff08;FlagmentLayout&#xff09;加载自定义属性失败&#xff0c;导致广告显示异常&#xff0c;甚至是闪退&#xff5e; InflateException 在 Android 中我们遇到的通常发生在自定义 View 创建中&#xff0c;动态加载…

设置服务器禁止和ip通信

要禁止服务器与特定 IP 地址的通信&#xff0c;可以使用防火墙来设置规则。在 Ubuntu 上&#xff0c;iptables 是一个常用的防火墙工具。以下是使用 iptables 设置禁止与特定 IP 通信的步骤&#xff1a; 阻止所有进出的通信 如果你想阻止服务器与特定 IP 地址的所有通信&…

探索交互设计:五大关键维度全面剖析

交互式设计是用户体验&#xff08;UX&#xff09;设计的重要组成部分。在本文中&#xff0c;我将向大家解释什么是交互设计并简要描述交互设计师通常每天都做什么。 一、什么是交互设计 交互式设计用简单的术语来理解就是用户和产品之间的交互。在大多数情况下&#xff0c;当…

[linux] Qwen2Tokenizer报错 transformers版本问题

上午没问题&#xff0c;下午pull了新代码&#xff0c;就有了报错。。 发现是transformers版本问题。但。。其实我都默认安的是最新版本。。 也许这就是人生吧。。 报错&#xff1a; File "/Pai-Megatron-Patch/megatron_patch/tokenizer/__init__.py", line 213…

大白菜PE系统进入时一直 ACPI_BIOS_ERROR

安装系统PE不支持&#xff0c;主板不兼容&#xff0c;换个WIN10的PE就解决了&#xff0c;跟之前部分电脑需要WIN8的PE同理 WIN10PE教程 WIN8PE教程

CLIPSeg

作者回答问题敷衍&#xff0c;不建议复现

谷歌Google广告开户要提供什么材料?

谷歌Google广告是企业出海&#xff0c;触及全球潜在客户的必备渠道&#xff0c;无论您是初创公司还是成熟企业&#xff0c;想要在激烈的市场竞争中脱颖而出&#xff0c;有效利用谷歌广告的力量至关重要。云衔科技&#xff0c;作为数字化营销解决方案与SaaS软件服务商&#xff0…

区分前端HTML标签中的href和src

在前端HTML中&#xff0c;href和src是用于指定外部资源文件的属性。 href属性用于指定链接的目标地址&#xff0c;比如用于链接到外部CSS文件或者超链接到其他页面。src属性用于指定要嵌入到HTML中的外部资源文件&#xff0c;比如用于引入图片、脚本或者媒体文件。 尽管它们的…

const char * 和char *const ptr的区别

const char *ptr 此代码常量化的是*ptr&#xff0c;即 ptr 的内容值无法修改&#xff0c;但是ptr的值&#xff08;指针指向&#xff09;可以修改 char const *ptr 等效 const char *ptr char *const ptr 此代码常量化的是ptr&#xff0c;即 ptr 的值&#xff08;指针指向&…

【Tkinter界面】Canvas 图形绘制(02/5)

文章目录 一、说明二、几何时使用 Canvas 组件2.1 用法2.2 简单范例2.3 对象移动2.4 对象删除2.5 文字对象显示 三、画布和画布对象3.1 画布生成函数原型3.2 使用create_xxx()方法3.3 对参数**options的解释 一、说明 Canvas&#xff08;画布&#xff09;组件为 Tkinter 的图形…

【打工日常】docker部署一款开源的笔记管理和协作工具

一、项目介绍1.项目简述Logseq 是一个隐私优先的开源知识库。2.项目功能插件系统:允许用户根据自己的需求扩展功能,社区开发的插件可以添加新特性或改进现有功能。主题和定制:支持主题定制,用户可以根据自己的喜好更改应用程序的外观。多语言支持:包括中文、英文、土耳其语…

多类型图像OCR:基于Dify的多模态Agent实现

大模型相关目录 大模型&#xff0c;包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步&#xff0c;扬帆起航。 大模型应用向开发路径&#xff1a;AI代理工作流大模型应用开发实用开源项目汇总大模…