欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android粒子線條效果實現(xiàn)過程與代碼

 更新時間:2023年02月09日 09:29:29   作者:撿一晌貪歡  
這篇文章主要介紹了Android粒子線條效果的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧

前言

很久沒寫代碼了,忙工作、忙朋友、人也懶了,最近重新調(diào)整自己,對技術(shù)還是要有熱情,要熱情的話還是用自定義view做游戲有趣,寫完這個粒子線條后面我會更新幾個小游戲博文及代碼,希望讀者喜歡。

這個粒子效果的控件是去年寫的,寫的很差勁,這幾天又重構(gòu)了一下,還是難看的要命,勉強(qiáng)記錄下吧。

需求

主要就是看到博客園的粒子線條背景很有意思,就想模仿一下。核心思想如下:

1、隨機(jī)出現(xiàn)點

2、范圍內(nèi)的點連線

3、手指按下,加入點,范圍內(nèi)點向手指移動

效果圖

效果圖就是難看,沒得說。

代碼

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import java.lang.ref.WeakReference
import kotlin.math.pow
import kotlin.math.sqrt
/**
 * 模仿博客粒子線條的view
 *
 * 核心思想簡易版
 *
 * 1、隨機(jī)出現(xiàn)點
 * 2、范圍內(nèi)的點連線
 * 3、手指按下,加入點,范圍內(nèi)點向手指移動
 *
 * @author silence
 * @date 2022-11-09
 *
 */
