Anroid之即时聊天的布局及适配器的编写.

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010316858/article/details/49488987

    即时聊天控件一般采用ListView,因为ListView可以支持不同类型的item,同时ListView本身自己维护了复用机制,可以避免大量的item重复创建导致OOM,但是由于ListView复用机制所以对于编写适配器就需要避免界面混乱,在第一次做布局的时候,一个播放语音动画就导致了布局了混乱显示,所以要编写一个好的apdater去深入了解复用机制去避免界面混乱.

    

    首先我们需要创建一个布局,布局包含了ListView,用来显示主要的对话界面:

    

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <!--输入界面-->
    <include
        android:id="@+id/ll_input"
        layout="@layout/chat_input" />

    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/ll_input"
        android:divider="@null" />


</RelativeLayout>

    

    然后我们需要编写一个Adapter去设置给ListView,那么我们就要考虑用什么apdater.我们都知道SimpleAdapter支持:CheckBox,RadioButton,TextView,ImageView.而我们的需求是要编写复杂的Item,所以我们应该选择BaseAdapter.

   在BaseAdapter中我们需要重写的方法:

    @Override
    public int getCount() {
        return messages.size();
    }

    @Override
    public Message getItem(int position) {
        return messages.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return convertView;
    }
    上面仅仅是简述这几个基本方法,这几个基本的方法仅仅是适用于一个不变的Item,上面是一个不变的Item,? 就是单一元素的,样式大小控件个数等.为什么.?因为系统在缓存池拿去复用的控件的时候就会去判断是否单一,默认为单一,那么拿到的控件与新的Item样式大小和控件个数都不同,那么给当前的控件设置一些属性就会NullPiontException等.这也是关键所在.

    所以我们还需要根据自己的需求重写2个方法,分别为:

