最近仿照QQ聊天做了一个类似界面,先看下界面组成(画面不太美凑合凑合呗,,,,):
其中聊天背景可以是一个LinearLayout或者RelativeLayout里面存放的是ListView(将ListView的分割线设置成透明:android:divider="#0000"否则聊天界面会显示出分割线,,,想想都屌,,,)
于是,我要上主界面的xml布局文件了:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#c2c2c2"
android:orientation="vertical"
android:padding="16dp" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_horizontal_margin"
android:layout_weight="1"
android:background="@drawable/app_lvjian_rbtn_normal_background"
android:orientation="vertical"
android:padding="8dp" >
<ListView
android:id="@+id/lv_chat_dialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="#0000"
android:dividerHeight="8dp"
android:scrollbars="none" >
</ListView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="32dp"
android:layout_marginTop="8dp"
android:orientation="horizontal" >
<EditText
android:id="@+id/et_chat_message"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="14sp"
android:background="@drawable/app_lvjian_rbtn_normal_background"
android:gravity="center|left"
android:padding="8dp" />
<Button
android:id="@+id/btn_chat_message_send"
style="?android:attr/buttonStyleSmall"
android:layout_width="64dp"
android:layout_marginLeft="8dp"
android:layout_height="match_parent"
android:layout_gravity="center|right"
android:layout_marginRight="4dp"
android:background="@drawable/app_lvjian_chat_sends" />
</LinearLayout>
</LinearLayout>
完了就会出现下图:
于是该为ListView设置条目了,就是咱们聊天的消息了!
由图可以看出要为ListView设置两个item文件,(头像和气泡的位置,方向,都不一样)其中气泡一定是.9png的否则会失真的。
左边的item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:id="@+id/ivicon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="top"
android:src="@drawable/app_lvjian_message_background" />
<TextView
android:id="@+id/tvname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:padding="8dp"
android:background="@drawable/app_lvjian_other_chat_background"
android:text="权志龙好帅!!!" />
</LinearLayout>
右边的item
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_chat_me_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:layout_toLeftOf="@+id/iv_chat_imagr_right"
android:background="@drawable/app_lvjian_chat_right"
android:padding="8dp"
android:text="把那些贩毒的关到小黑屋,枪毙五十次,快去" />
<ImageView
android:id="@+id/iv_chat_imagr_right"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_alignParentRight="true"
android:layout_gravity="top"
android:src="@drawable/app_lvjian_message_background" />
</RelativeLayout>
接下来还要为LiseView设置Adapter,发送消息时候有姓名,聊天内容等,我把这些元素封装了一个实体类先贴出来(Adapter会用到的):
package com.example.mychattext;
public class PersonChat {
/**
* id
*/
private int id;
/**
* 姓名
*/
private String name;
/**
* 聊天内容
*/
private String chatMessage;
/**
*
* @return 是否为本人发送
*/
private boolean isMeSend;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getChatMessage() {
return chatMessage;
}
public void setChatMessage(String chatMessage) {
this.chatMessage = chatMessage;
}
public boolean isMeSend() {
return isMeSend;
}
public void setMeSend(boolean isMeSend) {
this.isMeSend = isMeSend;
}
public PersonChat(int id, String name, String chatMessage, boolean isMeSend) {
super();
this.id = id;
this.name = name;
this.chatMessage = chatMessage;
this.isMeSend = isMeSend;
}
public PersonChat() {
super();
}
}
自定义的Adapter加载布局文件的时候需要判断是哪方发送的消息来决定用哪个item布局文件,看Adapter:
package com.example.mychattext;
import java.util.List;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class ChatAdapter extends BaseAdapter {
private Context context;
private List<PersonChat> lists;
public ChatAdapter(Context context, List<PersonChat> lists) {
super();
this.context = context;
this.lists = lists;
}
/**
* 是否是自己发送的消息
*
* @author cyf
*
*/
public static interface IMsgViewType {
int IMVT_COM_MSG = 0;// 收到对方的消息
int IMVT_TO_MSG = 1;// 自己发送出去的消息
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return lists.size();
}
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return lists.get(arg0);
}
@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
/**
* 得到Item的类型,是对方发过来的消息,还是自己发送出去的
*/
public int getItemViewType(int position) {
PersonChat entity = lists.get(position);
if (entity.isMeSend()) {// 收到的消息
return IMsgViewType.IMVT_COM_MSG;
} else {// 自己发送的消息
return IMsgViewType.IMVT_TO_MSG;
}
}
@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
// TODO Auto-generated method stub
HolderView holderView = null;
PersonChat entity = lists.get(arg0);
boolean isMeSend = entity.isMeSend();
if (holderView == null) {
holderView = new HolderView();
if (isMeSend) {
arg1 = View.inflate(context, R.layout.chat_dialog_right_item,
null);
holderView.tv_chat_me_message = (TextView) arg1
.findViewById(R.id.tv_chat_me_message);
holderView.tv_chat_me_message.setText(entity.getChatMessage());
} else {
arg1 = View.inflate(context, R.layout.chat_dialog_left_item,
null);
}
arg1.setTag(holderView);
} else {
holderView = (HolderView) arg1.getTag();
}
return arg1;
}
class HolderView {
TextView tv_chat_me_message;
}
@Override
public boolean isEnabled(int position) {
return false;
}
}
区分消息发送方重点在IMsgViewType、getItemViewType、getView方法中,注释很详细,相信大家可以理解
最后是注释详细的MAinActivity:
package com.example.mychattext;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity {
private ChatAdapter chatAdapter;
/**
* 声明ListView
*/
private ListView lv_chat_dialog;
/**
* 集合
*/
private List<PersonChat> personChats = new ArrayList<PersonChat>();
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
int what = msg.what;
switch (what) {
case 1:
/**
* ListView条目控制在最后一行
*/
lv_chat_dialog.setSelection(personChats.size());
break;
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
/**
* 虚拟4条发送方的消息
*/
for (int i = 0; i <= 3; i++) {
PersonChat personChat = new PersonChat();
personChat.setMeSend(false);
personChats.add(personChat);
}
lv_chat_dialog = (ListView) findViewById(R.id.lv_chat_dialog);
Button btn_chat_message_send = (Button) findViewById(R.id.btn_chat_message_send);
final EditText et_chat_message = (EditText) findViewById(R.id.et_chat_message);
/**
*setAdapter
*/
chatAdapter = new ChatAdapter(this, personChats);
lv_chat_dialog.setAdapter(chatAdapter);
/**
* 发送按钮的点击事件
*/
btn_chat_message_send.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if (TextUtils.isEmpty(et_chat_message.getText().toString())) {
Toast.makeText(MainActivity.this, "发送内容不能为空", 0).show();
return;
}
PersonChat personChat = new PersonChat();
//代表自己发送
personChat.setMeSend(true);
//得到发送内容
personChat.setChatMessage(et_chat_message.getText().toString());
//加入集合
personChats.add(personChat);
//清空输入框
et_chat_message.setText("");
//刷新ListView
chatAdapter.notifyDataSetChanged();
handler.sendEmptyMessage(1);
}
});
}
}
源码连接:http://pan.baidu.com/s/1dF9Rcrv