android 弹窗,菜单

之前封装的弹窗,搞了一个2.0的版本,加了配置类,用于定制。先看一下,使用方法

//继承BaseMenuWork覆盖对应的binding
class MusicListWindow :
    BaseMenuWork<LayoutXXBinding> {

    var mContext: WeakReference<AppCompatActivity>//如果用到了上下文要用弱引用。避免内存泄露
    


    var onHideWindow: (() -> Unit)? = null//可以根据需要,去定义一些回调的方法

    constructor(context: Activity, view: View?) : super(
        context,
        MenuConfig.Build().setGravityV(Gravity.BOTTOM).setGravityH(Gravity.RIGHT)
            .setMenuWidth(575 + 22).setMenuHeight(545)
            .setAppearAnim(
                arrayOf(
                    ObjectAnimator.ofFloat(null, "translationY", 545f, 0f),
                    ObjectAnimator.ofFloat(null, "translationX", 575f, 0f)
                )
            )
            .setDisappearAnim(
                arrayOf(
                    ObjectAnimator.ofFloat(null, "translationY", 0f, 545f),
                    ObjectAnimator.ofFloat(null, "translationX", 0f, 575f)
                )
            ).setNewRoot(true).build(),
        view
    ) {
//新增的构造方法,可以传入相关的配置,定制弹窗的动画,大小,位置等
        mContext = WeakReference(context as AppCompatActivity)
        cancalOnclickSpace = false//点击空白是否消失
        transSpace = true//空白区域是否拦截点击时间,如果是true则不拦截点击事件
        //实现一些点击事件,和初始化一些业务逻辑等等

        binding.ivClose.setOnClickListener {
            hindWindow()
        }
        binding.ivSearch.setOnClickListener {
           //...
            
        }
    }


   
    override fun getBindingInstance(context: Activity): LayoutMusicListBinding {
        return LayoutMusicListBinding.inflate(context.layoutInflater)
    }
}

接下来是MenuCofig和BaseMenuWork的源代码

class MenuConfig {
    private constructor()

    companion object {
        fun Build(): ConfigBuild {
            return ConfigBuild(MenuConfig())
        }
    }

    private var gravityH = Gravity.TOP
    private var gravityV = Gravity.LEFT
    private var menuWidth = ViewGroup.LayoutParams.MATCH_PARENT
    private var menuHeight = ViewGroup.LayoutParams.MATCH_PARENT
    private var animAppear = arrayOf( ObjectAnimator.ofFloat(null, "translationY", 400f, 0f))
    private var animDisAppear = arrayOf(ObjectAnimator.ofFloat(null, "translationY", 0f, 400f))
    private var newRootId = false
    private var newId: Int = -1
    private var marginLeft = 0
    private var marginRight = 0
    private var marginTop = 0
    private var marginBottom = 0
    fun getGravityH(): Int {
        return gravityH
    }

    fun getGravityV(): Int {
        return gravityV
    }

    fun getAppearAnim():Array< ObjectAnimator> {
        return animAppear
    }

    fun getDisappearAnim(): Array<ObjectAnimator> {
        return animDisAppear
    }

    fun getMenuH(): Int {
        return menuHeight
    }

    fun getMenuW(): Int {
        return menuWidth
    }

    fun isNewRoot(): Boolean {
        return newRootId
    }

    fun getNewId(): Int {
        return newId
    }

    fun getMarginLeft(): Int {
        return marginLeft
    }

    fun getMarginRight1(): Int {
        return marginRight
    }

    fun getMarginTop(): Int {
        return marginTop
    }

    fun getMarginBottom(): Int {
        return marginBottom
    }

    class ConfigBuild(config: MenuConfig) {
        val config = config
        fun setGravityH(gravity: Int): ConfigBuild {
            config.gravityH = gravity
            return this
        }

        fun setGravityV(gravity: Int): ConfigBuild {
            config.gravityV = gravity
            return this
        }

        fun setAppearAnim(anim: Array<ObjectAnimator>): ConfigBuild {
            config.animAppear = anim
            return this
        }

        fun setDisappearAnim(anim:Array< ObjectAnimator>): ConfigBuild {
            config.animDisAppear = anim
            return this
        }

        fun setMenuHeight(h: Int): ConfigBuild {
            config.menuHeight = h
            return this
        }

        fun setMenuWidth(w: Int): ConfigBuild {
            config.menuWidth = w
            return this
        }

