zoukankan      html  css  js  c++  java
  • 【实战】聊天窗口的实现

      今天参考书上的例子,自己也实现了一个相对美观的聊天界面,过程如下:

    一、第一步制作用于显示聊天内容的图片,使用SDK目录下的Tools下的draw9patch.bat来制作Nine-Patch图片,以便适用于各种分辨率的终端;

      需要注意的是在制作好之后保存的时候不能把保存的名称改掉,一定要带上保存时自动加上的.9,并且在引用的时候名称不用写.9即可,切记!在这浪费了一个多小时

    二、编写主界面activity_main.xml,放一个ListView和LinearLayout,LinearLayout下面再放一个EditText(用于编写消息)和Button(用于发送消息)

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:id="@+id/LinearLayout1"
     4     android:layout_width="match_parent"
     5     android:layout_height="match_parent"
     6     android:orientation="vertical"
     7     android:background="#d8e0e8" >
     8 
     9     <ListView
    10         android:id="@+id/msg_list_view"
    11         android:layout_width="match_parent"
    12         android:layout_height="0dp"
    13         android:layout_weight="1"
    14         android:divider="#0000" >
    15     </ListView>
    16     
    17     
    18     <LinearLayout 
    19         android:layout_width="match_parent"
    20         android:layout_height="wrap_content">
    21         <EditText android:id="@+id/input_text"
    22             android:layout_width="0dp"
    23             android:layout_height="wrap_content"
    24             android:layout_weight="1"
    25             android:hint="Type something here"
    26             android:maxLines="2"/>
    27         
    28         <Button 
    29             android:id="@+id/send"
    30             android:layout_width="wrap_content"
    31             android:layout_height="wrap_content"
    32             android:text="Send"/>
    33         
    34     </LinearLayout>
    35 </LinearLayout>
    activity_main.xml

    三、新建消息实体类Msg

     1 package com.example.Entity;
     2 
     3 public class Msg {
     4     public static final int TYPE_RECEIVED = 0;
     5     public static final int TYPE_SEND = 1;
     6     private String content;//消息内容
     7     private int type;//消息类型,分为发送(TYPE_SEND)和接收的(TYPE_RECEIVED)
     8     
     9     public Msg(String content, int type) {
    10         // TODO Auto-generated constructor stub
    11         this.content = content;
    12         this.type = type;
    13     }
    14 
    15     public String getContent() {
    16         return content;
    17     }
    18 
    19     public int getType() {
    20         return type;
    21     }
    22 
    23 }
    Msg

    四、由于消息是用ListView显示的,那么接下来要编写ListView子项的布局,新建一个xml文件,msg_item.xml,发送和接收的消息在一个布局中,只要待会在代码中对布局的可见性进行控制即可;

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     android:orientation="vertical" 
     6     android:padding="10dp">
     7     
     8     9-26行是在左侧出现的主要是在left_layout布局中放入了一个TextView来显示文字,left_layout布局中的背景就是我们做的Nine-Patch图片;;;代表的是接收的消息
     9     <LinearLayout
    10         android:id="@+id/left_layout"
    11            android:layout_width="wrap_content"
    12            android:layout_height="wrap_content"
    13            android:layout_gravity="start"
    14            android:orientation = "vertical"
    15         android:background="@drawable/message_left">
    16         
    17         <TextView 
    18             android:id="@+id/left_msg"
    19                android:layout_width="wrap_content"
    20                android:layout_height="wrap_content"
    21                android:layout_gravity="center"
    22                android:layout_margin="10dp"
    23                android:textColor="#fff"
    24                android:textSize="15sp"/>
    25 
    26     </LinearLayout>
    27     9-26行是在右侧出现的主要是在right_layout布局中放入了一个TextView来显示文字,right_layout布局中的背景就是我们做的Nine-Patch图片;;;代表的是发送的消息
    28     <LinearLayout
    29         android:id="@+id/right_layout"
    30            android:layout_width="wrap_content"
    31            android:layout_height="wrap_content"
    32            android:layout_gravity="end"
    33            android:orientation = "vertical"
    34         android:background="@drawable/message_right">
    35         
    36         <TextView 
    37             android:id="@+id/right_msg"
    38                android:layout_width="wrap_content"
    39                android:layout_height="wrap_content"
    40                android:layout_gravity="center"
    41                android:layout_margin="10dp"
    42                android:textColor="#fff"
    43                android:textSize="15sp"/>
    44 
    45     </LinearLayout>
    46     
    47 </LinearLayout>

     四、由于ListView要显示的数据需要通过适配器Adapter来实现,下面我们来建立一个适配器类MsgAdapter,继承于ArrayAdapter,并将泛型指定为Msg类;

     1 package com.example.uibestpractice;
     2 
     3 import java.util.List;
     4 
     5 import com.example.Entity.Msg;
     6 
     7 import android.content.Context;
     8 import android.view.LayoutInflater;
     9 import android.view.View;
    10 import android.view.ViewGroup;
    11 import android.widget.ArrayAdapter;
    12 import android.widget.LinearLayout;
    13 import android.widget.TextView;
    14 
    15 public class MsgAdapter extends ArrayAdapter<Msg> {
    16     
    17     //设置私有变量
    18     private int resourceId;
    19     
    20     //建立三个参数的构造方法
    21     public MsgAdapter(Context context, int textViewResourceId , List<Msg> objects) {
    22 
    23         //实现了ArrayAdapter类的构造方法
    24         super(context, textViewResourceId,objects);
    25         resourceId = textViewResourceId;
    26     }
    27     
    28     //position就是你选择的 item的第几条从0开始
    29     //convertView就是item上的布局layout或者组件
    30     //ViewGroup parent 就是设置adapter的那个组件里面封装一个viewGroup用来盛放item
    31     @Override
    32     public View getView(int position, View convertView, ViewGroup parent) {
    33         // TODO Auto-generated method stub
    34         Msg msg = getItem(position);//获取当前项的Msg实例;
    35         View view ;//定义一个View
    36         ViewHolder viewHolder ;
    37 //        定义一个ViewHolder,ViewHolder是一个内部类,    
    38 //        就是一个持有者的类,他里面一般没有方法,只有属性,
    39 //        作用就是一个临时的储存器,把你getView方法中每次返回的View存起来,可以下次再用。
    40 //        这样做的好处就是不必每次都到布局文件中去拿到你的View,提高了效率
    41         
    42         //判断convertView对象是否为空,如果为空就重新加载;
    43         if(convertView == null)
    44         {
    45             //使用Layoutinflater为这个子项加载我们传入的布局(resourceId),
    46             view = LayoutInflater.from(getContext()).inflate(resourceId, null);
    47             //实例化内部类viewHolder
    48             viewHolder = new ViewHolder();
    49             //将控件的实例都存在ViewHolder中
    50             viewHolder.leftLayout =(LinearLayout) view.findViewById(R.id.left_layout);
    51             viewHolder.rightLayout =(LinearLayout) view.findViewById(R.id.right_layout);
    52             viewHolder.leftMag = (TextView) view.findViewById(R.id.left_msg);
    53             viewHolder.rightMag = (TextView) view.findViewById(R.id.right_msg);
    54             //把viewHolder通过View的setTag方法存放起来;
    55             view.setTag(viewHolder);
    56         }
    57         else//如果不为空,则重新调用convertView;不必重新加载
    58         {
    59             view = convertView;
    60             viewHolder = (ViewHolder) view.getTag();//取出viewHolder,也就取出了已经加载过得数据
    61         }
    62         
    63         if(msg.getType() == msg.TYPE_RECEIVED)//如果是接收的消息则左侧显示布局和文字,右侧隐藏
    64         {
    65             viewHolder.leftLayout.setVisibility(View.VISIBLE);
    66             viewHolder.rightLayout.setVisibility(View.GONE);
    67             viewHolder.leftMag.setText(msg.getContent());
    68         }
    69         else if(msg.getType() == msg.TYPE_SEND)//如果是发送的消息则右侧显示布局和文字,左侧隐藏
    70         {
    71             viewHolder.rightLayout.setVisibility(View.VISIBLE);
    72             viewHolder.rightMag.setText(msg.getContent());
    73             viewHolder.leftLayout.setVisibility(View.GONE);
    74         }
    75         //返回一个View
    76         return view;
    77     }
    78     class ViewHolder//临时存储器,把getView方法中每次返回的View存起来,可以下次再用
    79     {
    80         LinearLayout leftLayout ;
    81         LinearLayout rightLayout ;
    82         TextView leftMag;
    83         TextView rightMag;
    84         
    85     }
    86 }
    MsgAdapter

     五、最后来实现MainActivity.java的代码,为ListView初始化数据,并设置一些响应事件,完成最后的操作

     1 package com.example.uibestpractice;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 import com.example.Entity.Msg;
     7 
     8 import android.app.Activity;
     9 import android.os.Bundle;
    10 import android.view.Menu;
    11 import android.view.MenuItem;
    12 import android.view.View;
    13 import android.view.View.OnClickListener;
    14 import android.widget.Button;
    15 import android.widget.EditText;
    16 import android.widget.ListView;
    17 
    18 public class MainActivity extends Activity {
    19 
    20     private ListView msgListView;//定义ListView
    21     private EditText inputText;//定义EditText
    22     private Button send;//定义Button
    23     private MsgAdapter adapter;//定义MsgAdapter
    24     private List<Msg> msgList = new ArrayList<Msg>();//实例化一个泛型为Msg的List
    25     
    26     @Override
    27     protected void onCreate(Bundle savedInstanceState) {
    28         super.onCreate(savedInstanceState);
    29         setContentView(R.layout.activity_main);
    30         
    31         //初始化数据
    32         initMsgs();
    33         
    34         //调用MsgAdapter的构造方法实例化adapter,
    35         adapter = new MsgAdapter(MainActivity.this, R.layout.msg_item, msgList);
    36         
    37         //分别实例化EditText、Button、ListView
    38         inputText = (EditText) findViewById(R.id.input_text);
    39         send = (Button) findViewById(R.id.send);
    40         msgListView = (ListView) findViewById(R.id.msg_list_view);
    41         
    42         //为ListView加适配器;
    43         msgListView.setAdapter(adapter);
    44         
    45         //设置send的点击事件,响应用户操作
    46         send.setOnClickListener(new OnClickListener() {
    47             
    48             @Override
    49             public void onClick(View v) {
    50                 
    51                 //定义内容获取用户在EditText中输入的字符串
    52                 String content = inputText.getText().toString();
    53                 
    54                 //如果字符串不为空,把数据添加到 msgList中
    55                 if(!"".equals(content))
    56                 {
    57                     Msg msg = new Msg(content , Msg.TYPE_SEND);
    58                     msgList.add(msg);
    59                     
    60                     //动态更新ListView
    61                     adapter.notifyDataSetChanged();
    62                     
    63                     //将列表移动到刚发的消息处,即msgList的最大位置
    64                     msgListView.setSelection(msgList.size());
    65                     
    66                     //把输入框置空
    67                     inputText.setText("");
    68                 }
    69             }
    70         });
    71     }
    72 
    73     private void initMsgs() {
    74         // TODO Auto-generated method stub
    75         Msg msg1 = new Msg("Hello guy!",Msg.TYPE_RECEIVED);//往msgList中添加接收数据
    76         msgList.add(msg1);
    77         Msg msg2 = new Msg("Hello,Who is that?",Msg.TYPE_SEND);//往msgList中添加发送数据
    78         msgList.add(msg2);
    79         Msg msg3 = new Msg("This is Tom,Nice talking to you.",Msg.TYPE_RECEIVED);//往msgList中添加接收数据
    80         msgList.add(msg3);
    81     }
    82 
    83 
    84 }
    MainActivity.java

    至此,此次实战结束,运行效果图:

  • 相关阅读:
    Keyboarding题解
    埃及分数 解题报告
    小木棍加强版解题报告
    扩展欧几里得
    luoguP4999 烦人的数学作业
    中国剩余定理
    20201115gryz模拟赛解题报告
    扩展欧几里得算法
    斐蜀定理
    CSP2020-S游记
  • 原文地址:https://www.cnblogs.com/csschn/p/5248976.html
Copyright © 2011-2022 走看看