扫描二维码关注公众号,回复: 3520154 查看本文章

    @Override
    public int getItemViewType(int position) {

        Message message = messages.get(position);
        MessageContent messageContent = message.getContent();
        if (messageContent instanceof TextMessage) {// 文本
            return message.getMessageDirection() == Message.MessageDirection.RECEIVE ? MESSAGE_TYPE_RECV_TXT : MESSAGE_TYPE_SENT_TXT;
        } else if (messageContent instanceof ImageMessage) { // 图片
            return message.getMessageDirection() == Message.MessageDirection.RECEIVE ? MESSAGE_TYPE_RECV_IMAGE : MESSAGE_TYPE_SENT_IMAGE;
        } else if (messageContent instanceof LocationMessage) {// 位置
            return message.getMessageDirection() == Message.MessageDirection.RECEIVE ? MESSAGE_TYPE_RECV_LOCATION : MESSAGE_TYPE_SENT_LOCATION;
        } else if (messageContent instanceof RichContentMessage) {// 图文消息
            return message.getMessageDirection() == Message.MessageDirection.RECEIVE ? MESSAGE_TYPE_RECV_RICH_CONTENT : MESSAGE_TYPE_SENT_RICH_CONTENT;
        } else if (messageContent instanceof VoiceMessage) { // 语音消息
            return message.getMessageDirection() == Message.MessageDirection.RECEIVE ? MESSAGE_TYPE_RECV_VOICE : MESSAGE_TYPE_SENT_VOICE;
        } else if (messageContent instanceof InformationNotificationMessage) {//灰色提示消息
            return MESSAGE_TYPE_RECV_NTF_MSG;
        }
        return -1;
    }

    @Override
    public int getViewTypeCount() {
        return 12;//暂时12种,后续根据业务会增加红包,广告等消息.
    }

    这样就避免复用的时候找到控件与对应的控件不匹配,而导致给控件设置一些属性而异常.

    做完这些后我们需要真正的就是去关键的方法getView中了.在getView中我们需要使用google推荐的写法,牺牲空间去换时间,为什么要去牺牲空间换时间.?虽然ListView提供了复用机制,但是每次复用的时候你还是需要去findViewByID,而id本身就是一个二叉树,一级级的遍历非常消耗时间,所以我们还需要增加用户体验,就需要创建一个Holder,避免重复查找.

    那么Holder的代码如下:

    

   private class ViewHoder {
        TextView name;//名字
        ImageView head;//头像
        TextView content;//文本内容
        ProgressBar progressBar;//进度
        ImageView state;//状态
        TextView time;//消息时间
        ImageView imageView;//图片消息
        TextView voiceTime;//语音时间
        ImageView voiceIcon;//语音图片
        LinearLayout voiceGroup;//包裹语音
        LinearLayout location;//包裹地图
    }

    这样getView的完整代码:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHoder viewHoder = null;
        final Message message = getItem(position);
        MessageContent messageContent = message.getContent();
        if (null == convertView) {
            viewHoder = new ViewHoder();
            convertView = createViewByMessage(messages.get(position));
            if (message.getContent() instanceof TextMessage) {
                try {
                    viewHoder.time = (TextView) convertView.findViewById(R.id.chat_tv_time);
                    viewHoder.name = (TextView) convertView.findViewById(R.id.chat_tv_name);
                    viewHoder.head = (ImageView) convertView.findViewById(R.id.chat_iv_head);
                    viewHoder.content = (TextView) convertView.findViewById(R.id.chat_tv_content);
                    viewHoder.progressBar = (ProgressBar) convertView.findViewById(R.id.chat_pb);
                    viewHoder.state = (ImageView) convertView.findViewById(R.id.chat_iv_state);
                } catch (Exception e) {
                }
            } else if (message.getContent() instanceof ImageMessage) {
                try {
                    viewHoder.time = (TextView) convertView.findViewById(R.id.chat_tv_time);
                    viewHoder.name = (TextView) convertView.findViewById(R.id.chat_tv_name);
                    viewHoder.head = (ImageView) convertView.findViewById(R.id.chat_iv_head);
                    viewHoder.imageView = (ImageView) convertView.findViewById(R.id.chat_iv_content);
                    viewHoder.progressBar = (ProgressBar) convertView.findViewById(R.id.chat_pb);
                    viewHoder.state = (ImageView) convertView.findViewById(R.id.chat_iv_state);
                } catch (Exception e) {
                }
            } else if (message.getContent() instanceof VoiceMessage) {
                try {
                    viewHoder.time = (TextView) convertView.findViewById(R.id.chat_tv_time);
                    viewHoder.name = (TextView) convertView.findViewById(R.id.chat_tv_name);
                    viewHoder.head = (ImageView) convertView.findViewById(R.id.chat_iv_head);
                    viewHoder.voiceTime = (TextView) convertView.findViewById(R.id.chat_tv_voice_time);
                    viewHoder.voiceIcon = (ImageView) convertView.findViewById(R.id.chat_iv_voice);
                    viewHoder.voiceGroup = (LinearLayout) convertView.findViewById(R.id.chat_ll_content);
                    viewHoder.progressBar = (ProgressBar) convertView.findViewById(R.id.chat_pb);
                    viewHoder.state = (ImageView) convertView.findViewById(R.id.chat_iv_state);
                } catch (Exception e) {
                }
            } else if (message.getContent() instanceof LocationMessage) {
                try {
                    viewHoder.time = (TextView) convertView.findViewById(R.id.chat_tv_time);
                    viewHoder.name = (TextView) convertView.findViewById(R.id.chat_tv_name);
                    viewHoder.head = (ImageView) convertView.findViewById(R.id.chat_iv_head);
                    viewHoder.content = (TextView) convertView.findViewById(R.id.chat_tv_content);// 位置
                    viewHoder.location = (LinearLayout) convertView.findViewById(R.id.chat_ll_content);
                    viewHoder.progressBar = (ProgressBar) convertView.findViewById(R.id.chat_pb);
                    viewHoder.state = (ImageView) convertView.findViewById(R.id.chat_iv_state);
                } catch (Exception e) {
                }
            }
            convertView.setTag(viewHoder);
        } else {
            viewHoder = (ViewHoder) convertView.getTag();
        }

        handleTime(message, viewHoder, position);

        //handler UserName and UserHead.

        if (messageContent instanceof TextMessage) { // 文本消息
            handleTextMessage(message, viewHoder, position);
        } else if (messageContent instanceof ImageMessage) {// 图片消息
            handleImageMessage(message, viewHoder, position);
        } else if (messageContent instanceof VoiceMessage) { // 语音消息
            handleVoiceMessage(message, viewHoder, position);
        } else if (messageContent instanceof RichContentMessage) { // 图文消息
            handleRichContentMessage(message, viewHoder, position);
        } else if (messageContent instanceof InformationNotificationMessage) { // 灰色提示
            handleNotifiMessage(message, viewHoder, position);
        } else if (messageContent instanceof LocationMessage) { // 位置消息
            handleLocationMessage(message, viewHoder, position);
        } else {
            //not supported.
        }

        return convertView;
    }



猜你喜欢

转载自blog.csdn.net/u010316858/article/details/49488987