可以播放GIF的自定义控件

可以播放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()
    }
} 

参考自互联网

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值