        fun setNewRoot(boolean: Boolean): ConfigBuild {
            config.newRootId = boolean
            return this
        }

        fun setNewId(id: Int): ConfigBuild {
            config.newId = id
            return this
        }

        fun setMarginLeft(a: Int): ConfigBuild {
            config.marginLeft = a
            return this
        }

        fun setMarginRight(a: Int): ConfigBuild {
            config.marginRight = a
            return this
        }

        fun setMarginBottom(a: Int): ConfigBuild {
            config.marginBottom = a
            return this
        }

        fun setMarginTop(a: Int): ConfigBuild {
            config.marginTop = a
            return this
        }

        fun setMargin(a: Int): ConfigBuild {
            config.marginTop = a
            config.marginBottom = a
            config.marginRight = a
            config.marginLeft = a
            return this
        }

        fun build(): MenuConfig {
            return config
        }


    }
}

 




abstract class BaseMenuWork<T : ViewBinding> {

    protected val binding: T
    val weakReference: WeakReference<Activity>;
    protected var constraintLayout: ConstraintLayout
    var view: View? = null
    protected var animAppear: Array<ObjectAnimator>
    protected var animDisAppear: Array<ObjectAnimator>
    protected var menuWidth = ViewGroup.LayoutParams.MATCH_PARENT
    protected var menuHeight = ViewGroup.LayoutParams.MATCH_PARENT
    protected var gravityH = Gravity.LEFT
    protected var gravityV = Gravity.TOP
    protected var cancalOnclickSpace = true
    protected var marginLeft = 0
    protected var marginRight = 0
    protected var marginTop = 0
    protected var marginBottom = 0
    protected var transSpace = false

    constructor(context: Activity, view: View?) {
        val config = MenuConfig.Build().config
        this.view = view
        weakReference = WeakReference(context)
        this.binding = getBindingInstance(context)
        binding?.root?.id = View.generateViewId()
        gravityH = config.getGravityH()
        gravityV = config.getGravityV()
        menuHeight = config.getMenuH()
        menuWidth = config.getMenuW()
        animAppear = config.getAppearAnim()
        animDisAppear = config.getDisappearAnim()
        if ((context.findViewById<ConstraintLayout>(R.id.widget_menu_root) == null)) {
            constraintLayout = ConstraintLayout(context)
            addView()
        } else {
            constraintLayout = context.findViewById(R.id.widget_menu_root)
        }
    }


    constructor(context: Activity, config: MenuConfig, view: View?) {
        this.view = view
        weakReference = WeakReference(context)
        this.binding = getBindingInstance(context)
        binding?.root?.id = View.generateViewId()
        gravityH = config.getGravityH()
        gravityV = config.getGravityV()
        menuHeight = config.getMenuH()
        menuWidth = config.getMenuW()
        marginRight = config.getMarginRight1()
        marginLeft = config.getMarginLeft()
        marginTop = config.getMarginTop()
        marginBottom = config.getMarginBottom()
        animAppear = config.getAppearAnim()
        animDisAppear = config.getDisappearAnim()
        if (config.isNewRoot()) {
            var id: Int = config.getNewId()
            if (id == -1) {
                id = config.getNewId()
            }
            if ((context.findViewById<ConstraintLayout>(id) == null)) {
                constraintLayout = ConstraintLayout(context)
                addView()
            } else {
                constraintLayout = context.findViewById(id)
            }
        } else {
            if ((context.findViewById<ConstraintLayout>(R.id.widget_menu_root) == null)) {
                constraintLayout = ConstraintLayout(context)
                addView()
            } else {
                constraintLayout = context.findViewById(R.id.widget_menu_root)
            }
        }
    }

    fun getActivity(): Activity? {
        return weakReference.get()
    }


    protected abstract fun getBindingInstance(context: Activity): T
    private fun addView() {
        getActivity()?.let { context ->
            constraintLayout.layoutParams = ConstraintLayout.LayoutParams(
                ConstraintLayout.LayoutParams.MATCH_PARENT,
                ConstraintLayout.LayoutParams.MATCH_PARENT
            )
            addAnim(constraintLayout)
            constraintLayout.id = R.id.widget_menu_root

            if (view == null) {
                (context.window.decorView as ViewGroup).addView(constraintLayout)
            } else {
                view?.let {
                    (it.parent as ViewGroup).addView(constraintLayout)
                }
            }
        }
    }

