Android聊天列表Demo(QQ,微信,等通讯工具的聊天列表)

                                       Android聊天列表Demo(QQ,微信,等通讯工具的聊天列表)


                              

                                  左边item     

                                  右边item 

             在示意图中,整体布局很清晰。

                         头部很底部都是 普通的控件形成的布局,关键是中间的这一块 消息列表的布局以及数据的装载。

                           

                         中间: 中间用的是一个ListView 重点是在ListView的适配器上 怎么样让适配器加载一个小的项item

                             也就是 红色跟蓝色虚线围成的那一块。

                            (省略了 适配器优化的详解和ViewHolder的作用了 重点介绍不同类型的item 如何工作)

                            

                           代码:

                           

/**
 * 
 */
package com.example.listview;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * @author Administrator
 *
 */
public class MsgViewAdapter extends BaseAdapter
{

    private List<MessageEntity> mEntities;
    private LayoutInflater lInflater;

    public MsgViewAdapter(Context mContext, List<MessageEntity> mEntities)
    {
	this.mEntities = mEntities;
	lInflater = LayoutInflater.from(mContext);
    }

    @Override
    public int getCount()
    {
	// TODO Auto-generated method stub
	return mEntities.size();
    }

    @Override
    public Object getItem(int position)
    {
	// TODO Auto-generated method stub
	return mEntities.get(position);
    }

    @Override
    public int getItemViewType(int position)
    {
	MessageEntity entity = mEntities.get(position);
	if (entity.getMsgType())
	{
	    return 0;
	} else
	{
	    return 1;
	}
    }

    @Override
    public int getViewTypeCount()
    {
	// TODO Auto-generated method stub
	return 2;
    }

    @Override
    public long getItemId(int position)
    {
	// TODO Auto-generated method stub
	return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
	MessageEntity mEntity = mEntities.get(position);
	boolean isFrom = mEntity.getMsgType();
	ViewHolder holder = null;
	if (convertView == null)
	{
	    if (isFrom)
	    {
		convertView = lInflater.inflate(R.layout.item_left, null);
	    } else
	    {
		convertView = lInflater.inflate(R.layout.item_right, null);
	    }

	    holder = new ViewHolder();
	    holder.content = (TextView) convertView.findViewById(R.id.tv_chatcontent);
	    holder.datextView = (TextView) convertView.findViewById(R.id.tv_sendtime);
	    holder.name = (TextView) convertView.findViewById(R.id.tv_username);
	    holder.touxiang = (ImageView) convertView.findViewById(R.id.iv_userhead);
	    convertView.setTag(holder);
	} else
	{
	    holder = (ViewHolder) convertView.getTag();
	}
	holder.content.setText(mEntity.getMessage());
	holder.datextView.setText(mEntity.getDate());
	holder.name.setText(mEntity.getName());
	return convertView;

    }

    public class ViewHolder
    {
	TextView datextView;
	ImageView touxiang;
	TextView name;
	TextView content;
    }

}

                        

              其中, private List<MessageEntity> mEntities;  为一个消息的实体库。 

             这个类简单的介绍:

                    属性有:

                                

        private String name;//消息来自
	private String date;//消息日期
	private String message;//消息内容
	private boolean isComMeg = true;// 是否为收到的消息

                因为这里没有联网 所以把头像的属性去掉了。在有与服务器连接时 可以加个头像imageview 


                在继承BaseAdapter的同时,必须实现的及格方法:

 

                       

  @Override
    public int getCount()
    {
	// TODO Auto-generated method stub
	return mEntities.size();
    }

    @Override
    public Object getItem(int position)
    {
	// TODO Auto-generated method stub
	return mEntities.get(position);
    }
 @Override
    public long getItemId(int position)
    {
	// TODO Auto-generated method stub
	return position;
    }
  @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
    }

          getCount() 返回 列表中 item的个数  

                  getItem() 返回这个item (我把他理解为传回来的数据)

                 getView  返回这个项的视图

                 getItemId()返回item的索引


              以上是基本的 必须要重写的方法。 但是做一个聊天列表 远远满足不了。 所以还需要添加以下的方法:


               getViewTypeCount()   从方法名可以知道 是 获取item视图的类型的个数。 比如说聊天列表

                                                     有左右之分 那就是  返回2 当然可以有更多种类型的布局


                 public int getItemViewType(int position)  从方法名也可以显而易见 是获取类型的标志 获取的是 发送还是接受的类型

                                                                                         发送为1 接受为0


                 最后在public View getView(int position, View convertView, ViewGroup parent) 这个方法中 去判断视图的类型

             比如判断 获取的视图标志是0 还是1  进行 初始化不同的布局

             代码示例:

              

@Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
	MessageEntity mEntity = mEntities.get(position);
	boolean isFrom = mEntity.getMsgType();
	ViewHolder holder = null;
	if (convertView == null)
	{
	    if (isFrom)
	    {
		convertView = lInflater.inflate(R.layout.item_left, null);
	    } else
	    {
		convertView = lInflater.inflate(R.layout.item_right, null);
	    }

	    holder = new ViewHolder();
	    holder.content = (TextView) convertView.findViewById(R.id.tv_chatcontent);
	    holder.datextView = (TextView) convertView.findViewById(R.id.tv_sendtime);
	    holder.name = (TextView) convertView.findViewById(R.id.tv_username);
	    holder.touxiang = (ImageView) convertView.findViewById(R.id.iv_userhead);
	    convertView.setTag(holder);
	} else
	{
	    holder = (ViewHolder) convertView.getTag();
	}
	holder.content.setText(mEntity.getMessage());
	holder.datextView.setText(mEntity.getDate());
	holder.name.setText(mEntity.getName());
	return convertView;

    }

    public class ViewHolder
    {
	TextView datextView;
	ImageView touxiang;
	TextView name;
	TextView content;
    }

                     可以看到 在:

                

              if (isFrom)
	    {
		convertView = lInflater.inflate(R.layout.item_left, null);
	    } else
	    {
		convertView = lInflater.inflate(R.layout.item_right, null);
	    }
                   上 判断了是获取哪种视图。 因为在

                     

 @Override
    public int getItemViewType(int position)
    {
	MessageEntity entity = mEntities.get(position);
	if (entity.getMsgType())
	{
	    return 0;
	} else
	{
	    return 1;
	}
    }
                          

                            用 MessageEntity  类中有一个判断       private boolean isComMeg = true;// 是否为收到的消息 的属性

                            获取到的实体消息对象中 如果为true 就为0 false 就为1


                            在getView中也就方便的对 视图类型进行判断。

                            

                              这样一来,适配器的代码就完毕了,兴趣的网友可以 动手标记日记看看执行顺序。

                     

                    主Activity:

                           

                                 在主界面中,当发送按钮的事件响应时,我们可以让列表出现我们的 消息实体  

                

/**
     * 发送消息
     */
    private void sendMsg()
    {
	String content = input.getText().toString();
	if (content.length() > 0)
	{
	    MessageEntity messageEntity = new MessageEntity();
	    messageEntity.setName("奥巴马");
	    messageEntity.setMessage(content);
	    messageEntity.setMsgType(false);
	    messageEntity.setDate(gainTime());
	    messages.add(messageEntity);
	    // 增加了一个之后 通知适配器改变数据
	    adapter.notifyDataSetChanged();

	    input.setText("");
	    cathlist.setSelection(cathlist.getCount() - 1);
	}

    }

    /**
     * @return
     */
    private String gainTime()
    {
	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	return format.format(new Date());
    }
              

                  在编辑框有内容时。 设置  发送人的ID 获取当前的时间 gainTime  然后设置消息类的时间属性  设置类型 为false 为发送信息


                 在 消息类 集合添加玩这个   新的消息实体 的时候  通知适配器 数据的更改

                adapter.notifyDataSetChanged();

                  这样列表会更新添加的数据

                  cathlist.setSelection(cathlist.getCount() - 1);

                  这个方法的意思是  发送了信息 最后 让ListView 选择显示最后一个item


             这样的话  整个聊天的模块就做好了。



            代码:

                 聊天界面的代码

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值