class ParticleLinesBgView @JvmOverloads constructor(
    context: Context,
    attributeSet: AttributeSet? = null,
    defStyleAttr: Int = 0
): View(context, attributeSet, defStyleAttr){
    companion object{
        // 屏幕刷新時間,每秒20次
        const val SCREEN_FLUSH_TIME = 50L
        // 新增點的間隔時間
        const val POINT_ADD_TIME = 200L
        // 粒子存活時間
        const val POINT_ALIVE_TIME = 18000L
        // 吸引的合適距離
        const val ATTRACT_LENGTH = 250f
        // 維持的合適距離
        const val PROPER_LENGTH = 150f
        // 粒子被吸引每次接近的距離
        const val POINT_MOVE_LENGTH = 30f
        // 距離計算公式
        fun getDistance(x1: Float, y1: Float, x2: Float, y2: Float): Float {
            return sqrt(((x1 - x2).toDouble().pow(2.0)
                    + (y1 - y2).toDouble().pow(2.0)).toFloat())
        }
    }
    // 存放的粒子
    private val mParticles = ArrayList<Particle>(64)
    // 手指按下位置
    private var mTouchParticle: Particle? = null
    // 處理的handler
    private val mHandler = ParticleHandler(this)
    // 畫筆
    private val mPaint = Paint().apply {
        color = Color.LTGRAY
        strokeWidth = 3f
        style = Paint.Style.STROKE
        flags = Paint.ANTI_ALIAS_FLAG
    }
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        // 通過發(fā)送消息給handler實現(xiàn)間隔添加點
        mHandler.removeMessages(0)
        mHandler.sendEmptyMessageDelayed(0, POINT_ADD_TIME)
    }
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        // 繪制點和線
        for (i in 0 until mParticles.size) {
            val point = mParticles[i]
            canvas.drawPoint(point.x, point.y, mPaint)
            // 連線
            for (j in (i + 1) until mParticles.size) {
                val another = mParticles[j]
                val distance = getDistance(point.x, point.y, another.x, another.y)
                if (distance <= PROPER_LENGTH) {
                    canvas.drawLine(point.x, point.y, another.x, another.y, mPaint)
                }
            }
        }
        mTouchParticle?.let {
            // 手指按下點與附近連線
            for(point in mParticles) {
                val distance = getDistance(point.x, point.y, it.x, it.y)
                if (distance <= PROPER_LENGTH) {
                    canvas.drawLine(point.x, point.y, it.x, it.y, mPaint)
                }
            }
            // 吸引范圍顯示
            mPaint.color = Color.BLUE
            canvas.drawCircle(it.x, it.y, PROPER_LENGTH, mPaint)
            mPaint.color = Color.LTGRAY
        }
    }
    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        when(event.action) {
            MotionEvent.ACTION_DOWN -> {
                mTouchParticle = Particle(event.x, event.y, 0)
            }
            MotionEvent.ACTION_MOVE -> {
                mTouchParticle!!.x = event.x
                mTouchParticle!!.y = event.y
                invalidate()
            }
            MotionEvent.ACTION_UP -> {
                mTouchParticle = null
            }
        }
        return true
    }
    // 粒子
    class Particle(var x: Float, var y: Float, var counter: Int)
    // kotlin自動編譯為Java靜態(tài)類,控件引用使用弱引用
    class ParticleHandler(view: ParticleLinesBgView): Handler(Looper.getMainLooper()){
        // 控件引用
        private val mRef: WeakReference<ParticleLinesBgView> = WeakReference(view)
        // 粒子出現(xiàn)控制
        private var mPointCounter = 0
        override fun handleMessage(msg: Message) {
            mRef.get()?.let {view->
                // 新增點
                mPointCounter++
                if (mPointCounter == (POINT_ADD_TIME / SCREEN_FLUSH_TIME).toInt()) {
                    // 隨機(jī)位置
                    val x = (Math.random() * view.width).toFloat()
                    val y = (Math.random() * view.height).toFloat()
                    view.mParticles.add(Particle(x, y, 0))
                    mPointCounter = 0
                }
                val iterator = view.mParticles.iterator()
                while (iterator.hasNext()) {
                    val point = iterator.next()
                    // 移除失活粒子
                    if (point.counter == (POINT_ALIVE_TIME / SCREEN_FLUSH_TIME).toInt()) {
                        iterator.remove()
                    }
                    // 手指按下時,粒子朝合適的距離移動
                    view.mTouchParticle?.let {
                        val distance = getDistance(point.x, point.y, it.x, it.y)
                        if(distance in PROPER_LENGTH..ATTRACT_LENGTH) {
                            // 橫向接近
                            if (point.x < it.x) point.x += POINT_MOVE_LENGTH
                            else point.x -= POINT_MOVE_LENGTH
                            // 縱向接近
                            if (point.y < it.y) point.y += POINT_MOVE_LENGTH
                            else point.y -= POINT_MOVE_LENGTH
                        }else if(distance <= PROPER_LENGTH) {
                            // 橫向遠(yuǎn)離
                            if (point.x < it.x) point.x -= POINT_MOVE_LENGTH
                            else point.x += POINT_MOVE_LENGTH
                            // 縱向遠(yuǎn)離
                            if (point.y < it.y) point.y -= POINT_MOVE_LENGTH
                            else point.y += POINT_MOVE_LENGTH
                        }
                    }
                }
                // 循環(huán)發(fā)送
                view.invalidate()
                view.mHandler.sendEmptyMessageDelayed(0, POINT_ADD_TIME)
            }
        }
    }
}

這里沒寫onMeasure,注意下不能用wrap-content,布局的話改個黑色背景就行了。

主要問題

下面簡單講講吧。

粒子

這里用了個數(shù)據(jù)類構(gòu)造了粒子,用了一個ArrayList來存放,本來想用linkedHashMap來保存并實現(xiàn)下LRU的,結(jié)果連線的時候比較復(fù)雜,重構(gòu)的時候直接刪了,后面用了一個counter來控制粒子的存活時間。

邏輯控制

一開始的時候想的比較復(fù)雜,實現(xiàn)來弄得自己頭疼,后面覺得何不將邏輯和繪制分離,在ondraw里面只進(jìn)行繪制不就行了,邏輯通過handler來更新,實際這樣在我看來是對的。

我這用了一個Handler配合嵌套循環(huán)發(fā)送空消息,實現(xiàn)定時更新效果,每隔一段時間更新一下邏輯,Handler內(nèi)部通過弱引用獲得view,并對其中的內(nèi)容修改,修改完成后,通過invalidate出發(fā)線程更新。

