之前封装的弹窗,搞了一个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)
}
}
}
}
}