android 上拉菜单,Android 上拉菜单

Android 上拉菜单

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

46aaea42b167?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image

要求点击购物车,弹出后面的视图,弹出的视图要置于 购物车按钮 下方

Dialog会将购物车盖住。

所以自己写了个自定义View实现该功能。

46aaea42b167?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image

46aaea42b167?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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 即可

布局文件非常简单:

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"

>

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">

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"/>

下面是具体代码:

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() = {}

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值