新增點

Handler會定時更新,只需要在handleMessage里面添加點就行了,為了控制點出現(xiàn)的頻率,我這又引入了控制變量。

粒子生命周期

handleMessage里面會檢查粒子是否失活,失活了就通過iterator去移除,移除數(shù)組內(nèi)內(nèi)容還是盡量通過iterator去實現(xiàn)吧,特別是for-eacn循環(huán)以及for循環(huán)內(nèi)刪除多個時,會出錯的!

粒子趨向于手指

手指按下時設(shè)置mTouchParticle,移動時更新這個mTouchParticle,手指抬起時對mTouchParticle賦空,這樣在handleMessage里面只要在mTouchParticle不為空時稍稍改變下其他粒子的位置,就可以達(dá)到趨向效果。

粒子連線

這里我沒有想到什么好辦法,直接兩兩計算,并對合適距離的粒子進(jìn)行連線。

到此這篇關(guān)于Android粒子線條效果實現(xiàn)過程與代碼的文章就介紹到這了,更多相關(guān)Android粒子線條內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android布局性能優(yōu)化之按需加載View

    Android布局性能優(yōu)化之按需加載View

    這篇文章主要介紹了Android布局性能優(yōu)化之按需加載View的相關(guān)資料,非常不錯,具有參考借鑒價值,感興趣的朋友一起看看吧
    2016-09-09
  • 封裝flutter狀態(tài)管理工具示例詳解

    封裝flutter狀態(tài)管理工具示例詳解

    這篇文章主要為大家介紹了封裝flutter狀態(tài)管理工具示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Android HttpURLConnection下載網(wǎng)絡(luò)圖片設(shè)置系統(tǒng)壁紙

    Android HttpURLConnection下載網(wǎng)絡(luò)圖片設(shè)置系統(tǒng)壁紙

    這篇文章主要為大家詳細(xì)介紹了Android HttpURLConnection下載網(wǎng)絡(luò)圖片設(shè)置系統(tǒng)壁紙,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • Android View教程之自定義驗證碼輸入框效果

    Android View教程之自定義驗證碼輸入框效果

    這篇文章主要給大家介紹了關(guān)于Android View教程之自定義驗證碼輸入框效果的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Android仿微信朋友圈實現(xiàn)滾動條下拉反彈效果

    Android仿微信朋友圈實現(xiàn)滾動條下拉反彈效果

    這篇文章主要為大家介紹了Android仿微信朋友圈實現(xiàn)滾動條下拉反彈效果,感興趣的小伙伴們可以參考一下
    2016-01-01
  • Android開發(fā)實例之多點觸控程序

    Android開發(fā)實例之多點觸控程序

    本文主要介紹 Android開發(fā)多點觸控,這里提供了詳細(xì)的資料和示例代碼,以及實現(xiàn)效果圖,有開發(fā)Android應(yīng)用需要這樣的功能的小伙伴可以參考下
    2016-08-08
  • Kotlin定義其他類的實現(xiàn)詳解

    Kotlin定義其他類的實現(xiàn)詳解

    這篇文章主要介紹了Kotlin定義其他類的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-09-09
  • Android實現(xiàn)水波紋效果

    Android實現(xiàn)水波紋效果

    這篇文章主要介紹了Android實現(xiàn)水波紋效果的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-10-10
  • android實現(xiàn)模擬加載中的效果

    android實現(xiàn)模擬加載中的效果

    本篇文章主要介紹的是android實現(xiàn)模擬加載中的效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-10-10
  • Android加載大分辨率圖片到手機(jī)內(nèi)存中的實例方法

    Android加載大分辨率圖片到手機(jī)內(nèi)存中的實例方法

    有些圖片的分辨率比較高,把它直接加載到手機(jī)內(nèi)存中之后,會導(dǎo)致堆內(nèi)存溢出的問題,下面就講解一下Android的堆內(nèi)存以及如何在Android應(yīng)用中加載一個高分辨率的圖片的方法
    2013-11-11

最新評論