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

想象一下,最简单的聊天界面里面需要的有哪些?
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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值