聊天界面 使用listview和recyclerview

在构建类似微信的聊天界面时,面临下拉加载更多和定位问题。ListView在刷新时可能导致界面闪烁,而RecyclerView通过setStackFromEnd(true)和setReverseLayout(true)可以解决这一问题。然而,RecyclerView缺少像ListView的alwaysScroll属性,使得滚动到最新内容变得复杂,需要监听键盘弹起事件并自定义外层Layout来实现。选择ListView还是RecyclerView,取决于如何更好地满足特定需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前做一个类似微信聊天的界面,要实现这种效果在自定义adapter的时候需要复写两个方法:

public int getItemViewType(int position)
public int getViewTypeCount()

然后在getView的时候根据type来指定converView。

当然这个是最基本的知识,今天要说的是另外的坑。

我们知道,listview渲染view是从上到下的

header
item0
item1
item2
。。。
footer

聊天界面是有下拉加载更多的,即到顶下拉会加载之前的记录,然后我们调用notifyDataSetChanged(),listview会刷新视图,这时我们会到新加载数据的顶部,通过查看源码,我发现listview在onChange的时候,如果当前位置不在顶部,它会记录下位置,更新的时候再复原,而在顶部的时候,就相当于重新开始渲染(其实也相当于是记住位置了,因为就是在顶部。)

但是聊天界面一般都是加载完新数据之后还是停留在之前的位置,那我们会调用listview.setSelectSection(int index),回到之前浏览的位置,这样界面会闪一下。为了解决这个问题,我使用recyclerView,recyclerview有两个方法可以反转列表,setStackFromEnd(true),setReverseLayout(true),设置完这两个属性时候,recyclerview展示视图变成了这样

footer
。。。
item2
item1
item0
header
这样我们就好说了,下拉加载更新之后视图还是停留在之前的位置,就像listview上拉加载一样,并不会像之前那样滑动到最顶部了。这样这个完善就算是搞定了。

但是使用recyclrview又带来了另一个问题。聊天记录的页面还有另一个需求,当用户点击输入的时候,界面需要滚到最底部,即最新的聊天内容处,这个需求使用listview实现很方便,listview有一个属性,alwaysScroll,在xml里定义listview的时候alwaysScroll设置为true,就能实现这个需求。但是recyclerview没有这个属性啊,那我们就只能监听键盘弹起事件了,但是android好像没有这种监听事件,所以我自定义了外层Layout,在manifest里定义activity的时候,我们设置聊天的activity的windowSoftInputMode为“adjustResize”,这样键盘弹起的时候布局会重绘,调整高度。

所以我自定义了外层Layout:

public class KeyBoardChangeLinearLayout extends LinearLayout {

    private OnKeyBoardChangeListener mListner;
    public KeyBoardChangeLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public KeyBoardChangeLinearLayout(Context context) {
        super(context);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (mListner != null) {
            if (oldh > h) {
                mListner.onShow();
            } else {
                mListner.onHidden();
            }
        }
    }

    public void setOnKeyBoardChangeListener(OnKeyBoardChangeListener listener) {
        mListner = listener;
    }

    public interface OnKeyBoardChangeListener {
        void onShow();
        void onHidden();
    }
}

复写onSizeChanged方法,当键盘弹起,触发layout重绘,oldh>h,当键盘收起,也触发layout重绘,oldh<h,这样我就能监听到键盘弹起还是收回了,当键盘弹起的时候,我让recyclerview滑动到第0项,也就是最底部就可以了,recyclerview.scrollToPosition(0),这个需求也算是实现了。


recyclerview之前没有使用过,经常使用的是listview,一个需求使用哪个空间合适并没有什么可以争执的,只要能更好的实现效果就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值