android小技巧实现聊天窗口
第一步添加聊天界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:background="#d8e0e8"
android:layout_height="match_parent">
<ListView
android:id="@+id/msg_list_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
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="编写"
android:maxLines="2"/>
<Button
android:id="@+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送"/>
</LinearLayout>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:background="#d8e0e8"
android:layout_height="match_parent">
<ListView
android:id="@+id/msg_list_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
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="编写"
android:maxLines="2"/>
<Button
android:id="@+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送"/>
</LinearLayout>
</LinearLayout>
第二步添加消息实体
public class Msg {
public static final int TYPE_RECEIVED=0;
public static final int TYPE_SEND=1;
private String content;
private int type;
public Msg(String content,int type){
this.content=content;
this.type=type;
}
public String getContent(){
return content;
}
public int getType(){
return type;
}
}
public static final int TYPE_RECEIVED=0;
public static final int TYPE_SEND=1;
private String content;
private int type;
public Msg(String content,int type){
this.content=content;
this.type=type;
}
public String getContent(){
return content;
}
public int getType(){
return type;
}
}
第三步添加ListView的子项布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
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/two9">
<TextView
android:id="@+id/left_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="20dp"
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/two9"
>
<TextView
android:id="@+id/right_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="30dp"/>
</LinearLayout>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
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/two9">
<TextView
android:id="@+id/left_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="20dp"
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/two9"
>
<TextView
android:id="@+id/right_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="30dp"/>
</LinearLayout>
</LinearLayout>
第四步添加适配器
public class MsgAdapter extends ArrayAdapter<Msg> {
private int resourceId;
public MsgAdapter(Context context,int textViewResourceId,List<Msg> objects){
super(context,textViewResourceId,objects);
resourceId=textViewResourceId;
}
@Override
public View getView(int position,View convertView,ViewGroup parent){
if(convertView==null)
{
convertView= LayoutInflater.from(getContext()).inflate(resourceId, null);
}
Msg msg=getItem(position);//获取当前项的Msg实例
if (msg.getType()==Msg.TYPE_RECEIVED)
{
ViewHolderExt.get(convertView,R.id.left_layout).setVisibility(View.VISIBLE);
ViewHolderExt.get(convertView,R.id.right_layout).setVisibility(View.GONE);
((TextView)ViewHolderExt.get(convertView,R.id.left_msg)).setText(msg.getContent());
}
else if(msg.getType()==Msg.TYPE_SEND)
{
ViewHolderExt.get(convertView,R.id.right_layout).setVisibility(View.VISIBLE);
ViewHolderExt.get(convertView,R.id.left_layout).setVisibility(View.GONE);
((TextView)ViewHolderExt.get(convertView,R.id.right_msg)).setText(msg.getContent());
}
return convertView;
}
}
private int resourceId;
public MsgAdapter(Context context,int textViewResourceId,List<Msg> objects){
super(context,textViewResourceId,objects);
resourceId=textViewResourceId;
}
@Override
public View getView(int position,View convertView,ViewGroup parent){
if(convertView==null)
{
convertView= LayoutInflater.from(getContext()).inflate(resourceId, null);
}
Msg msg=getItem(position);//获取当前项的Msg实例
if (msg.getType()==Msg.TYPE_RECEIVED)
{
ViewHolderExt.get(convertView,R.id.left_layout).setVisibility(View.VISIBLE);
ViewHolderExt.get(convertView,R.id.right_layout).setVisibility(View.GONE);
((TextView)ViewHolderExt.get(convertView,R.id.left_msg)).setText(msg.getContent());
}
else if(msg.getType()==Msg.TYPE_SEND)
{
ViewHolderExt.get(convertView,R.id.right_layout).setVisibility(View.VISIBLE);
ViewHolderExt.get(convertView,R.id.left_layout).setVisibility(View.GONE);
((TextView)ViewHolderExt.get(convertView,R.id.right_msg)).setText(msg.getContent());
}
return convertView;
}
}
其中ViewHolderExt是一个通用类,用于缓存每个View下对应的子view,这样在返回时不用再继续找每个子View,提高效率。
//高度抽象的ViewHolder
public class ViewHolderExt{
@SuppressWarnings("unchecked")
public static <T extends View> T get(View view,int id){
SparseArray<View> viewHolder=(SparseArray<View>)view.getTag();
if(viewHolder==null)
{
viewHolder=new SparseArray<View>();
view.setTag(viewHolder);
}
View childView=viewHolder.get(id);
if(childView==null){
childView=view.findViewById(id);
viewHolder.put(id,childView);
}
return (T)childView;
}
}
public class ViewHolderExt{
@SuppressWarnings("unchecked")
public static <T extends View> T get(View view,int id){
SparseArray<View> viewHolder=(SparseArray<View>)view.getTag();
if(viewHolder==null)
{
viewHolder=new SparseArray<View>();
view.setTag(viewHolder);
}
View childView=viewHolder.get(id);
if(childView==null){
childView=view.findViewById(id);
viewHolder.put(id,childView);
}
return (T)childView;
}
}
第五步添加界面代码和公共缓存器
public class MsgActivity extends Activity {
private ListView msgListView;
private EditText inputText;
private Button send;
private MsgAdapter adapter;
private List<Msg> msgList=new ArrayList<Msg>();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.ui_talk);
initMsgs();
adapter=new MsgAdapter(MsgActivity.this,R.layout.msg_item,msgList);
inputText=(EditText)findViewById(R.id.input_text);
send=(Button)findViewById(R.id.send);
msgListView=(ListView)findViewById(R.id.msg_list_view);
msgListView.setAdapter(adapter);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String content=inputText.getText().toString();
if (!"".equals(content)){
Msg msg=new Msg(content, Msg.TYPE_SEND);
msgList.add(msg);
adapter.notifyDataSetChanged();//有新消息刷新
msgListView.setSelection(msgList.size());//选择最后一条
inputText.setText("");
}
}
});
}
private void initMsgs(){
Msg msg1=new Msg("hello guy.",Msg.TYPE_RECEIVED);
msgList.add(msg1);
Msg msg2=new Msg("你好。你是谁?",Msg.TYPE_SEND);
msgList.add(msg2);
Msg msg3=new Msg("this is Tom. Nice talking to you.",Msg.TYPE_RECEIVED);
msgList.add(msg3);
}
}
private ListView msgListView;
private EditText inputText;
private Button send;
private MsgAdapter adapter;
private List<Msg> msgList=new ArrayList<Msg>();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.ui_talk);
initMsgs();
adapter=new MsgAdapter(MsgActivity.this,R.layout.msg_item,msgList);
inputText=(EditText)findViewById(R.id.input_text);
send=(Button)findViewById(R.id.send);
msgListView=(ListView)findViewById(R.id.msg_list_view);
msgListView.setAdapter(adapter);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String content=inputText.getText().toString();
if (!"".equals(content)){
Msg msg=new Msg(content, Msg.TYPE_SEND);
msgList.add(msg);
adapter.notifyDataSetChanged();//有新消息刷新
msgListView.setSelection(msgList.size());//选择最后一条
inputText.setText("");
}
}
});
}
private void initMsgs(){
Msg msg1=new Msg("hello guy.",Msg.TYPE_RECEIVED);
msgList.add(msg1);
Msg msg2=new Msg("你好。你是谁?",Msg.TYPE_SEND);
msgList.add(msg2);
Msg msg3=new Msg("this is Tom. Nice talking to you.",Msg.TYPE_RECEIVED);
msgList.add(msg3);
}
}