    fun showMenuNoAnim() {
        if (constraintLayout.childCount > 0) {
            return
        }
        constraintLayout.layoutTransition.disableTransitionType(LayoutTransition.APPEARING)
        if (!transSpace) {
            constraintLayout.isClickable = true
//        constraintLayout.setBackgroundColor(Color.parseColor("#80000000"))
            if (cancalOnclickSpace) {
                constraintLayout.setOnClickListener({
                    if (constraintLayout.childCount > 0) {
                        hindMenu()
                    }
                })
            }
        }
        var cs = ConstraintSet()
        constraintLayout.addView(binding.root, menuWidth, menuHeight)
        cs.clone(constraintLayout)
        if (gravityH != Gravity.LEFT) {
            cs.connect(
                binding.root.id,
                ConstraintSet.RIGHT,
                constraintLayout.id,
                ConstraintSet.RIGHT,
                marginRight
            )
        }
        if (gravityH != Gravity.RIGHT) {
            cs.connect(
                binding.root.id,
                ConstraintSet.LEFT,
                constraintLayout.id,
                ConstraintSet.LEFT,
                marginLeft
            )
        }
        if (gravityV != Gravity.TOP) {
            cs.connect(
                binding.root.id,
                ConstraintSet.BOTTOM,
                constraintLayout.id,
                ConstraintSet.BOTTOM, marginBottom
            )
        }
        if (gravityV != Gravity.BOTTOM) {
            cs.connect(
                binding.root.id,
                ConstraintSet.TOP,
                constraintLayout.id,
                ConstraintSet.TOP,
                marginTop
            )
        }
        cs.applyTo(constraintLayout)
    }


    fun showMenu() {
        if (constraintLayout.childCount > 0) {
            return
        }
        constraintLayout.layoutTransition.enableTransitionType(LayoutTransition.APPEARING)
        if (!transSpace) {
            constraintLayout.isClickable = true
//        constraintLayout.setBackgroundColor(Color.parseColor("#80000000"))
            if (cancalOnclickSpace) {
                constraintLayout.setOnClickListener({
                    if (constraintLayout.childCount > 0) {
                        hindMenu()
                    }
                })
            }
        }
        constraintLayout.addView(binding.root, menuWidth, menuHeight)
        var cs = ConstraintSet()
        cs.clone(constraintLayout)
        if (gravityH != Gravity.LEFT) {
            cs.connect(
                binding.root.id,
                ConstraintSet.RIGHT,
                constraintLayout.id,
                ConstraintSet.RIGHT,
                marginRight
            )
        }
        if (gravityH != Gravity.RIGHT) {
            cs.connect(
                binding.root.id,
                ConstraintSet.LEFT,
                constraintLayout.id,
                ConstraintSet.LEFT,
                marginLeft
            )
        }
        if (gravityV != Gravity.TOP) {
            cs.connect(
                binding.root.id,
                ConstraintSet.BOTTOM,
                constraintLayout.id,
                ConstraintSet.BOTTOM, marginBottom
            )
        }
        if (gravityV != Gravity.BOTTOM) {
            cs.connect(
                binding.root.id,
                ConstraintSet.TOP,
                constraintLayout.id,
                ConstraintSet.TOP,
                marginTop
            )
        }
        cs.applyTo(constraintLayout)

    }
    fun hindMenuNoAnim() {
        constraintLayout.layoutTransition.disableTransitionType(LayoutTransition.DISAPPEARING)
        constraintLayout.isClickable = false
//        constraintLayout.setBackgroundColor(Color.parseColor("#00000000"))
        constraintLayout.removeView(binding.root)
    }

    fun hindMenu() {
        constraintLayout.layoutTransition.enableTransitionType(LayoutTransition.DISAPPEARING)
        constraintLayout.isClickable = false
//        constraintLayout.setBackgroundColor(Color.parseColor("#00000000"))
        constraintLayout.removeView(binding.root)
    }

