最近用recyclerview实现了一个长按并滑动显示当前item内容的demo,类似通讯录索引或者微信滑动查看表情,废话不多说,先看图再看代码


/**
*
* @ProjectName: HiltDemo
* @Package: com.example.hiltdemo.ui.main
* @ClassName: RecyclerviewHelper
* @Description: java类作用描述
* @Author: wanghaiyang
* @CreateDate: 2021/11/12 11:10
* @UpdateUser: 更新者
* @UpdateDate: 2021/11/12 11:10
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
class RecyclerviewHelperFragment : Fragment() {
companion object{
val instance = RecyclerviewHelperFragment()
}
private val binding: RecyclerviewHelperFragmentBinding by lazy { RecyclerviewHelperFragmentBinding.inflate(layoutInflater) }
private val recyAdapter: RecyclerviewHelperAdapter by lazy { RecyclerviewHelperAdapter() }
private val popLayoutManager by lazy{GridLayoutManager(requireContext(), 5)}
private val popWidow by lazy { TestPopupWindow(requireContext()) }
private val dats = mutableListOf<String>()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.recycler.adapter = recyAdapter
binding.recycler.layoutManager = popLayoutManager
for(i in 65..90){
dats.add(i.toChar().toString())
}
recyAdapter.refreshDatas(dats)
initListener()
}
private fun initListener() {
var startTime = 0L
var initFlag = true
var startX = 0f
var startY = 0f
var currPosition = -1
binding.recycler.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener{
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
return when(e.action){
MotionEvent.ACTION_DOWN->{
startTime = System.currentTimeMillis()
startX = e.x
startY = e.y
Log.e("swipe", "按下")
false
}
MotionEvent.ACTION_MOVE->{
if(startTime != 0L && System.currentTimeMillis() - startTime > 500){
Log.e("swipe", "滑动$startTime x=${e.x} y=${e.y}")
true
}else{
if(abs(e.x - startX) > 10 || abs(e.y - startY) > 10){
initFlag = false
startTime = 0
Log.e("swipe", "提前滑动了 x=${e.x} y=${e.y}")
}
false
}
}
MotionEvent.ACTION_UP->{
Log.e("swipe", "已经抬起")
initFlag = true
startTime = 0
false
}
else-> false
}
}
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {
when(e.action){
MotionEvent.ACTION_MOVE->{
val view = binding.recycler.findChildViewUnder(e.x, e.y)
view?.let {
val position = binding.recycler.getChildAdapterPosition(it)
val layoutPosition = binding.recycler.getChildLayoutPosition(it)
Log.e("position", "position=$position")
if(currPosition != position){
popWidow.updateData(dats[position])
popWidow.dismiss()
PopupWindowCompat.showAsDropDown(popWidow, view, -view.width - 10, - view.height / 2, Gravity.START)
currPosition = position
}
}
}
}
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
}
})
}
}
class TestPopupWindow constructor(val context: Context) : PopupWindow() {
private val binding by lazy { PopupTestBinding.inflate(LayoutInflater.from(context)) }
init {
height = ViewGroup.LayoutParams.WRAP_CONTENT
width = ViewGroup.LayoutParams.WRAP_CONTENT
isOutsideTouchable = true
isFocusable = true
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
contentView = binding.root
}
fun updateData(str: String){
binding.text.text = str
}
}
其中最重要的代码就是addOnItemTouchListener里面的代码,在onInterceptTouchEvent中进行判定是否为长按,我判定的时间为500,大家可以提取出来弄一个变量进行控制。
还有就是要做一些滑动距离的误判,例如点击很快但还是会走到move,这个时候就要增加一点儿小的滑动距离防止进入长按逻辑。
最后就是UP那里进行一个popup销毁就可以了,这个只是一个demo,可能会有一定问题,大家注意优化
本文展示了如何使用RecyclerView实现长按并滑动显示当前item内容的demo,类似于通讯录索引或微信表情展示。通过监听触摸事件,判断长按和滑动,结合PopupWindow展示内容。关键代码在于addOnItemTouchListener中的手势判断和PopupWindow的使用。

5439

被折叠的 条评论
为什么被折叠?



