ImageFrame
ImageFrame copied to clipboard
另外一种实现方式
用Kotlin实现的另外一种方式的思路。看一下是否有参考价值
用法:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_anim);
View imageView = findViewById(R.id.imageView);
List<Integer> resources = new ArrayList<>(32);
Resources res = getResources();
final String packageName = getPackageName();
for (int i=1; i<=210; i++){
String resName = "gift_" + i;
int imageResId = res.getIdentifier(resName, "drawable", packageName);
resources.add(imageResId);
}
controller = FrameAnim.Companion.create()
.target(imageView) //target支持任意View
.resources(resources)
.duration(16)
.controller();
controller.start();
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (controller == null) {
return;
}
if (controller.isPaused()) {
controller.resume();
} else {
controller.pause();
}
}
});
}
主要功能类如下:
import android.graphics.drawable.BitmapDrawable
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.support.v4.view.ViewCompat
import android.util.Log
import android.view.View
import com.mrwang.imageframe.BitmapLoadUtils
import com.mrwang.imageframe.ImageCache
import java.lang.ref.SoftReference
/**
* Created by young on 2018/2/8.
*/
class FrameAnim {
companion object {
fun create(): FrameAnim {
return FrameAnim()
}
}
interface AnimEndCallBack{
fun onAnimEnd()
}
interface AnimLoopedCallBack{
fun onAnimLooped(loopedCount:Int)
}
/**
* 遥控器
*/
interface Controller {
fun start()
fun isPaused(): Boolean
fun pause()
fun resume()
fun destroy()
}
private inner class ControllerImpl(val ext: FrameAnim) : Controller {
override fun start() {
ext.start()
}
override fun destroy() {
ext.destroy()
}
override fun isPaused(): Boolean {
return ext.paused
}
override fun pause() {
ext.pause()
}
override fun resume() {
ext.resume()
}
}
private val TAG = javaClass.simpleName
private var target: View? = null
private var list: List<Int>? = null
private var duration: Long = 300
private var index = 0
private val decodeThread = DecodeThread()
private var decodeHandler: Handler? = null
private val uiHandler = Handler(Looper.getMainLooper())
private var bitmapDrawable: BitmapDrawable? = null
private var isInitLoad = true
private var loop = true
private var loopedCount = 0
private var paused = false
private var destroyed = false
private val controller: Controller = ControllerImpl(this)
private var animEndCallBack:AnimEndCallBack? = null
private var animLoopedCallBack:AnimLoopedCallBack? = null
private val autoDestroy:IAutoDestroy = object : IAutoDestroy {
override fun autoDestroy() {
destroy()
}
}
fun target(target: View): FrameAnim {
this.target = target
return this
}
fun resources(list: List<Int>): FrameAnim {
this.list = list
return this
}
fun duration(duration: Long): FrameAnim {
this.duration = duration
return this
}
fun loop(lp: Boolean): FrameAnim {
this.loop = lp
return this
}
fun callBackForAnimEnd(endCallBack: AnimEndCallBack): FrameAnim {
this.animEndCallBack = endCallBack
return this
}
fun callBackForAnimLooped(loopedCallBack: AnimLoopedCallBack): FrameAnim {
this.animLoopedCallBack = loopedCallBack
return this
}
fun controller():Controller{
return controller
}
fun start(): Controller {
if (target == null) {
Log.w(TAG, "The target is Null")
throw IllegalArgumentException("The target must not be Null")
}
if (list == null || list!!.isEmpty()) {
Log.w(TAG, "The resources is Empty")
throw IllegalArgumentException("The resources must not be Null or Empty")
}
val ctx = target!!.context
ctx.registerAutoDestroy(autoDestroy)
if (decodeHandler!=null){
Log.e(TAG, "Task already started")
return controller
}
if (paused) {
Log.e(TAG, "Task is paused, Please use resume() to continue")
return controller
}
decodeThread.start()
if (decodeHandler == null) {
decodeHandler = Handler(decodeThread.looper)
}
load()
return controller
}
private fun pause() {
if (decodeHandler == null) {
throw IllegalStateException("Have u forgot to invoke the ``fun start()``")
}
paused = true
decodeHandler!!.removeCallbacksAndMessages(null)
uiHandler.removeCallbacksAndMessages(null)
}
private fun resume() {
if (decodeHandler == null) {
throw IllegalStateException("Have u forgot to invoke the ``fun start()``")
}
paused = false
load()
}
fun destroy() {
if (destroyed){
return
}
destroyed = true
decodeThread.quit()
uiHandler.removeCallbacks(uiCallBack)
println("Component has destroyed")
}
private var uiCallBack: Runnable? = null
private val imageCache = ImageCache()
private fun load() {
val resources = list!!
if (index >= resources.size && loop) {
index = 0
loopedCount++
animLoopedCallBack?.onAnimLooped(loopedCount)
} else if (index >= resources.size && !loop) {
Log.d(TAG, "The End")
println("The End")
animEndCallBack?.onAnimEnd()
return
}
if (bitmapDrawable != null) {
imageCache.mReusableBitmaps.add(SoftReference(bitmapDrawable!!.bitmap))
}
val resId = resources[index]
decodeHandler!!.post {
val start = System.currentTimeMillis()
val resource = target!!.resources
bitmapDrawable = BitmapLoadUtils.decodeSampledBitmapFromRes(resource, resId, 0,
0,
imageCache, true)
val end = System.currentTimeMillis()
val decodeConsuming = end - start
val delay = duration - decodeConsuming
val actDelay = if (delay > 0) delay else 0
val finalDelay = if (isInitLoad) 0 else actDelay
isInitLoad = false
uiCallBack = Runnable {
ViewCompat.setBackground(target, bitmapDrawable)
index++
load()
}
uiHandler.postDelayed(uiCallBack, finalDelay)
}
}
inner class DecodeThread : HandlerThread("DecodeThread")
}
自动处理生命周期:
interface IAutoDestroy {
fun autoDestroy()
}
class LifeFragment : Fragment() {
private val set: MutableSet<IAutoDestroy> = mutableSetOf()
fun register(autoDestroy: IAutoDestroy) {
set.add(autoDestroy)
}
override fun onDestroy() {
super.onDestroy()
for (autoDestroy in set) {
autoDestroy.autoDestroy()
}
}
}
fun Context.registerAutoDestroy(autoDestroy: IAutoDestroy) {
if (this is FragmentActivity) {
var exist = supportFragmentManager.findFragmentByTag("Hello")
if (exist == null) {
exist = LifeFragment()
supportFragmentManager.beginTransaction().add(exist, "Hello").commit()
}
if (exist is LifeFragment) {
exist.register(autoDestroy)
}
}else {
Log.e("registerAutoDestroy", "The context type do not support fragment")
}
}
大佬666