package com.xiasuhuei321.gank_kotlin.customview.weather
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.PointF
import com.xiasuhuei321.gank_kotlin.context
import com.xiasuhuei321.gank_kotlin.extension.getScreenWidth
import java.util.*
/**
* Created by xiasuhuei321 on 2017/9/5.
* author:luo
* e-mail:xiasuhuei321@163.com
*
* desc: All shape's parent class.It describes a shape will have
* what feature.It's draw flows are:
* 1.Outside the class init some value such as the start and the
* end point.
* 2.Invoke draw(Canvas) method, in this method, there are still
* two flows:
* 1) Get random value to init paint, this will affect the shape
* draw style.
* 2) When the shape is not used, invoke init method, and when it
* is not used invoke drawWhenInUse(Canvas) method. It should be
* override by user and to implement draw itself.
*
*/
abstract class WeatherShape(val start: PointF, val end: PointF) {
open var TAG = "WeatherShape"
/**
* 是否是正在被使用的状态
*/
var isInUse = false
/**
* 是否是随机刷新的Shape
*/
var isRandom = false
/**
* 下落的速度,特指垂直方向,子类可以实现自己水平方向的速度
*/
var speed = 0.05f
/**
* shape的宽度
*/
var width = 5f
var shapeAlpha = 100
var paint = Paint().apply {
strokeWidth = width
isAntiAlias = true
alpha = alpha
}
// 总共下落的时间
var lastTime = 0L
// 原始x坐标位置
var originX = 0f
/**
* 根据自己的规则计算加速度,如果是匀速直接 return 0
*/
abstract fun getAcceleration(): Float
/**
* 绘制自身,这里在Shape是非使用的时候进行一些初始化操作
*/
open fun draw(canvas: Canvas) {
if (!isInUse) {
lastTime += randomPre()
initStyle()
isInUse = true
} else {
drawWhenInUse(canvas)
}
}
/**
* Shape在使用的时候调用此方法
*/
abstract fun drawWhenInUse(canvas: Canvas)
/**
* 初始化Shape风格
*/
open fun initStyle() {
val random = Random()
// 获取随机透明度
shapeAlpha = random.nextInt(155) + 50
// 获得起点x偏移
val translateX = random.nextInt(10).toFloat() + 5
if (!isRandom) {
start.x = translateX + originX
end.x = translateX + originX
} else {
// 如果是随机Shape,将x坐标随机范围扩大到整个屏幕的宽度
val randomWidth = random.nextInt(context.getScreenWidth())
start.x = randomWidth.toFloat()
end.x = randomWidth.toFloat()
}
speed = randomSpeed(random)
// 初始化length的工作留给之后对应的子类去实现
// 初始化color也留给子类去实现
paint.apply {
alpha = shapeAlpha
strokeWidth = width
isAntiAlias = true
}
// 如果有什么想要做的,刚好可以在追加上完成,就使用这个函数
wtc(random)
}
/**
* Empty body, this will be invoke in initStyle
* method.If current initStyle method can satisfy your need
* but you still add something, by override this method
* will be a good idea to solve the problem.
*/
open fun wtc(random:Random): Unit {
}
abstract fun randomSpeed(random: Random): Float
/**
* 获取一个随机的提前量,让shape在竖屏上有一个初始的偏移
*/
open fun randomPre(): Long {
val random = Random()
val pre = random.nextInt(1000).toLong()
return pre
}
}
package com.xiasuhuei321.gank_kotlin.customview.weather
import android.graphics.*
import com.xiasuhuei321.gank_kotlin.context
import com.xiasuhuei321.gank_kotlin.extension.getScreenHeight
import java.util.*
/**
* Created by xiasuhuei321 on 2017/9/5.
* author:luo
* e-mail:xiasuhuei321@163.com
*/
class Snow(start: PointF, end: PointF) : WeatherShape(start, end) {
/**
* 圆心,用户可以改变这个值
*/
var center = calcCenter()
/**
* 半径
*/
var radius = 10f
override fun getAcceleration(): Float {
return 0f
}
override fun drawWhenInUse(canvas: Canvas) {
// 通过圆心与半径确定圆的位置及大小
val distance = speed * lastTime
center.y += distance
start.y += distance
end.y += distance
lastTime += 16
canvas.drawCircle(center.x, center.y, radius, paint)
if (end.y > context.getScreenHeight()) clear()
}
fun calcCenter(): PointF {
val center = PointF(0f, 0f)
center.x = (start.x + end.x) / 2f
center.y = (start.y + end.y) / 2f
return center
}
override fun randomSpeed(random: Random): Float {
// 获取随机速度0.005 ~ 0.01
return (random.nextInt(5) + 5) / 1000f
}
override fun wtc(random: Random) {
// 设置颜色渐变
val shader = RadialGradient(center.x, center.y, radius,
Color.parseColor("#FFFFFF"), Color.parseColor("#D1D1D1"),
Shader.TileMode.CLAMP)
// 外部设置的起始点其实并不对,先计算出半径
radius = random.nextInt(10) + 15f
// 根据半径计算start end
end.x = start.x + radius
end.y = start.y + radius
// 计算圆心
calcCenter()
paint.apply {
setShader(shader)
}
}
fun clear() {
isInUse = false
lastTime = 0
start.y = -radius * 2
end.y = 0f
center = calcCenter()
}
}
package com.xiasuhuei321.gank_kotlin.customview.weather
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.PixelFormat
import android.graphics.PorterDuff
import android.util.AttributeSet
import android.view.SurfaceHolder
import android.view.SurfaceView
import com.xiasuhuei321.gank_kotlin.extension.LogUtil
import java.lang.Exception
/**
* Created by xiasuhuei321 on 2017/9/5.
* author:luo
* e-mail:xiasuhuei321@163.com
*/
class WeatherView(context: Context, attributeSet: AttributeSet?, defaultStyle: Int) :
SurfaceView(context, attributeSet, defaultStyle), SurfaceHolder.Callback {
private val TAG = "WeatherView"
constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0)
constructor(context: Context) : this(context, null, 0)
// 低级并发,Kotlin中支持的不是很好,所以用一下黑科技
val lock = Object()
var type = Weather.RAIN
var weatherShapePool = WeatherShapePool()
@Volatile var canRun = false
@Volatile var threadQuit = false
var thread = Thread {
while (!threadQuit) {
if (!canRun) {
synchronized(lock) {
try {
LogUtil.i(TAG, "条件尚不充足,阻塞中...")
lock.wait()
} catch (e: Exception) {
}
}
}
val startTime = System.currentTimeMillis()
try {
// 正式开始表演
val canvas = holder.lockCanvas()
if (canvas != null) {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
draw(canvas, type, startTime)
}
holder.unlockCanvasAndPost(canvas)
val drawTime = System.currentTimeMillis() - startTime
// 平均16ms一帧才能有顺畅的感觉
if (drawTime < 16) {
Thread.sleep(16 - drawTime)
}
} catch (e: Exception) {
// e.printStackTrace()
}
}
}.apply { name = "WeatherThread" }
override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
// surface发生了变化
// canRun = true
}
override fun surfaceDestroyed(holder: SurfaceHolder?) {
// 在这里释放资源
canRun = false
LogUtil.i(TAG, "surfaceDestroyed")
}
override fun surfaceCreated(holder: SurfaceHolder?) {
threadQuit = false
canRun = true
try {
// 如果没有执行wait的话,这里notify会抛异常
synchronized(lock) {
lock.notify()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
init {
LogUtil.i(TAG, "init开始")
holder.addCallback(this)
holder.setFormat(PixelFormat.RGBA_8888)
// initData()
setZOrderOnTop(true)
// setZOrderMediaOverlay(true)
thread.start()
}
private fun draw(canvas: Canvas, type: Weather, startTime: Long) {
// type什么的先放一边,先实现一个
weatherShapePool.drawSnow(canvas)
}
enum class Weather {
RAIN,
SNOW
}
fun onDestroy() {
threadQuit = true
canRun = true
try {
synchronized(lock) {
lock.notify()
}
} catch (e: Exception) {
}
}
}
package com.xiasuhuei321.gank_kotlin.customview.weather
import android.graphics.Canvas
import android.graphics.PointF
import com.xiasuhuei321.gank_kotlin.context
import com.xiasuhuei321.gank_kotlin.extension.getScreenWidth
/**
* Created by xiasuhuei321 on 2017/9/7.
* author:luo
* e-mail:xiasuhuei321@163.com
*/
class WeatherShapePool {
val constantRain = ArrayList<Rain>()
val randomRain = ArrayList<Rain>()
val constantSnow = ArrayList<Snow>()
val randomSnow = ArrayList<Snow>()
init {
// 初始化
initData()
initSnow()
}
private fun initData() {
val space = context.getScreenWidth() / 20
var currentSpace = 0f
// 将其均匀的分布在屏幕x方向上
for (i in 0..19) {
val rain = Rain(PointF(currentSpace, 0f), PointF(currentSpace, 0f))
rain.originLength = 20f
rain.originX = currentSpace
constantRain.add(rain)
currentSpace += space
}
for (j in 0..9) {
val rain = Rain(PointF(0f, 0f), PointF(0f, 0f))
rain.isRandom = true
rain.originLength = 20f
randomRain.add(rain)
}
}
fun drawRain(canvas: Canvas) {
for (r in constantRain) {
r.draw(canvas)
}
for (r in randomRain) {
r.draw(canvas)
}
}
private fun initSnow(){
val space = context.getScreenWidth() / 20
var currentSpace = 0f
// 将其均匀的分布在屏幕x方向上
for (i in 0..19) {
val snow = Snow(PointF(currentSpace, 0f), PointF(currentSpace, 0f))
snow.originX = currentSpace
snow.radius = 20f
constantSnow.add(snow)
currentSpace += space
}
for (j in 0..19) {
val snow = Snow(PointF(0f, 0f), PointF(0f, 0f))
snow.isRandom = true
snow.radius = 20f
randomSnow.add(snow)
}
}
fun drawSnow(canvas: Canvas){
for(r in constantSnow){
r.draw(canvas)
}
for (r in randomSnow){
r.draw(canvas)
}
}
}
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有