上图效果,代码如下:
主类:
class ContactsFilterPop(private val context: Activity, val mParent: View) {
private lateinit var mCommonPopupWindow: CommonPopupWindow
private lateinit var rv_contacts_filter: RecyclerView
private var mBlock: (contentSelected: String) -> Unit = {}
private var mContactsFilterAdapter: ContactsFilterAdapter? = null
private var mList: MutableList<ContactsFilterBean> = mutableListOf()
init {
init()
setListener()
}
private fun setListener() {
}
private fun init() {
val view = LayoutInflater.from(context).inflate(R.layout.contacts_pop_filter, null)
mList.clear()
mList = getItemsName()
rv_contacts_filter = view.findViewById(R.id.rv_contacts_filter)
if (mContactsFilterAdapter == null) {
mContactsFilterAdapter = ContactsFilterAdapter(R.layout.item_contacts_filter_pop, mList)
rv_contacts_filter.adapter = mContactsFilterAdapter
rv_contacts_filter.layoutManager =
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
} else {
mContactsFilterAdapter?.notifyDataSetChanged()
}
mContactsFilterAdapter?.setOnItemClickListener { adapter, view, position ->
mList?.forEach {
it.isSelected = false
}
mList[position].isSelected = true
mCommonPopupWindow.dismiss()
mContactsFilterAdapter?.notifyDataSetChanged()
mBlock.invoke(mList[position].itemContent)
}
mCommonPopupWindow = CommonPopupWindow.Builder(context)
.setView(view)
.setWidthAndHeight(ListPopupWindow.WRAP_CONTENT, ListPopupWindow.WRAP_CONTENT)
.setAnimationStyle(R.style.popwin_anim_style_top)
.setOutsideTouchable(true)
.create()
//动态设置popWindow的宽度
mCommonPopupWindow.width = App.SCREEN_WIDTH / 2
}
/**
* 设置弹窗内容
*
* @return
*/
private fun getItemsName(): ArrayList<ContactsFilterBean> {
val items = ArrayList<ContactsFilterBean>()
var contactsFilterItem1 = ContactsFilterBean()
//刚进来默认第一项选中
contactsFilterItem1.isSelected = true
contactsFilterItem1.itemContent = "A~Z"
items.add(contactsFilterItem1)
var contactsFilterItem2 = ContactsFilterBean()
contactsFilterItem2.isSelected = false
contactsFilterItem2.itemContent = "Recently Added"
items.add(contactsFilterItem2)
var contactsFilterItem3 = ContactsFilterBean()
contactsFilterItem3.isSelected = false
contactsFilterItem3.itemContent = "Star Rating"
items.add(contactsFilterItem3)
var contactsFilterItem4 = ContactsFilterBean()
contactsFilterItem4.isSelected = false
contactsFilterItem4.itemContent = "Recent Used"
items.add(contactsFilterItem4)
return items
}
fun show(block: (contentSelected: String) -> Unit = {}) {
mBlock = block
context.setWindowDark()
//动态设置popWindow距离顶部的距离
var mShowPop = mParent?.bottom / 3 * 4
mCommonPopupWindow.showAtLocation(mParent, Gravity.TOP, 0, mShowPop)
}
}
继承基类
class CommonPopupWindow private constructor(context: Context) : PopupWindow() {
internal val controller: PopupController = PopupController(context, this)
private var mIsDismissDark = false
override fun getWidth(): Int {
return controller.mPopupView!!.measuredWidth
}
override fun getHeight(): Int {
return controller.mPopupView!!.measuredHeight
}
interface ViewInterface {
fun getChildView(view: View?, layoutResId: Int)
}
override fun dismiss() {
super.dismiss()
if (!mIsDismissDark) {
controller.setBackGroundLevel(1.0f)
}
}
fun cancel() {
super.dismiss()
}
/**
* 设置取消pop是否暗屏
* @param isDismissDark true dismiss暗屏 false 亮屏
*/
fun setIsDismissDark(isDismissDark: Boolean = false) {
mIsDismissDark = isDismissDark
}
/**
* 展示在anchor左正下方
* @param anchor
*/
override fun showAsDropDown(anchor: View) {
if (Build.VERSION.SDK_INT < 24) {
super.showAsDropDown(anchor)
} else {
val location = IntArray(2)
anchor.getLocationOnScreen(location)
showAtLocation(anchor, Gravity.NO_GRAVITY, 0, location[1] + anchor.height)
}
}
/**
* 展示在anchor左正上方
* @param anchor
*/
fun showAsAbove(anchor: View) {
val location = IntArray(2)
anchor.getLocationOnScreen(location)
showAtLocation(anchor, Gravity.NO_GRAVITY, location[0], location[1] - height)
}
class Builder(context: Context) {
private val params: PopupController.PopupParams = PopupController.PopupParams(context)
private var listener: ViewInterface? = null
/**
* @param layoutResId 设置PopupWindow 布局ID
* @return Builder
*/
fun setView(layoutResId: Int): Builder {
params.mView = null
params.layoutResId = layoutResId
return this
}
/**
* @param view 设置PopupWindow布局
* @return Builder
*/
fun setView(view: View): Builder {
params.mView = view
params.layoutResId = 0
return this
}
/**
* 设置子View
*
* @param listener ViewInterface
* @return Builder
*/
fun setViewOnclickListener(listener: ViewInterface): Builder {
this.listener = listener
return this
}
/**
* 设置宽度和高度 如果不设置 默认是wrap_content
*
* @param width 宽
* @return Builder
*/
fun setWidthAndHeight(width: Int, height: Int): Builder {
params.mWidth = width
params.mHeight = height
return this
}
/**
* 设置背景灰色程度
*
* @param level 0.0f-1.0f
* @return Builder
*/
fun setBackGroundLevel(level: Float): Builder {
params.isShowBg = true
params.bg_level = level
return this
}
/**
* 是否可点击Outside消失
*
* @param touchable 是否可点击
* @return Builder
*/
fun setOutsideTouchable(touchable: Boolean): Builder {
params.isTouchable = touchable
return this
}
/**
*
* @param touchable 是否可点击
* @return Builder
*/
fun setIsFocusable(isFocusable: Boolean): Builder {
params.isFocusable = isFocusable
return this
}
/**
* 设置动画
*
* @return Builder
*/
fun setAnimationStyle(animationStyle: Int): Builder {
params.isShowAnim = true
params.animationStyle = animationStyle
return this
}
fun setInputMethondMode(inputMethodMode: Int): Builder {
params.inoutMethodMode = inputMethodMode
return this
}
fun create(): CommonPopupWindow {
val popupWindow = CommonPopupWindow(params.mContext)
params.apply(popupWindow.controller)
if (listener != null && params.layoutResId != 0) {
listener!!.getChildView(popupWindow.controller.mPopupView, params.layoutResId)
}
measureWidthAndHeight(popupWindow.controller.mPopupView!!)
return popupWindow
}
/**
* 测量View的宽高
*
* @param view View
*/
private fun measureWidthAndHeight(view: View) {
val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
val heightMeasureSpec =
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
view.measure(widthMeasureSpec, heightMeasureSpec)
}
}
}
布局:contacts_pop_filter
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardBackgroundColor="@color/contacts_filter_item_line"
app:cardCornerRadius="@dimen/PX_20">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_contacts_filter"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/item_contacts_filter_pop"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
Adapter类ContactsFilterAdapter:
class ContactsFilterAdapter(@LayoutRes layoutResId: Int, data: MutableList<ContactsFilterBean>?) :
BaseQuickAdapter<ContactsFilterBean, BaseViewHolder>(layoutResId, data) {
override fun convert(holder: BaseViewHolder, item: ContactsFilterBean) {
holder?.setText(R.id.tv_show, item.itemContent)
?.setVisible(R.id.iv_tick, item.isSelected)
if (holder.adapterPosition == 3) {
holder?.getView<View>(R.id.view_contacts_filter_item_line)?.visibility = View.INVISIBLE
}
}
}
item-item_contacts_filter_pop
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@color/white"
android:layout_height="@dimen/PX_100">
<TextView
android:id="@+id/tv_show"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:gravity="center_vertical"
android:layout_marginLeft="@dimen/PX_44"
android:textSize="14sp"
android:textColor="@color/black"
android:textStyle="bold"
android:text="1234"
/>
<ImageView
android:id="@+id/iv_tick"
android:src="@mipmap/ico_gou"
android:layout_width="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginRight="16dp"
android:visibility="invisible"
android:layout_height="wrap_content" />
<View
android:id="@+id/view_contacts_filter_item_line"
android:layout_width="match_parent"
android:layout_height="@dimen/PX_1"
android:background="@color/contacts_filter_item_line"
android:layout_marginLeft="@dimen/PX_44"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
javaBean的实现类:
class ContactsFilterBean(
var itemContent: String = "",
var isSelected: Boolean = false
)
调用入口:
// 顶部Contacts筛选
private val mContactsFilterPop: ContactsFilterPop by lazy {
ContactsFilterPop(activity!!, tv_title)
}
回调接口:
tv_title?.setOnClickListener {
mContactsFilterPop.show {
when (it) {
// A~Z
"A~Z" -> {
searchContext = ""
mType = 0
getCurrentActivityUserList()
}
}
}
}
R.style.popwin_anim_style_top
<style name="popwin_anim_style_top">
<item name="android:windowEnterAnimation">@anim/dialog_top_out</item>
<item name="android:windowExitAnimation">@anim/dialog_top_in</item>
</style>
dialog_top_in
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:interpolator="@android:anim/accelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.0"
android:fromYScale="1.0"
android:toYScale="0.0"
android:pivotX="100%"
android:pivotY="0%"
android:fillAfter="false"
android:duration="300"/>
</set>
dialog_top_out
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:interpolator="@android:anim/accelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.0"
android:fromYScale="0.0"
android:toYScale="1.0"
android:pivotX="100%"
android:pivotY="0%"
android:fillAfter="false"
android:duration="300"/>
</set>
网友评论