    private fun addAnim(v: ViewGroup) {
        var mLayoutTransition = LayoutTransition();
        mLayoutTransition.setAnimator(LayoutTransition.APPEARING, getAppearingAnimation());
        mLayoutTransition.setDuration(LayoutTransition.APPEARING, 200);
//        mLayoutTransition.setStartDelay(
//            LayoutTransition.APPEARING,
//            0
//        );
        mLayoutTransition.enableTransitionType(LayoutTransition.APPEARING);

//
//        mLayoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, getAppearingAnimation());
//        mLayoutTransition.setDuration(LayoutTransition.CHANGE_APPEARING,200);
//        mLayoutTransition.enableTransitionType(LayoutTransition.CHANGE_APPEARING);
//        mLayoutTransition.setStartDelay(
//            LayoutTransition.CHANGE_APPEARING,
//            0
//        );
//
        mLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, getDisappearingAnimation());
        mLayoutTransition.setDuration(LayoutTransition.DISAPPEARING, 200);
        mLayoutTransition.enableTransitionType(LayoutTransition.DISAPPEARING);
        mLayoutTransition.setStartDelay(
            LayoutTransition.DISAPPEARING,
            0
        );
        mLayoutTransition.setStartDelay(
            LayoutTransition.APPEARING,
            0
        );

        mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_APPEARING)
        mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING)
        mLayoutTransition.disableTransitionType(LayoutTransition.CHANGING)


//        mLayoutTransition.setAnimator(
//            LayoutTransition.CHANGE_DISAPPEARING,
//            getDisappearingChangeAnimation()
//        );
//        mLayoutTransition.setDuration(LayoutTransition.CHANGE_DISAPPEARING,200);
//        mLayoutTransition.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
//        mLayoutTransition.setStartDelay(
//            LayoutTransition.CHANGE_DISAPPEARING,
//            0
//        );

        mLayoutTransition.addTransitionListener(object : LayoutTransition.TransitionListener {
            override fun startTransition(
                transition: LayoutTransition?,
                container: ViewGroup?,
                view: View?,
                transitionType: Int
            ) {

            }

            override fun endTransition(
                transition: LayoutTransition?,
                container: ViewGroup?,
                view: View?,
                transitionType: Int
            ) {

            }
        });

        v.setLayoutTransition(mLayoutTransition);
    }

    @SuppressLint("ObjectAnimatorBinding")
    open protected fun getAppearingAnimation(): Animator {
        var mSet = AnimatorSet();
        mSet.playTogether(
//            ObjectAnimator.ofFloat(null, "ScaleX", 2.0f, 1.0f),
//            ObjectAnimator.ofFloat(null, "ScaleY", 2.0f, 1.0f),
//            ObjectAnimator.ofFloat(null, "Alpha", 0.0f, 1.0f),
            animAppear.toList()
        )
        return mSet;
    }

    @SuppressLint("ObjectAnimatorBinding")
    open protected fun getDisappearingAnimation(): Animator {
        var mSet = AnimatorSet();
        mSet.playTogether(
//            ObjectAnimator.ofFloat(null, "ScaleX", 1.0f, 0f),
//            ObjectAnimator.ofFloat(null, "ScaleY", 1.0f, 0f),
//            ObjectAnimator.ofFloat(null, "Alpha", 1.0f, 0.0f),
            animDisAppear.toList()
        );
        return mSet;
    }

    open protected fun getDisappearingChangeAnimation(): Animator {
        var pvhLeft = PropertyValuesHolder.ofInt("left", 0, 0);
        var pvhTop = PropertyValuesHolder.ofInt("top", 0, 0);
        var pvhRight = PropertyValuesHolder.ofInt("right", 0, 0);
        var pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 0);
        var scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0f, 1.0f);
        var scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0f, 1.0f);
        var rotate = PropertyValuesHolder.ofFloat("rotation", 0f, 0f, 0f);
        return ObjectAnimator.ofPropertyValuesHolder(
            pvhLeft,
            pvhTop,
            pvhRight,
            pvhBottom,
            scaleX,
            scaleY,
            rotate
        );
    }

    open protected fun getAppearingChangeAnimation(): Animator {
        var pvhLeft = PropertyValuesHolder.ofInt("left", 0, 0);
        var pvhTop = PropertyValuesHolder.ofInt("top", 0, 0);
        var pvhRight = PropertyValuesHolder.ofInt("right", 0, 0);
        var pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 0);
        var scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 3f, 1.0f);
        var scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 3f, 1.0f);
        return ObjectAnimator.ofPropertyValuesHolder(
            pvhLeft,
            pvhTop,
            pvhRight,
            pvhBottom,
            scaleX,
            scaleY
        );
    }

    fun removeView() {
        getActivity()?.let { context ->
            constraintLayout.removeView(binding.root)
            if (view == null) {
                (context.window.decorView as ViewGroup).removeView(constraintLayout)
            } else {
                view?.let {
                    (it.parent as ViewGroup).removeView(constraintLayout)
                }

            }
        }
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值