Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

另外一种实现方式 #13

Open
nobeginning opened this issue Feb 12, 2018 · 1 comment
Open

另外一种实现方式 #13

nobeginning opened this issue Feb 12, 2018 · 1 comment

Comments

@nobeginning
Copy link

用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")
    }
}
@Mr-wangyong
Copy link
Owner

大佬666

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants