• Android Splash实现


    1、创建Activity

    1. package com.wsy.knowledge.ui.splash
    2. import android.animation.Animator
    3. import android.animation.AnimatorListenerAdapter
    4. import android.annotation.SuppressLint
    5. import android.os.Build
    6. import android.os.Looper
    7. import android.util.Log
    8. import androidx.annotation.RequiresApi
    9. import com.alibaba.android.arouter.facade.annotation.Route
    10. import com.wsy.knowledge.common.arouter.ArouterUrl
    11. import com.wsy.knowledge.common.ui.component.BaseActivity
    12. import com.wsy.knowledge.databinding.ActivityNativeSplashBinding
    13. import com.wsy.knowledge.ui.homepage.HomePageActivity
    14. @SuppressLint("CustomSplashScreen")
    15. @Route(path = ArouterUrl.native_splash)
    16. class NativeSplashActivity : BaseActivity() {
    17. private lateinit var binding: ActivityNativeSplashBinding
    18. override fun getLayoutId() {
    19. binding = ActivityNativeSplashBinding.inflate(layoutInflater)
    20. setContentView(binding.root)
    21. }
    22. override fun initData() {
    23. }
    24. @RequiresApi(Build.VERSION_CODES.O)
    25. override fun init() {
    26. setFAFStatusBar()
    27. binding.animLogo.apply {
    28. addOffsetAnimListener(object : AnimatorListenerAdapter() {
    29. override fun onAnimationEnd(animation: Animator) {
    30. Log.d("AnimLogoView", "Offset anim end")
    31. }
    32. })
    33. addGradientAnimListener(object : AnimatorListenerAdapter() {
    34. override fun onAnimationEnd(animation: Animator) {
    35. Log.d("AnimLogoView", "Gradient anim end")
    36. startActivity(HomePageActivity::class.java, true)
    37. }
    38. })
    39. }
    40. Looper.myQueue().addIdleHandler {
    41. binding.animLogo.startAnimation()
    42. false
    43. }
    44. }
    45. }

     2、XML文件

    1. "1.0" encoding="utf-8"?>
    2. "http://schemas.android.com/apk/res/android"
    3. xmlns:app="http://schemas.android.com/apk/res-auto"
    4. xmlns:tools="http://schemas.android.com/tools"
    5. android:layout_width="match_parent"
    6. android:layout_height="match_parent"
    7. tools:context=".ui.splash.NativeSplashActivity"
    8. android:background="@color/blue_2A6FAF"
    9. tools:ignore="MissingDefaultResource">
    10. android:id="@+id/anim_logo"
    11. android:layout_width="match_parent"
    12. android:layout_height="@dimen/sp_200"
    13. app:layout_constraintTop_toBottomOf="@+id/splashImg"
    14. app:autoPlay="false"
    15. app:gradientAnimDuration="2000"
    16. app:gradientColor="@color/blue_2A6FAF"
    17. app:logoName="@string/app_name"
    18. app:offsetAnimDuration="2000"
    19. app:showGradient="true"
    20. app:textColor="@color/white"
    21. app:textPadding="3dp"
    22. app:textSize="@dimen/sp_40"
    23. />
    24. android:id="@+id/splashImg"
    25. app:layout_constraintLeft_toLeftOf="parent"
    26. app:layout_constraintRight_toRightOf="parent"
    27. app:layout_constraintTop_toTopOf="parent"
    28. android:layout_marginBottom="@dimen/sp_200"
    29. android:src="@drawable/launch_second"
    30. android:layout_marginTop="@dimen/sp_200"
    31. android:layout_width="wrap_content"
    32. android:layout_height="wrap_content"/>
    33. app:layout_constraintLeft_toLeftOf="parent"
    34. app:layout_constraintRight_toRightOf="parent"
    35. app:layout_constraintBottom_toBottomOf="parent"
    36. android:layout_marginBottom="@dimen/sp_20"
    37. android:text="@string/search_service"
    38. android:textSize="@dimen/sp_14"
    39. android:textColor="@color/color_999"
    40. android:gravity="center"
    41. android:layout_width="match_parent"
    42. android:layout_height="wrap_content"
    43. />

     3、AnimationLogoView

    1. package com.wsy.knowledge.common.ui.view
    2. import android.animation.Animator
    3. import android.animation.AnimatorListenerAdapter
    4. import android.animation.PointFEvaluator
    5. import android.animation.ValueAnimator
    6. import android.animation.ValueAnimator.AnimatorUpdateListener
    7. import android.annotation.SuppressLint
    8. import android.content.Context
    9. import android.graphics.*
    10. import android.text.TextUtils
    11. import android.util.AttributeSet
    12. import android.util.Log
    13. import android.util.SparseArray
    14. import android.view.View
    15. import android.view.animation.AccelerateDecelerateInterpolator
    16. import com.wsy.knowledge.R
    17. class AnimationLogoView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {
    18. private val mLogoTexts = SparseArray()
    19. private val mQuietPoints = SparseArray()
    20. private val mRandomPoints = SparseArray()
    21. private var mOffsetAnimator: ValueAnimator? = null
    22. private var mGradientAnimator: ValueAnimator? = null
    23. private var mPaint: Paint? = null
    24. private var mTextPadding: Int
    25. private var mTextColor: Int
    26. private var mTextSize: Float
    27. private var mOffsetAnimProgress = 0f
    28. private var mOffsetDuration: Int
    29. private var isOffsetAnimEnd = false
    30. private var mGradientDuration: Int
    31. private var mLinearGradient: LinearGradient? = null
    32. private var mGradientColor: Int
    33. private var mGradientMatrix: Matrix? = null
    34. private var mMatrixTranslate = 0
    35. private val isAutoPlay: Boolean
    36. private var mWidth = 0
    37. private var mHeight = 0
    38. private var isShowGradient: Boolean
    39. private val mLogoOffset: Int
    40. private var mGradientListener: Animator.AnimatorListener? = null
    41. companion object {
    42. private const val DEFAULT_LOGO = "Animation"
    43. private const val DEFAULT_TEXT_PADDING = 10
    44. private const val ANIM_LOGO_DURATION = 1500
    45. private const val ANIM_LOGO_GRADIENT_DURATION = 1500
    46. private const val ANIM_LOGO_TEXT_SIZE = 30f
    47. private const val ANIM_LOGO_TEXT_COLOR = Color.BLACK
    48. private const val ANIM_LOGO_GRADIENT_COLOR = Color.YELLOW
    49. }
    50. init {
    51. val ta = context.obtainStyledAttributes(attrs, R.styleable.AnimationLogoView)
    52. var logoName = ta.getString(R.styleable.AnimationLogoView_logoName)
    53. isAutoPlay = ta.getBoolean(R.styleable.AnimationLogoView_autoPlay, true)
    54. isShowGradient = ta.getBoolean(R.styleable.AnimationLogoView_showGradient, false)
    55. mOffsetDuration = ta.getInt(R.styleable.AnimationLogoView_offsetAnimDuration, ANIM_LOGO_DURATION)
    56. mGradientDuration = ta.getInt(R.styleable.AnimationLogoView_gradientAnimDuration, ANIM_LOGO_GRADIENT_DURATION)
    57. mTextColor = ta.getColor(R.styleable.AnimationLogoView_textColor, ANIM_LOGO_TEXT_COLOR)
    58. mGradientColor = ta.getColor(R.styleable.AnimationLogoView_gradientColor, ANIM_LOGO_GRADIENT_COLOR)
    59. mTextPadding = ta.getDimensionPixelSize(R.styleable.AnimationLogoView_textPadding, DEFAULT_TEXT_PADDING)
    60. mTextSize = ta.getDimension(R.styleable.AnimationLogoView_textSize, ANIM_LOGO_TEXT_SIZE)
    61. mLogoOffset = ta.getDimensionPixelOffset(R.styleable.AnimationLogoView_verticalOffset, 0)
    62. ta.recycle()
    63. if (TextUtils.isEmpty(logoName)) {
    64. logoName = DEFAULT_LOGO
    65. }
    66. fillLogoTextArray(logoName)
    67. initPaint()
    68. initOffsetAnimation()
    69. }
    70. private fun fillLogoTextArray(logoName: String?) {
    71. if (TextUtils.isEmpty(logoName)) {
    72. return
    73. }
    74. if (mLogoTexts.size() > 0) {
    75. mLogoTexts.clear()
    76. }
    77. for (i in logoName!!.indices) {
    78. mLogoTexts.put(i, logoName[i].toString())
    79. }
    80. }
    81. private fun initPaint() {
    82. mPaint=Paint().apply {
    83. isAntiAlias = true
    84. style = Paint.Style.FILL
    85. textSize = mTextSize
    86. color = mTextColor
    87. }
    88. }
    89. private fun initOffsetAnimation() {
    90. if (mOffsetAnimator == null) {
    91. mOffsetAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
    92. interpolator = AccelerateDecelerateInterpolator()
    93. addUpdateListener(AnimatorUpdateListener { animation ->
    94. if (mQuietPoints.size() <= 0 || mRandomPoints.size() <= 0) {
    95. return@AnimatorUpdateListener
    96. }
    97. mOffsetAnimProgress = animation.animatedValue as Float
    98. invalidate()
    99. })
    100. addListener(object : AnimatorListenerAdapter() {
    101. override fun onAnimationEnd(animation: Animator) {
    102. if (mGradientAnimator != null && isShowGradient) {
    103. isOffsetAnimEnd = true
    104. mPaint?.shader = mLinearGradient
    105. mGradientAnimator!!.start()
    106. }
    107. }
    108. })
    109. duration = mOffsetDuration.toLong()
    110. }
    111. }
    112. }
    113. override fun onAttachedToWindow() {
    114. super.onAttachedToWindow()
    115. if (visibility == VISIBLE && isAutoPlay) {
    116. mOffsetAnimator?.start()
    117. }
    118. }
    119. override fun onDetachedFromWindow() {
    120. if (mOffsetAnimator != null && mOffsetAnimator!!.isRunning) {
    121. mOffsetAnimator!!.cancel()
    122. }
    123. if (mGradientAnimator != null && mGradientAnimator!!.isRunning) {
    124. mGradientAnimator!!.cancel()
    125. }
    126. super.onDetachedFromWindow()
    127. }
    128. fun addOffsetAnimListener(listener: Animator.AnimatorListener?) {
    129. mOffsetAnimator!!.addListener(listener)
    130. }
    131. fun addGradientAnimListener(listener: Animator.AnimatorListener?) {
    132. mGradientListener = listener
    133. }
    134. /**
    135. * 开启动画
    136. */
    137. fun startAnimation() {
    138. if (visibility == VISIBLE) {
    139. if (mOffsetAnimator!!.isRunning) {
    140. mOffsetAnimator!!.cancel()
    141. }
    142. isOffsetAnimEnd = false
    143. mOffsetAnimator!!.start()
    144. } else {
    145. Log.w("AnimLogoView", "The view is not visible, not to play the animation .")
    146. }
    147. }
    148. override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    149. super.onSizeChanged(w, h, oldw, oldh)
    150. mWidth = w
    151. mHeight = h
    152. initLogoCoordinate()
    153. initGradientAnimation()
    154. }
    155. private fun initLogoCoordinate() {
    156. if (mWidth == 0 || mHeight == 0) {
    157. return
    158. }
    159. val fontMetrics = mPaint!!.fontMetrics
    160. val baseY = mHeight / 2 - fontMetrics.top / 2 - fontMetrics.bottom / 2
    161. val centerY = baseY + mLogoOffset
    162. var totalLength = 0f
    163. for (i in 0 until mLogoTexts.size()) {
    164. val str = mLogoTexts[i]
    165. val currentLength = mPaint!!.measureText(str)
    166. totalLength += if (i != mLogoTexts.size() - 1) {
    167. currentLength + mTextPadding
    168. } else {
    169. currentLength
    170. }
    171. }
    172. check(totalLength <= mWidth) { "The text of logoName is too large that this view can not display all text" }
    173. var startX = (mWidth - totalLength) / 2
    174. if (mQuietPoints.size() > 0) {
    175. mQuietPoints.clear()
    176. }
    177. for (i in 0 until mLogoTexts.size()) {
    178. val str = mLogoTexts[i]
    179. val currentLength = mPaint!!.measureText(str)
    180. mQuietPoints.put(i, PointF(startX, centerY))
    181. startX += currentLength + mTextPadding
    182. }
    183. if (mRandomPoints.size() > 0) {
    184. mRandomPoints.clear()
    185. }
    186. for (i in 0 until mLogoTexts.size()) {
    187. mRandomPoints.put(i, PointF(Math.random().toFloat() * mWidth, Math.random().toFloat() * mHeight))
    188. }
    189. }
    190. private fun initGradientAnimation() {
    191. if (mWidth == 0 || mHeight == 0) {
    192. return
    193. }
    194. if (mGradientAnimator == null) {
    195. mGradientAnimator = ValueAnimator.ofInt(0, 2 * mWidth).apply {
    196. if (mGradientListener != null) {
    197. addListener(mGradientListener)
    198. }
    199. addUpdateListener { animation ->
    200. mMatrixTranslate = animation.animatedValue as Int
    201. invalidate()
    202. }
    203. mLinearGradient = LinearGradient(-mWidth.toFloat(), 0f, 0f, 0f, intArrayOf(mTextColor, mGradientColor, mTextColor), floatArrayOf(0f, 0.5f, 1f), Shader.TileMode.CLAMP)
    204. mGradientMatrix = Matrix()
    205. duration = mGradientDuration.toLong()
    206. }
    207. }
    208. }
    209. @SuppressLint("DrawAllocation")
    210. override fun onDraw(canvas: Canvas) {
    211. if (!isOffsetAnimEnd) {
    212. mPaint!!.alpha = 255f.coerceAtMost(255 * mOffsetAnimProgress + 100).toInt()
    213. for (i in 0 until mQuietPoints.size()) {
    214. val point=PointFEvaluator().evaluate(mOffsetAnimProgress,mRandomPoints[i],mQuietPoints[i])
    215. canvas.drawText(mLogoTexts[i],point.x, point.y, mPaint!!)
    216. }
    217. } else {
    218. for (i in 0 until mQuietPoints.size()) {
    219. val quietP = mQuietPoints[i]
    220. canvas.drawText(mLogoTexts[i], quietP.x, quietP.y, mPaint!!)
    221. }
    222. mGradientMatrix!!.setTranslate(mMatrixTranslate.toFloat(), 0f)
    223. mLinearGradient!!.setLocalMatrix(mGradientMatrix)
    224. }
    225. }
    226. }

     

  • 相关阅读:
    Hadoop HA (三) --------- HDFS-HA 自动模式
    随手写的小程序2 一个nc能控制的程序
    自学Python 49 正则表达式(一)基本语法表达
    禁止linux shell 终端显示完整工作路径,如何让linux bash终端不显示当前工作路径
    Java动态代理
    go语言结构体使用小结
    动态规划解决01背包问题
    神经网络的训练与测试,神经网络显著性检测
    【Java】封装、继承、多态
    [AutoSar]工程中的cpuload陷阱(三)测试
  • 原文地址:https://blog.csdn.net/qq_41264674/article/details/132855930