• 自定义实现乘风破浪的小船


            我在昨天的文章中实现了波纹荡漾的效果,这个效果太千篇一律了,今天试着发散一下,实现一个玻璃球中的水波荡漾效果,其次只有水波荡漾怎么够呢,必须给大家来一艘乘风破浪的帆船吧。这就安排。

     

     

            如果你没看昨天的文章请先去看看,不然这里怕一头雾水。

            首先说下思路,这里重点来了。

    1.实现水波局限在玻璃球(圆形)中荡漾效果

            我第一下就想到了clipPath(),那你在WaveView的onDraw()之中去clipPath()一个圆形行不行呢,这里当然是可以的。

            但是这么做我发现了一个,因为水波荡漾要结合属性动画实现,会频繁调用invalidate()重新绘制,那就会频繁触发onDraw(),那其中的clipPath()方法也会频繁被触发,这个方法实际上是切割画布的,开销很大。运行的时候画面会时不时闪动一下,当然不符合预期。

            于是,我目前的思路是自定义一个CircleLinearLayout(继承自LinearLayout),在其中clipPath()并把裁剪后的Canvas分发给子View去绘制。这样的话既能裁切出圆形,又能保证频繁的WaveView刷新不会频繁触发clipPath()。

            这里暂时没想到在WaveView本身中怎样更优雅地切出圆形,如果大家有思路欢迎交流学习

    2.实现帆船乘风破浪效果

            要实现帆船乘风破浪效果太简单了,你就drawBitmap()画一艘帆船吧,计算下位置让其初始位置位于波浪上方,然后还是利用属性动画去设置帆船上下移动,无限循环,那最终结合波浪的翻涌效果,就实现了乘风破浪的帆船。

            因为今天的效果都是基于昨天的波浪效果实现的,因此代码也很简单。

             相比昨天只多了一个CircleLinearLayout

    1. package com.openld.seniorui.testwave
    2. import android.content.Context
    3. import android.graphics.Canvas
    4. import android.graphics.Color
    5. import android.graphics.Paint
    6. import android.graphics.Path
    7. import android.util.AttributeSet
    8. import android.widget.LinearLayout
    9. /**
    10. * author: lllddd
    11. * created on: 2022/8/2 14:12
    12. * description:圆形的线性布局
    13. */
    14. class CircleLinearLayout @JvmOverloads constructor(
    15. context: Context, attrs: AttributeSet? = null
    16. ) : LinearLayout(context, attrs) {
    17. private var mWidth = 0;
    18. private var mHeight = 0;
    19. private var mPaint = Paint().apply {
    20. isAntiAlias = true
    21. strokeWidth = 5F
    22. color = Color.parseColor("#6495ed")
    23. style = Paint.Style.STROKE
    24. }
    25. private var mCirclePath = Path()
    26. override fun dispatchDraw(canvas: Canvas?) {
    27. mWidth = measuredWidth
    28. mHeight = measuredHeight
    29. canvas!!.save()
    30. mCirclePath.addCircle(
    31. (mWidth shr 1).toFloat(),
    32. (mHeight shr 1).toFloat(),
    33. (mWidth shr 1).coerceAtMost(mHeight shr 1).toFloat(),
    34. Path.Direction.CCW
    35. )
    36. canvas.clipPath(mCirclePath)
    37. canvas.drawCircle(
    38. (mWidth shr 1).toFloat(),
    39. (mHeight shr 1).toFloat(),
    40. (mWidth shr 1).coerceAtMost(mHeight shr 1).toFloat() - 5F,
    41. mPaint
    42. )
    43. super.dispatchDraw(canvas)
    44. canvas.restore()
    45. }
    46. }

            然后在调用的页面布局里,WaveView肯定要套在CircleLinearLayout里面

    1. <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    2. xmlns:app="http://schemas.android.com/apk/res-auto"
    3. xmlns:tools="http://schemas.android.com/tools"
    4. android:layout_width="match_parent"
    5. android:layout_height="match_parent"
    6. tools:context=".testwave.TestWaveActivity">
    7. <com.openld.seniorui.testwave.CircleLinearLayout
    8. android:layout_width="match_parent"
    9. android:layout_height="0dp"
    10. android:orientation="vertical"
    11. app:layout_constraintBottom_toBottomOf="parent"
    12. app:layout_constraintDimensionRatio="1:1"
    13. app:layout_constraintLeft_toLeftOf="parent"
    14. app:layout_constraintRight_toRightOf="parent"
    15. app:layout_constraintTop_toTopOf="parent">
    16. <com.openld.seniorui.testwave.WaveView
    17. android:id="@+id/wave_view"
    18. android:layout_width="match_parent"
    19. android:layout_height="match_parent"
    20. app:layout_constraintEnd_toEndOf="parent"
    21. app:layout_constraintStart_toStartOf="parent"
    22. app:layout_constraintTop_toTopOf="parent" />
    23. com.openld.seniorui.testwave.CircleLinearLayout>
    24. androidx.constraintlayout.widget.ConstraintLayout>

            页面调用的地方依旧简单得我都不想贴了

    1. package com.openld.seniorui.testwave
    2. import android.os.Bundle
    3. import androidx.appcompat.app.AppCompatActivity
    4. import com.openld.seniorui.R
    5. class TestWaveActivity : AppCompatActivity() {
    6. override fun onCreate(savedInstanceState: Bundle?) {
    7. super.onCreate(savedInstanceState)
    8. setContentView(R.layout.activity_test_wave)
    9. }
    10. }

            于是大功告成!!!

    完整工程要的自取

  • 相关阅读:
    密码设置有关方法:不能相同字母,不能为连续字符
    不习惯的 Vue3 起步六 の Echarts绘制下钻地图
    uniapp高德地图ios 使用uni.chooseLocation选取位置显示没有搜索到相关数据
    Hadoop3:MapReduce中的Reduce Join和Map Join
    JAVA线程与锁的笔记
    啃完这本阿里手册,应届七面进阿里
    伪分布Hadoop的安装与部署
    ISYSTEM调试实践12-软件运行时间的优化
    【Docker与微服务】高级篇
    机器学习知识总结 —— 15. 什么是支持向量机(对偶问题、核技巧)?
  • 原文地址:https://blog.csdn.net/ldld1717/article/details/126130688