RecyclerView中获取item在屏幕中的绝对坐标

本文为原创作品,转载请标明出处:https://blog.csdn.net/wjj1996825/article/details/80433143

需求分析:在项目中有时候我们用RecyclerView的时候会有需要获取指定位置的itemview在屏幕中的绝对坐标,比如说做一个商品列表点击商品item后启动商品加入购物车动画,或者星座生肖项目中,用户选择出生日期后,自动匹配对应的生肖并启动一个生肖列表view的选中动画,都需要获取到RecyclerView中一个itemview在屏幕中的绝对坐标然后作为动画的起始位置进行启动,动画的结束位置就是你的购物车或者显示选中生肖的button或者view在屏幕中的绝对坐标,当然今天要讨论的主题是这个动画的起始位置,也就是获取RecyclerView指定位置的itemview在屏幕中的绝对坐标。
我总结的有两种方案:
第一种方案(针对点击item进行操作类型):是点击其中一个item的时候,通过自定义RecyclerView的item点击监听把你想要的坐标数组回传过来,这样是运用观察者模式,对点击的item进行观察,点击的时候调用回调方法,返回数组坐标,Activity中通过adapter.setOnItemClick()方法拿到回调的参数,进行动画启动操作,这样得到的坐标数组是正确的,就是无论你点击哪一个item,得到的都是这个itemview在屏幕中的绝对坐标,下面贴下关键代码 (注意我这里贴的是cotlin的代码,用java的同学复制的话需要改动才能使用):

// MyAdapter代码

class MyAdapter(private var con: Context) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var itemclickListener : OnItemClickListener? = null

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
holder.itemView.setOnClickListener {
                if (itemclickListener!=null){
                    val startLocation = IntArray(2)
                    holder.choose_zodiac_img.getLocationOnScreen(startLocation)//获取点击星座控件的位置
                    itemclickListener!!.onItemClick(position,startLocation)               
                }
            }
}

fun setOnItemClickListener(listener: OnItemClickListener) {
        this.itemclickListener = listener
    }

    interface OnItemClickListener{
        abstract fun onItemClick(position: Int, startLocation : IntArray)
    }

}

然后在Activity或者fragment中调用就可以

myAdapter?.setOnItemClickListener(object : MyAdapter.OnItemClickListener{
            override fun onItemClick(position: Int, startLocation: IntArray) {              
                    begAddShopAnim(view, startLocation)                         
            }
        })

第二种方案(针对非点击item进行操作类型)
先对这种需求进行一番解释,非点击item进行操作类型举个例子讲,就比如生肖或者星座项目中,当你不知道你的星座的时候,你可以点击生日选择出生年月日,当用户点击日期选择框的ok
按钮后,你需要做的事情就是根据用户的出生日期自动配对他或她的星座,如果产品经理要求页面展现一个星座列表的对应动画,你就需要获取这个星座对应的item在RecyclerView中的绝对坐标了,这时候就不能用上面的方案靠点击一个item的时候动态获取坐标了,我曾经做过一个尝试,在adapter种创建一个map对象和十二个星座的名字list,把十二个星座的名字作为key,然后在bandviewohlder的时候,把每一个holder的对应绑定的每一个星座数据的名字作为key,这个holder中的你想获取的view的坐标为value存起来:

var startLocation = IntArray(2)
            holder.itemView.getLocationOnScreen(startLocation)
            zodiacLocationMap!![zodiacLists[position].zodiacName] = startLocation

然后从fragment根据用户选择出生日期后算出的星座名字,然后从adapter中的map中根据获取星座名称,获取到我们存在map中的这个RecyclerView中对应的星座item的数组对象,然而思路很好,结果却令人失望,无论取哪个item获取到的数组坐标都是一样的,最后实在解决不了只好放弃这个方案了
正确的解决方案应该是这样的其实:
先讲思路:RecyclerView有findViewHolderForAdapterPosition(int postion)方法,可以获取指定位置的holder对象,然后你转型成你自己的holder对象,就可以获取你想获取的item中某个view 的坐标了,然后就可以进行正确位置的动画开始位置启动加载

var holder =  view!!.compatibility_recycle_view.findViewHolderForAdapterPosition(costionIndex) as YourRecyclerViewItmeHolder
            var startLocation = IntArray(2)
            holder.itemView.getLocationOnScreen(startLocation)
 begAddShopAnim(view, startLocation)  

其实就是换了一种思路绕了个弯儿回到第一种解决方案的思路解决了,哈哈,这里只讲思路,动画的代码就不贴了,这样的动画代码网上太多了,有问题或者更好思路的欢迎在博客留言一起讨论探讨哦~

猜你喜欢

转载自blog.csdn.net/wjj1996825/article/details/80433143