美文网首页
Android 上拉菜单

Android 上拉菜单

作者: 红酥手黄藤酒丶 | 来源:发表于2019-01-08 23:07 被阅读0次

Android 上拉菜单

Dialog 会置于顶层,项目需求是这样的:


image

要求点击购物车,弹出后面的视图,弹出的视图要置于 购物车按钮 下方
Dialog会将购物车盖住。
所以自己写了个自定义View实现该功能。

image image

使用时实现 BottomPopupConstraintLayout.BottomConstraintLayoutAdap 接口:

class BottomAdapter(val context:Context):BottomPopupConstraintLayout.BottomConstraintLayoutAdapter{
    override fun getMaxHeight(): Int {
        val dp2px = DisplayUtil.dp2px(context, 462f)
        return dp2px
    }

    override fun getDuration(): Long {
        return 300
    }
}

必须实现的方法:
getMaxHeight() 从来设置 弹出的高度

剩下还有一些可选的方法,查看BottomPopupConstraintLayout.BottomConstraintLayoutAdapter 即可

布局文件非常简单:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    >

    <zyf.com.selectdemo.BottomPopupConstraintLayout
        android:id="@+id/likeDialog"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="gone"
        android:background="#00ff00"
        app:layout_constraintBottom_toBottomOf="parent">

    </zyf.com.selectdemo.BottomPopupConstraintLayout>


    <Button
        android:id="@+id/btnTest"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="点我"
        android:background="#ff0000"
        android:textColor="#ffffff"
        android:textSize="20sp"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="20dp"/>

</android.support.constraint.ConstraintLayout>

下面是具体代码:

package zyf.com.selectdemo
import android.animation.Animator
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Color
import android.support.constraint.ConstraintLayout
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup

/**
 * create by zyf on 2019/1/8 7:23 PM
 */
class BottomPopupConstraintLayout : ConstraintLayout {

    private val mShadowView: View = View(context)
    private var mIsShow = false
    private var mIsSliding = false

    private var mAlphaMin = 80

    private var slideTop: ValueAnimator? = null

    private var slideBottom: ValueAnimator? = null

    private lateinit var mAdapter: BottomConstraintLayoutAdapter


    constructor(context: Context) : this(context, null) {
    }


    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) {

    }

    constructor(context: Context, attrs: AttributeSet?, defstyleAttr: Int) : super(context, attrs, defstyleAttr) {
        mInit(context)
    }


    private fun mInit(context: Context) {


    }


    private fun mDeployAnimator() {

        slideTop = ValueAnimator.ofInt(mAdapter.getMinHeight(), mAdapter.getMaxHeight()).apply {
            addUpdateListener {
                val value = it.animatedValue as Int

                layoutParams.height = value
                requestLayout()

                if (mAdapter.showShadow()) {
                    mShadowView.setBackgroundColor(Color.argb(mAlphaMin * value / mAdapter.getMaxHeight(), 0, 0, 0))
                }
            }

            addListener(object : Animator.AnimatorListener {
                override fun onAnimationRepeat(animation: Animator?) {

                }

                override fun onAnimationCancel(animation: Animator?) {
                }

                override fun onAnimationStart(animation: Animator?) {
                    changeSlideStatus()
                    mShadowView.visibility = View.VISIBLE
                    visibility = View.VISIBLE

                }

                override fun onAnimationEnd(animation: Animator?) {
                    changeSlideStatus()
                    mAdapter.getShowCompleted().invoke()
                }

            })

            duration = mAdapter.getDuration()


        }
        slideBottom = ValueAnimator.ofInt(mAdapter.getMaxHeight(), mAdapter.getMinHeight()).apply {
            addUpdateListener {
                val value = it.animatedValue as Int
                layoutParams.height = value
                if(value == mAdapter.getMinHeight()){
                    visibility = View.GONE
                }
                requestLayout()
                if (mAdapter.showShadow()) {

                    if (value == mAdapter.getMinHeight()) {
                        mShadowView.setBackgroundColor(Color.argb(0, 0, 0, 0))

                    } else {
                        mShadowView.setBackgroundColor(Color.argb(mAlphaMin * value / maxHeight, 0, 0, 0))
                    }

                }
            }

            addListener(object : Animator.AnimatorListener {
                override fun onAnimationRepeat(animation: Animator?) {

                }

                override fun onAnimationCancel(animation: Animator?) {
                }

                override fun onAnimationStart(animation: Animator?) {
                    changeSlideStatus()
                }

                override fun onAnimationEnd(animation: Animator?) {
                    mShadowView.visibility = View.GONE
                    changeSlideStatus()
                    mAdapter.getHideCompleted().invoke()

                }

            })

            duration = mAdapter.getDuration()

        }
    }


    private fun mDeployShadow() {
        if (mAdapter.showShadow()) {
            mShadowView.apply {
                layoutParams =
                        ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
            }

            val viewGroup = parent as ViewGroup
            viewGroup.addView(mShadowView, 0)
            mShadowView.setOnClickListener {
                if (mAdapter.clickOutSideClose()) {
                    hide()
                }
            }
        }
    }

    private fun mDeployDefaultListener() {
        setOnClickListener { }
    }

    private fun changeSlideStatus() {
        mIsSliding = !mIsSliding
    }

    private fun changeShowStatus() {
        mIsShow = !mIsShow
    }

    fun showOrHide() {
        if (mIsShow) {
            hide()
        } else {
            show()
        }
    }

    fun show() {
        if (!mIsShow && !mIsSliding) {

            slideTop?.start()
            changeShowStatus()
        }
    }

    fun hide() {
        if (mIsShow && !mIsSliding) {

            slideBottom?.start()
            changeShowStatus()
        }
    }

    fun setAdapter(adapter: BottomConstraintLayoutAdapter) {
        mAdapter = adapter

        //配置动画
        mDeployAnimator()

        //配置阴影点击时间
        mDeployShadow()

        //配置点击默认点击时间,否则点击时间会穿过Constraint,使得Shadow响应
        mDeployDefaultListener()
    }


    interface BottomConstraintLayoutAdapter {
        fun getMaxHeight(): Int
        fun getMinHeight(): Int = 1
        fun showShadow(): Boolean = true
        fun clickOutSideClose(): Boolean = true
        fun getDuration(): Long = 500
        fun getHideCompleted() = {}
        fun getShowCompleted() = {}

    }
}

相关文章

网友评论

      本文标题:Android 上拉菜单

      本文链接:https://www.haomeiwen.com/subject/ljuirqtx.html