android学习笔记——聊天界面的练习

来源:互联网 发布:linux根目录介绍 编辑:程序博客网 时间:2024/05/22 15:01
想象一下,最简单的聊天界面里面需要的有哪些?
1、一个ListView来显示对话信息
2、底部需要一个EditText来输入信息,还要一个Button来点击发送。
好了,根据以上的想法先将activity_main.xml文件编写出来
<?xml version="1.0" encoding="utf-8"?>
<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: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 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>

写好主界面的布局后,我们把消息的实体类写一下。
消息分为两种,一种是发出的,一种是收到的,所以我们将消息实体设计成这样:
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;
    }
}

消息的实体类有了,我们需要将实体放在View上才能看的到,这是就得好好想想msg_item.xml这个文件该怎么写了。就是它要填充到主界面中ListView的每一个item中去。既然消息分两种,那么显示的View自然也是需要两种的。看看布局文件是怎么写的。
<?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/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="#000"/>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/right_layout"
        android:layout_marginLeft="200dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:background="@drawable/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"
            android:textColor="#000"/>
    </LinearLayout>
</LinearLayout>

这个时候就有些疑惑了,怎么能让收到和发送的信息布局放到同一个布局文件里呢?别担心,还记得可见属性么?
我们在代码中根据发送还是接收进行一个判断,然后设置相应的可见性,问题不就解决了吗?
但是,到底该在哪里写这些代码呢?
答案就是Adapter,可以肯定的一点,Adapter的作用就是将view与数据进行绑定的工具,它与布局中的每个组件联系紧密,就是在这里,我们需要判断数据到底该使用哪个布局,是发送呢?还是接收呢?
看看代码
public class MsgAdapter extends ArrayAdapter<Msg> {

    private int resourceId;

    public MsgAdapter(Context context,int textViewResourceId, List<Msg> objects) {
        super(context,textViewResourceId, objects);
        resourceId = textViewResourceId;
    }

一点一点来讲解,别急。
创建ListView的适配器类,让它继承ArrayAdapter,并将泛型指定为Msg类。新建类MsgAdapter。
上面的代码中,resourceId是为了获取当前View的ID,方便一会使用,进行一个绑定。

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Msg msg = getItem(position);
        View view;
        ViewHolder viewHolder;//还记得ViewHolder吧,他是一个内部类,方便在View已经存在的情况下使用该布局,只需要getTag(viewHolder)就可以咯
        if(convertView == null){
            view = LayoutInflater.from(getContext()).inflate(resourceId,null);//在这里使用resourceId来对view进行绑定,修改。
            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();
        }
//以上,我们使用ViewHolder给view进行了页面的布局绑定,之后我们只需要对ViewHolder中的内容进行操作,view中的内容也会随之跟着改变。很方便有木有!
        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());
        }
//上述对消息实体类进行了判断,然后设置不同的显示/隐藏。使用viewHolder,很方便吧,代码也简介明了了很多。
        return view;
//最后当然还是要返回view,给主活动使用。
    }

    class ViewHolder{
        LinearLayout leftLayout;
        LinearLayout rightLayout;
        TextView leftMsg;
        TextView rightMsg;
    }
}

把上面的这些事都干完后,回到主活动中来。仔细想想好像在主活动中要做的事情已经没多少了。
1、把消息实体初始化一下
2、给主活动的页面初始化一下(加载写好的ListView这个布局)
3、给设置下Button的点击事件,让输入框中的内容发送出去。
好,那我们就开始吧~

1.将消息实体初始化
public void initMsgs(){
    Msg msg1 = new Msg("Hello guys",Msg.TYPE_RECEIVED);
    msgList.add(msg1);
    Msg msg2 = new Msg("Hello Who is there?",Msg.TYPE_SENT);
    msgList.add(msg2);
    Msg msg3 = new Msg("I am tom ,Nice talking to you",Msg.TYPE_RECEIVED);
    msgList.add(msg3);
}
看上述代码,其实要做的只有两件事:1.创建一个Msg对象,传入两个参数,参数1是消息信息,参数2是消息类型。2.将创建出的Msg对象加入到msgList列表中去。

2.给主活动的页面初始化一下(加载写好的ListView这儿布局)
adapter new MsgAdapter(MainActivity.this,R.layout.msg_item,msgList);//在adapter中绑定好数据和组件
msgListView = (ListView) findViewById(R.id.msg_list_view);
msgListView.setAdapter(adapter)//给msgListView设置Adapter

3.设置Button的点击事件,让输入框中的内容发送出去
inputText = (EditText) findViewById(R.id.input_text);
send = (Button) findViewById(R.id.send);
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_SENT);
            msgList.add(msg);
            adapter.notifyDataSetChanged();//当有新消息时,刷新ListView中的显示
            msgListView.setSelection(msgList.size());//将ListView定位到最后一行
            inputText.setText("");//清空输入框中的内容
        }
    }
});
至此,所有的工作就做完了。同学们可以试试看啦~
0 0
原创粉丝点击