可以播放GIF的自定义控件
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Movie
import android.os.Build
import android.os.SystemClock
import android.support.annotation.IntDef
import android.support.annotation.RawRes
import android.util.AttributeSet
import android.view.View
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
/*
* @文件名: GifView
* @创建时间: 2018/7/24 11:50
* @描述: TODO
*/
class GifView : View {
companion object {
const val SCALE_TYPE_DEF = 0
const val SCALE_TYPE_EQUAL_RATIO = 1
}
@SuppressLint("UniqueConstants")
@IntDef(SCALE_TYPE_DEF, SCALE_TYPE_EQUAL_RATIO)
@Retention(RetentionPolicy.SOURCE)
annotation class ScaleType
private @ScaleType
var scaleType = SCALE_TYPE_DEF
set(@ScaleType value) {
field = value
}
get() = field
private var isVisible = false
private var movie: Movie? = null
private var movieStartTime: Long = 0
private var playTime = 0
private var scaleW = 1f
private var scaleH = 1f
private var mScale = 1f
private var viewW = 0
private var viewH = 0
private var mTop = 0f
private var mLeft = 0f
private var isPaused: Boolean = false
set(value) {
field = value
invalidates()
}
get() = field
var gifRes: Int = R.mipmap.coffe
set(gifRes) {
field = gifRes
setMovie(gifRes)
requestLayout()
}
get() = field
var defDuration = 1000
set(value) {
field = value
}
get() = field
private fun setMovie(@RawRes gifRes: Int) {
movie = Movie.decodeStream(resources.openRawResource(gifRes))
}
constructor(context: Context?) : this(context, null)
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, R.styleable.CustomTheme_gifViewStyle)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
setViewAttributes(context, attrs, R.styleable.CustomTheme_gifViewStyle)
}
fun setViewAttributes(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) {
val array = context?.obtainStyledAttributes(attrs, R.styleable.GifView, defStyleAttr, R.style.Widget_GifView)
if (array != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null)
}
gifRes = array.getResourceId(R.styleable.GifView_gif, gifRes)
isPaused = array.getBoolean(R.styleable.GifView_paused, isPaused)
scaleType = array.getInteger(R.styleable.GifView_scale_type, SCALE_TYPE_EQUAL_RATIO)
array.recycle()
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
if (movie != null) {
val movieWidth = movie?.width()
val movieHeight = movie?.height()
val widthSize = MeasureSpec.getSize(widthMeasureSpec)
val heightSize = MeasureSpec.getSize(heightMeasureSpec)
scaleW = widthSize / movieWidth?.toFloat()!!
scaleH = heightSize / movieHeight?.toFloat()!!
when (scaleType) {
SCALE_TYPE_DEF -> {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
SCALE_TYPE_EQUAL_RATIO -> {
mScale = Math.min(scaleH, scaleW)
scaleW = mScale
scaleH = mScale
viewW = (movieWidth * mScale).toInt()
viewH = (movieHeight * mScale).toInt()
setMeasuredDimension(MeasureSpec.makeMeasureSpec(viewW, MeasureSpec.getMode(widthMeasureSpec)),
MeasureSpec.makeMeasureSpec(viewH, MeasureSpec.getMode(heightMeasureSpec)))
}
}
} else
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
mLeft = (height - viewH) / 2f
mTop = (width - viewW) / 2f
isVisible = visibility == VISIBLE
}
override fun onDraw(canvas: Canvas?) {
if (movie != null) {
if (!isPaused) {
refurbishTime()
drawMovie(canvas)
invalidates()
} else {
drawMovie(canvas)
}
}
}
private fun invalidates() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
postInvalidateOnAnimation()
} else {
invalidate()
}
}
private fun refurbishTime() {
val millis = SystemClock.uptimeMillis()
if (movieStartTime == 0L) {
movieStartTime = millis
}
val duration = movie?.duration()
playTime = ((millis - movieStartTime) % (if (duration != null && duration != 0) duration as Int else defDuration)).toInt()
}
private fun drawMovie(canvas: Canvas?) {
movie?.setTime(playTime)
canvas?.save()
canvas?.scale(scaleW, scaleH)
movie?.draw(canvas, mLeft, mTop)
canvas?.restore()
}
fun play() {
if (isPaused) {
movieStartTime = SystemClock.uptimeMillis() - playTime
invalidates()
}
}
fun Pause() {
if (!isPaused) {
isPaused = true
invalidates()
}
}
override fun onWindowVisibilityChanged(visibility: Int) {
super.onWindowVisibilityChanged(visibility)
isVisible = visibility == VISIBLE
invalidates()
}
override fun onScreenStateChanged(screenState: Int) {
super.onScreenStateChanged(screenState)
isVisible = screenState == SCREEN_STATE_ON
invalidates()
}
override fun onVisibilityChanged(changedView: View?, visibility: Int) {
super.onVisibilityChanged(changedView, visibility)
isVisible = visibility == VISIBLE
invalidates()
}
}
参考自互联网