聊天界面,首先是布局,先用tools下的制作9patch图片的工具制作两张对话框图片,分别用作接收消息的图片背景和发送消息的图片背景。activity_main.xml的布局文件如下:
<ListView
android:id="@+id/message_listview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:divider="#0000" >
</ListView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<EditText
android:id="@+id/input_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Type somthing here"
android:maxLines="2" />
<Button
android:id="@+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送"
android:background="#70CFEB"/>
</LinearLayout>
显而易见,利用ListView来显示发送的和接收的消息,既然有了ListView,所以还应该有一个ListView的Item布局,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="vertical"
android:padding="10dp" >
<LinearLayout
android:id="@+id/left_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:background="@drawable/im_bg_chat_content_other_side_pressed" >
<TextView
android:id="@+id/left_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:textColor="#fff" />
</LinearLayout>
<LinearLayout
android:id="@+id/right_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:background="@drawable/chat_content_self_bg" >
<TextView
android:id="@+id/right_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp" />
</LinearLayout>
</LinearLayout>
其中@drawable引用的图片就是我们制作的两张对话框9patch图片。
既然是聊天界面,又是用LIstView来显示,所以得新建一个Message的实体类,定义两个属性,content和type,并且进行封装.
public class Message {
public static final int TYPE_SEND = 1; //发送方的唯一标识
public static final int TYPE_RECEIVED = 0; //接收者的唯一标识
private String Content; //消息的内容
private int type; //消息的类别(是发送还是接收)
public Message(String content, int type) {
super();
Content = content;
this.type = type;
}
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
接下来就是写数据源适配器了,初学时ListView一般都是和ArrayAdapter和SimpleAdapter,我一直用的都是更加灵活的自定义Adapter。所以,新建一个适配器继承BaseAdapter.
public class MessageAdapter extends BaseAdapter {
private List<Message> list; //Message类的集合
private LayoutInflater inflater;
public MessageAdapter(Context context) {
list = new ArrayList<Message>();
inflater = LayoutInflater.from(context);
}
public void addItem(Message msg) {
list.add(msg);
this.notifyDataSetChanged();
}
public void removeItem(int position){
list.remove(position);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return list.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) {
// TODO Auto-generated method stub
ViewHolder holder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.message_item, null);
holder = new ViewHolder();
holder.leftLayout = (LinearLayout) convertView
.findViewById(R.id.left_layout);
holder.rightLayout = (LinearLayout) convertView
.findViewById(R.id.right_layout);
holder.leftMsg = (TextView) convertView.findViewById(R.id.left_msg);
holder.rightMsg = (TextView) convertView
.findViewById(R.id.right_msg);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// 如果是收到的消息,则隐藏掉右边的布局
if (list.get(position).getType() == Message.TYPE_RECEIVED) {
holder.leftLayout.setVisibility(View.VISIBLE);
holder.rightLayout.setVisibility(View.GONE);
holder.leftMsg.setText(list.get(position).getContent());
} else if (list.get(position).getType() == Message.TYPE_SEND) { //如果是发送的信息
holder.leftLayout.setVisibility(View.GONE);
holder.rightLayout.setVisibility(View.VISIBLE);
holder.rightMsg.setText(list.get(position).getContent());
}
return convertView;
}
class ViewHolder {
LinearLayout leftLayout;
LinearLayout rightLayout;
TextView leftMsg;
TextView rightMsg;
}
}
最后,开始在Activity中编写。
/**
* 聊天界面
* @author zcsolf
*
*/
public class MainActivity extends Activity implements OnClickListener {
private Button Send;
private ListView ListMessage;
private EditText Input;
private MessageAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
findView();
InitMessage();
ListMessage.setAdapter(mAdapter);
ListMessage.setSelector(new ColorDrawable(Color.TRANSPARENT));
//注册上下文菜单
this.registerForContextMenu(ListMessage);
}
/**
* 初始化消息,即模拟消息
*/
private void InitMessage() {
// TODO Auto-generated method stub
Message msg;
msg = new Message("Hello SB.", Message.TYPE_RECEIVED);
mAdapter.addItem(msg);
msg = new Message("你哪位?", Message.TYPE_SEND);
mAdapter.addItem(msg);
msg = new Message("我是XXXXXXX", Message.TYPE_RECEIVED);
mAdapter.addItem(msg);
}
/**
* 初始化组件
*/
private void findView() {
// TODO Auto-generated method stub
Send = (Button) findViewById(R.id.send);
ListMessage = (ListView) findViewById(R.id.message_listview);
Input = (EditText) findViewById(R.id.input_text);
mAdapter = new MessageAdapter(MainActivity.this);
Send.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.send:
String content = Input.getText().toString();
if (!"".equals(content)) {
Message msg = new Message(content, Message.TYPE_SEND);
mAdapter.addItem(msg);
mAdapter.notifyDataSetChanged(); // 当有新消息时,刷新ListView中的显示
ListMessage.setSelection(mAdapter.getCount()); // 将ListView定位到最后一行
Input.setText(""); // 清空输入框中的内容
}
break;
default:
break;
}
}
/**
* 生成上下文菜单
*/
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("短信管理");
menu.add(0, 1, Menu.NONE, "复制");
menu.add(0, 2, Menu.NONE, "删除");
}
/**
* 响应上下文菜单
*/
@Override
public boolean onContextItemSelected(MenuItem item) {
//ContextMenuInfo的适配器
AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo();
Log.v("SampleContextMenuActivity", "context item seleted ID="+ menuInfo.id);
switch (item.getItemId()) {
case 1:
Toast.makeText(MainActivity.this, "复制", Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(MainActivity.this, "删除", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
return true;
}
}