本篇博文最后修改时间:2016年8月18日,23:16。
一、简介
本篇介绍如何编写精美的聊天界面。
二、实验平台
系统版本:Windows7 家庭普通版 32位操作系统。
三、版权声明
博主:思跡
声明:喝水不忘挖井人,转载请注明出处。
原文地址:http://blog.youkuaiyun.com/omoiato
联系方式:315878825@qq.com
Java零基础入门交流群:541462902
四、编写精美的聊天界面
既然是要编写一个聊天界面,那就肯定要有收到的消息和发出的消息。
上一节中我们制作的message_left.9.png 可以作为收到消息的背景图,
那么毫无疑问你还需要再制作一张message_right.9.png 作为发出消息的背景图。
图片都提供好了之后就可以开始编码了
1、编写主界面
修改activity_main.xml中的代码,如下所示:
<span style="font-size:18px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#d8e0e8"
android:orientation="vertical" >
<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 somthing here"
android:maxLines="2" />
<Button
android:id="@+id/send"
android:layout_width="wrap_content"android:layout_height="wrap_content"
android:text="Send" />
</LinearLayout>
</LinearLayout></span>
这里在主界面中放置了一个ListView 用于显示聊天的消息内容,
又放置了一个EditText用于输入消息,
还放置了一个Button 用于发送消息。
ListView 中用到了一个android:divider属性,它可以指定ListView 分隔线的颜色,
这里#0000 表示将分隔线设为透明色。
2、定义消息的实体类
新建Msg,代码如下所示:
<span style="font-size:18px;">public class Msg
{
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;
}
}</span>
Msg 类中只有两个字段,content 表示消息的内容,type 表示消息的类型。
其中消息类型有两个值可选,TYPE_RECEIVED 表示这是一条收到的消息,
TYPE_SENT 表示这是一条发出的消息接着来编写ListView 子项的布局,
3、新建msg_item.xml
<span style="font-size:18px;"><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></span>
这里我们让收到的消息居左对齐,发出的消息居右对齐,
并且分别使用message_left.9.png和message_right.9.png 作为背景图。
稍后在代码中根据消息的类型来决定隐藏和显示哪种消息。
4、创建ListView 的适配器类
让它继承自ArrayAdapter,并将泛型指定为Msg类。
新建类MsgAdapter,代码如下所示:
<span style="font-size:18px;">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)
{
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.rightLayout.setVisibility(View.VISIBLE);
viewHolder.leftLayout.setVisibility(View.GONE);
viewHolder.rightMsg.setText(msg.getContent());
}
return view;
}
class ViewHolder
{
LinearLayout leftLayout;
LinearLayout rightLayout;
TextView leftMsg;
TextView rightMsg;
}
}</span>
以上代码ListView 那一节的代码基本是一样的,只不过在getView()方法中增加了对消息类型的判断。
如果这条消息是收到的,则显示左边的消息布局,
如果这条消息是发出的,则显示右边的消息布局。
5、为ListView 初始化一些数据,并给发送按钮加入事件响应
修改MainActivity 中的代码,代码如下所示:
<span style="font-size:18px;">public class MainActivity 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);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initMsgs(); // 初始化消息数据
adapter = 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(adapter);
send.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
String content = inputText.getText().toString();
if (!"".equals(content))
{
Msg msg = new Msg(content, Msg.TYPE_SENT);
msgList.add(msg);
adapter.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);
}
}</span>
在initMsgs()方法中:
①初始化了几条数据用于在ListView 中显示。
②在发送按钮的点击事件里获取了EditText 中的内容,
如果内容不为空则创建出一个新的Msg 对象,并把它添加到msgList 列表中去。
③调用了适配器的notifyDataSetChanged()方法,用于通知列表的数据发生了变化,
这样新增的一条消息才能够在ListView 中显示。
④调用ListView的setSelection()方法将显示的数据定位到最后一行,
以保证一定可以看得到最后发出的一条消息。
⑤调用EditText 的setText()方法将输入的内容清空。
这样所有的工作就都完成了,运行程序之后将会看到非常美观的聊天界面,
并且可以输入和发送消息,如图所示。