最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Android實(shí)現(xiàn)太極圖、跑馬燈(自定義View)

2023-07-30 23:57 作者:老黑535  | 我要投稿

ANDROID 自定義 VIEW

雖然常用的 view 能夠滿足大部分需求,但是通過自定義 view 通常能夠更加方便的達(dá)到相應(yīng)目的。比如通過自定義 TextView 來實(shí)現(xiàn)一些文本動畫,只需要重寫相應(yīng)的部分代碼即可達(dá)到預(yù)期,比通過各種 view 組合實(shí)現(xiàn)更加方便。本文章將通過自定義 TextView 實(shí)現(xiàn)一個(gè)文本動畫效果,以及實(shí)現(xiàn)旋轉(zhuǎn)太極動畫進(jìn)行自定義 View 介紹。

實(shí)現(xiàn)自定義 View 的方式

  • 繼承 View

  • 繼承已實(shí)現(xiàn)的 View ,如:TextView、ImageView等

旋轉(zhuǎn)太極

通過旋轉(zhuǎn)太極圖的案例介紹 SurfaceView 的使用以及好處。

SurfaceView與View的區(qū)別在于:

  • View為主動更新視圖;SurfaceView為被動更新視圖。

  • View刷新在主線程中;SurfaceView則開啟子線程進(jìn)行刷新。

  • View在繪圖時(shí)沒有實(shí)現(xiàn)雙緩沖機(jī)制,SurfaceView在底層機(jī)制中就實(shí)現(xiàn)了雙緩沖機(jī)制。

實(shí)現(xiàn)過程

  • 繼承 SurfaceView 和實(shí)現(xiàn) SurfaceHolder.Callback 接口

class TaiChiView(context: Context) : SurfaceView(context), SurfaceHolder.Callback {

? ?override fun surfaceCreated(holder: SurfaceHolder) {
? ? ? ?// SurfaceView創(chuàng)建時(shí)候調(diào)用(僅一次)
? ?}

? ?override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
? ? ? ?// SurfaceView發(fā)生改變時(shí)調(diào)用
? ?}

? ?override fun surfaceDestroyed(holder: SurfaceHolder) {
? ? ? ?// SurfaceView發(fā)生銷毀時(shí)調(diào)用(僅一次)
? ?}

}

  • 接下來為繪制太極圖需要的變量進(jìn)行一個(gè)聲明和初始化

class TaiChiView(context: Context) : SurfaceView(context), SurfaceHolder.Callback {

? ?private lateinit var mBlackPaint: Paint
? ?private lateinit var mWhitePaint: Paint
? ?private lateinit var mCanvas: Canvas
? ?private var mHolder: SurfaceHolder

? ?init {
? ? ? ?mBlackPaint = Paint().apply {
? ? ? ? ? ?isAntiAlias = true
? ? ? ? ? ?strokeWidth = 2f
? ? ? ? ? ?color = Color.BLACK
? ? ? ? ? ?style = Paint.Style.FILL
? ? ? ?}
? ? ? ?mWhitePaint = Paint().apply {
? ? ? ? ? ?isAntiAlias = true
? ? ? ? ? ?strokeWidth = 2f
? ? ? ? ? ?color = Color.WHITE
? ? ? ? ? ?style = Paint.Style.FILL
? ? ? ?}
? ? ? ?mHolder = holder.apply {
? ? ? ? ? ?addCallback(this@TaiChiView)
? ? ? ?}
? ?}

? ?// 省略的代碼見上一節(jié)
...

}

  • 定義繪制函數(shù),并在 surfaceCreated 方法中調(diào)用

class TaiChiView(context: Context) : SurfaceView(context), SurfaceHolder.Callback {

? ?...

? ?private fun draw() {
? ? ? ?// 獲取畫布
? ? ? ?mCanvas = mHolder.lockCanvas()

? ? ? ?mCanvas.drawColor(Color.LTGRAY)

? ? ? ?// 定義曲線繪制的矩形,這里將太極圖居中繪制,且大圓半徑為屏幕寬度一半
? ? ? ?val rectLeft = width / 4f
? ? ? ?val rectTop = height / 2f - rectLeft
? ? ? ?val rectRight = width * 3 / 4f
? ? ? ?val rectBottom = height / 2f + rectLeft

? ? ? ?// 繪制左右半圓
? ? ? ?mCanvas.drawArc(RectF(rectLeft, rectTop, rectRight, rectBottom), 270f, -180f, true, mBlackPaint)
? ? ? ?mCanvas.drawArc(RectF(rectLeft, rectTop, rectRight, rectBottom), 270f, 180f, true, mWhitePaint)

? ? ? ?// 在左右半圓里繪制新的半圓,達(dá)到太極圖的分割效果
? ? ? ?mCanvas.drawArc(
? ? ? ? ? ?RectF(width / 2f - rectLeft / 2f, rectTop, width / 2f + rectLeft / 2f, height / 2f),
? ? ? ? ? ?270f,
? ? ? ? ? ?-180f,
? ? ? ? ? ?true,
? ? ? ? ? ?mWhitePaint
? ? ? ?)
? ? ? ?mCanvas.drawArc(
? ? ? ? ? ?RectF(width / 2f - rectLeft / 2f, height / 2f, width / 2f + rectLeft / 2f, rectBottom),
? ? ? ? ? ?270f,
? ? ? ? ? ?180f,
? ? ? ? ? ?true,
? ? ? ? ? ?mBlackPaint
? ? ? ?)

? ? ? ?// 繪制太極圖的兩個(gè)小圓
? ? ? ?mCanvas.drawCircle(width / 2f, height / 2f - rectLeft / 2f, rectLeft / 4f, mBlackPaint)
? ? ? ?mCanvas.drawCircle(width / 2f, height / 2f + rectLeft / 2f, rectLeft / 4f, mWhitePaint)


? ? ? ?mHolder.unlockCanvasAndPost(mCanvas)
? ?}

? ?override fun surfaceCreated(holder: SurfaceHolder) {
? ? ? ?draw()
? ?}

? ?...
}

  • 到此,一個(gè)太極圖便成功繪制,效果圖如下:

