【實戰】聊天窗口的實現


  今天參考書上的例子,自己也實現了一個相對美觀的聊天界面,過程如下:

一、第一步制作用於顯示聊天內容的圖片,使用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

 

至此,此次實戰結束,運行效果圖:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM