编写聊天界面的最佳实践

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编写聊天界面的最佳实践相关的知识,希望对你有一定的参考价值。

1、编写主界面,activity_main.xml:

  • 使用总线性布局,在总线性布局里包含了一个ListView控件和另一个LinearLayout。
  • 在垂直方向上,LinearLayout按照wrap_content来计算,剩下的空间是ListView控件的,( android:layout_weight="1"
  • LinearLayout里边包含一个EditText控件和一个按钮控件。按钮控件按照wrap_content来计算,剩下的空间是EditText控件的(android:layout_weight="1"
<LinearLayout 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"
    android:orientation="vertical"
 >
     <!-- ListView 占下剩余的空间 -->
    <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="Type something here"
           android:maxLines="2"/>
       <Button 
           android:id="@+id/send"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Send"/>
   </LinearLayout>

</LinearLayout>

2、编写消息的实体类

package com.example.uibestpractice;

public class Msg {
    public static final int TYPE_RECEIVED=0;  //接受一条消息
    public static final int TYPE_SENT=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;
    }
    
    
}

3、编写ListView子项的布局:msg_item.xml

LinearLayout里边又包含了两个线性布局分别为LinearLayout1和LinearLayout2.一个为左布局,一个为右。在后面中,可以控制控件的可见性,来区别消息是发送还是接收。

<?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/message_left">
        <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/message_right">
        <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>

4、创建ListView的适配器

package com.example.uibestpractice;

import java.util.List;

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

public class MsgAdapter extends ArrayAdapter<Msg>{
    
    private int resourceID;
    public MsgAdapter(Context context, int textViewResourceId, List<Msg> objects) {
        super(context, textViewResourceId, objects);
        // TODO Auto-generated constructor stub
        resourceID=textViewResourceId;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        Msg msg=getItem(position);
        View view;
        ViewHolder viewHolder;
        if(convertView==null){
            view=LayoutInflater.from(getContext()).inflate(resourceID, null);
            viewHolder=new ViewHolder();
            viewHolder.leftLayout=(LinearLayout) view.findViewById(R.id.left_layout);
            viewHolder.rightLayout=(LinearLayout) view.findViewById(R.id.right_layout);
            viewHolder.leftMsg=(TextView) view.findViewById(R.id.left_msg);
            viewHolder.rightMsg=(TextView) view.findViewById(R.id.right_msg);
            view.setTag(viewHolder);
        }else{
            view=convertView;
            viewHolder=(ViewHolder) view.getTag();
        }
        
        if(msg.getType()==Msg.TYPE_RECEIVED){//如果是收到的消息,则设置显示左边的消息布局,将右边的布局隐藏
            viewHolder.leftLayout.setVisibility(View.VISIBLE);
            viewHolder.rightLayout.setVisibility(View.GONE);
            viewHolder.leftMsg.setText(msg.getContent());
        }else if(msg.getType()==Msg.TYPE_SENT){
            viewHolder.leftLayout.setVisibility(View.GONE);
            viewHolder.rightLayout.setVisibility(View.VISIBLE);
            viewHolder.rightMsg.setText(msg.getContent());
        }
        return view;
    }
    
    class ViewHolder{
        LinearLayout leftLayout;
        LinearLayout rightLayout;
        TextView leftMsg;
        TextView rightMsg;
    }

}

5、最后修改MainActivity.java

package com.example.uibestpractice;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

public class MainActivity extends Activity {
    
    private ListView msgListView;
    private EditText inputText;
    private Button send;
    private MsgAdapter msgAdapter;
    private List<Msg> msgList=new ArrayList<Msg>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initMsgs();
        msgAdapter=new MsgAdapter(MainActivity.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(msgAdapter);
        send.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                String content=inputText.getText().toString();
                if(!"".equals(content)){
                    Msg msg=new Msg(content,Msg.TYPE_SENT);
                    msgList.add(msg);
                    msgAdapter.notifyDataSetChanged();//当有新消息时,刷新ListView中显示
                    msgListView.setSelection(msgList.size());//将ListView定位到最后一行。
                    inputText.setText("");//清空输入框中的内容
                }
                
            }
        });
        
    }
    
    private void initMsgs(){
        Msg msg1=new Msg("Hello guy.",Msg.TYPE_RECEIVED);
        msgList.add(msg1);
        Msg msg2=new Msg("Hello. Who is that?",Msg.TYPE_SENT);
        msgList.add(msg2);
        Msg msg3=new Msg("This is Tom. Nice Talking to you",Msg.TYPE_RECEIVED);
        msgList.add(msg3);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
}

 

以上是关于编写聊天界面的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

模仿QQ聊天界面的横向图片选择器HorizontalPicturePicker

模仿QQ聊天界面的横向图片选择器HorizontalPicturePicker

Android学习笔记-简单聊天界面的实现

iOS 类似微信,QQ聊天界面的气泡聊天简单实现Demo

不使用支持库的 Android 4.0、4.1 (<4.2) 中嵌套片段的最佳实践

更新片段参数的最佳实践?