太極圖(靜態(tài))
  • 接下來給繪制的太極圖添加旋轉(zhuǎn)動畫,新增角度變量聲明和動畫播放開關(guān)。

class TaiChiView(context: Context) : SurfaceView(context), SurfaceHolder.Callback {

? ?...
? ?
? ?// 添加動畫
? ?private var mDegrees = 0f
? ?private var isRunning = true

? ?...

}

  • 修改圖形繪制方法,讓畫布圍繞圖形中旋轉(zhuǎn)。

class TaiChiView(context: Context) : SurfaceView(context), SurfaceHolder.Callback {

? ?...

? ?private fun draw() {
? ? ? ?mCanvas = mHolder.lockCanvas()

? ? ? ?mCanvas.drawColor(Color.LTGRAY)

? ? ? ?val rectLeft = width / 4f
? ? ? ?val rectTop = height / 2f - rectLeft
? ? ? ?val rectRight = width * 3 / 4f
? ? ? ?val rectBottom = height / 2f + rectLeft

? ? ? ?mCanvas.save()
? ? ? ?// 設(shè)置旋轉(zhuǎn)角度
? ? ? ?mCanvas.rotate(mDegrees, width / 2f, height/2f)

? ? ? ?// 繪制太極圖的代碼路基
? ? ? ?...

? ? ? ?// restore方法和save方法數(shù)量一致
? ? ? ?mCanvas.restore()
? ? ? ?mHolder.unlockCanvasAndPost(mCanvas)
? ?}

? ?override fun surfaceCreated(holder: SurfaceHolder) {
? ? ? ?// 啟用協(xié)程,不斷繪制太極圖,改變旋轉(zhuǎn)角度
? ? ? ?CoroutineScope(Dispatchers.Default).launch {
? ? ? ? ? ?while (isRunning) {
? ? ? ? ? ? ? ?draw()
? ? ? ? ? ? ? ?mDegrees++
? ? ? ? ? ?}
? ? ? ?}
? ?}
...

? ?override fun surfaceDestroyed(holder: SurfaceHolder) {
? ? ? ?// SurfaceView銷毀則停止動畫
? ? ? ?isRunning = false
? ?}

}

  • 最后,一個(gè)會動的太極圖就成功繪制完成,效果如圖:

太極圖(動態(tài))

文本跑馬燈

使用 TextView 實(shí)現(xiàn)跑馬燈存在一個(gè)焦點(diǎn)的問題,如果不設(shè)置焦點(diǎn),那么跑馬燈無法運(yùn)行起來。通過自定義 TextView 方式重寫 isFocused 方法即可解決問題。

class MarqueeText(context: Context) : TextView(context) {

? ?init {
? ? ? ?// 初始化以下textview已提供的跑馬燈屬性
? ? ? ?ellipsize = TextUtils.TruncateAt.MARQUEE
? ? ? ?isSingleLine = true
? ? ? ?// 永久循環(huán)
? ? ? ?marqueeRepeatLimit = -1
? ? ? ?isSelected = true
? ?}

? ?// 重寫isFocused方法,讓textview失蹤獲取焦點(diǎn)
? ?override fun isFocused(): Boolean = true
}

注意:TextView 跑馬燈需要文本足夠長才能夠動起來。

效果如圖:

文本跑馬燈

項(xiàng)目地址:https://github.com/laoheix/lao_hei_dome.git

使用Android Compose顯示,存在SurfaceView跳轉(zhuǎn)后Canvas為空的異常,后續(xù)修復(fù)。

Android實(shí)現(xiàn)太極圖、跑馬燈(自定義View)的評論 (共 條)

分享到微博請遵守國家法律
双辽市| 兴宁市| 武汉市| 防城港市| 柳河县| 成都市| 平定县| 淮滨县| 谢通门县| 买车| 五台县| 慈溪市| 咸宁市| 蒲江县| 玉田县| 翼城县| 苏州市| 崇仁县| 洞口县| 靖边县| 班玛县| 彩票| 鄂托克前旗| 科尔| 乐东| 景东| 且末县| 庆阳市| 高陵县| SHOW| 乐都县| 绿春县| 名山县| 遂溪县| 福清市| 阿拉善右旗| 温泉县| 神木县| 汕尾市| 武夷山市| 密山市|