热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

android幻灯片效果自定义,Android波浪效果自定义View实现

前言最近在Github上看到1139618418大神写了一个波浪效果的View,发现效果非常酷炫,但是代码上有很大的优化空间,就照着思路自

前言

最近在Github上看到@1139618418 大神写了一个波浪效果的View,发现效果非常酷炫,但是代码上有很大的优化空间,就照着思路自己撸了一个。留着以后备用。

需求

实现一个类似于波浪效果的自定义view,并且可以提供一个波浪起伏变化距离的接口。

直接上效果图:

android:layout_width="match_parent"

android:layout_height="500dp"

android:layout_alignParentBottom="true"

app:peakHeight="5dp"

app:waveColor="#ffffff" />

在构造函数中获取xml设置的自定义属性,首先拿到typedArray对象 val ta = context.obtainStyledAttributes(attr, R.styleable.SugarWaveView) ,然后通过在attrs定义好的名称,一个个获取,敲黑板:获取完记得recycle():

constructor(context: Context, attr: AttributeSet) : super(context, attr) {

val ta = context.obtainStyledAttributes(attr, R.styleable.SugarWaveView)

waveColor = ta.getColor(R.styleable.SugarWaveView_waveColor, ContextCompat.getColor(context, R.color.colorPrimaryDark))

waveAlpha = ta.getInt(R.styleable.SugarWaveView_backWaveAlpha, 80)

cycle = ta.getInt(R.styleable.SugarWaveView_cycle, 2)

peakHeight = ta.getDimension(R.styleable.SugarWaveView_peakHeight, 8.0f)

ta.recycle()

}

拿到屏幕的宽度,只有拿到宽度后才知道曲线需要画多长,拿宽度比较合适的时机是在onMeasure之后,在这之前,是拿不到的。

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec)

range = cycle * Math.PI / width // range:周期,决定屏幕内波浪的数量,cycle:常数,通过改变它来改成range,width在java中为getWidth()

}

根据构造函数中拿到的自定义属性,来初始化画笔,mBelowPaint用于画出一个半透明的波浪,看起来有交错感,此处参照了原作者的思路:

override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {

super.onLayout(changed, left, top, right, bottom)

mAbovePaint.isAntiAlias = true

mAbovePaint.style = Paint.Style.FILL

mAbovePaint.color = waveColor

mBelowPaint.isAntiAlias = true

mBelowPaint.style = Paint.Style.FILL

mBelowPaint.color = waveColor

mBelowPaint.alpha = waveAlpha

}

OK,下面是最重要的画曲线部分。首先,给定一个初始的初相,画出正弦曲线,正弦曲线的画法为:通过改变x轴的坐标,不断通过y=Asin(ωx+φ)+k来算出y轴坐标。每N个像素算出一个点,将这些点连接起来,此处需要使用到path,然后不断的lineTo(x,y),当点足够密集的时候,看起来就是曲线了。代码如下:

override fun onDraw(canvas: Canvas?) {

super.onDraw(canvas)

canvas!!.drawFilter = drawFilter

mAbovePath.reset()//每次onDraw前初始化path,above为不透明波浪,below为透明的波浪

mBelowPath.reset()

start -= 0.1f//初相

var y1: Float

var y2: Float

mAbovePath.moveTo(left.toFloat(), bottom.toFloat())

mBelowPath.moveTo(left.toFloat(), bottom.toFloat())

for (x in 0..width step 20) {//kotlin写法 java为for(int i&#61;0;i<&#61;getWidth();i&#43;&#61;20)

/**

* 此处根据X不断变化&#xff0c;算出Y的值&#xff0c;得到正弦、余弦曲线的坐标点&#xff0c;最后一个个连接起来

*/

y1 &#61; (peakHeight * Math.cos(range * x &#43; start) &#43; peakHeight &#43; 10).toFloat()

y2 &#61; (peakHeight * Math.sin(range * x &#43; start) &#43; peakHeight).toFloat()

mAbovePath.lineTo(x.toFloat(), y1)

mBelowPath.lineTo(x.toFloat(), y2)

}

val middleY &#61; (peakHeight * Math.cos(range * width/2 &#43; start) &#43; peakHeight).toFloat()

listenr?.onWaveHeightChange(middleY)

mAbovePath.lineTo(right.toFloat(), bottom.toFloat())

mBelowPath.lineTo(right.toFloat(), bottom.toFloat())

canvas.drawPath(mAbovePath, mAbovePaint)

canvas.drawPath(mBelowPath, mBelowPaint)

postInvalidateDelayed(10)//延迟10ms重新绘制

}

然后&#xff0c;通过postInvalidateDelayed来延迟一段时间重新绘制&#xff0c;此时只需改变初相&#xff0c;图像就会得到移动的效果。

最后&#xff0c;定义一个返回中心位置波浪Y轴变化的接口&#xff0c;用于实现其他控件的联动&#xff1a;

interface OnWaveChangeListener{

fun onWaveHeightChange(y:Float)

}

如果使用java实现此自定义view的话&#xff0c;还需要写set各种参数的public 方法&#xff0c;以及setOnWaveChangeListener方法。

到这里就完成了整个自定义View的编写、使用。完整代码及Demo可以在我的Github中查看。如发现有改进之处&#xff0c;望指正&#xff0c;万分感谢&#xff01;



推荐阅读
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • 本文介绍如何在 Android 中通过代码模拟用户的点击和滑动操作,包括参数说明、事件生成及处理逻辑。详细解析了视图(View)对象、坐标偏移量以及不同类型的滑动方式。 ... [详细]
  • Android 九宫格布局详解及实现:人人网应用示例
    本文深入探讨了人人网Android应用中独特的九宫格布局设计,解析其背后的GridView实现原理,并提供详细的代码示例。这种布局方式不仅美观大方,而且在现代Android应用中较为少见,值得开发者借鉴。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • Linux 系统启动故障排除指南:MBR 和 GRUB 问题
    本文详细介绍了 Linux 系统启动过程中常见的 MBR 扇区和 GRUB 引导程序故障及其解决方案,涵盖从备份、模拟故障到恢复的具体步骤。 ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 构建基于BERT的中文NL2SQL模型:一个简明的基准
    本文探讨了将自然语言转换为SQL语句(NL2SQL)的任务,这是人工智能领域中一项非常实用的研究方向。文章介绍了笔者在公司举办的首届中文NL2SQL挑战赛中的实践,该比赛提供了金融和通用领域的表格数据,并标注了对应的自然语言与SQL语句对,旨在训练准确的NL2SQL模型。 ... [详细]
  • 本文介绍了如何使用JQuery实现省市二级联动和表单验证。首先,通过change事件监听用户选择的省份,并动态加载对应的城市列表。其次,详细讲解了使用Validation插件进行表单验证的方法,包括内置规则、自定义规则及实时验证功能。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
author-avatar
PHP小白
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有