上一篇说了欢迎和登陆界面的实现,现在来说一下关于聊天界面的搭建,整体界面采用了一个ListView,主要的布局很简单,在这里使用了ListView自定义是Adapter的写法
同时,我构造了一个TaliListInfo的类来和Adapter对应
闲话不多说,直接上代码
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.demo.Adapter; 2 3 import java.util.List; 4 5 import com.tuisong.R; 6 7 import android.content.Context; 8 import android.database.DataSetObserver; 9 import android.view.LayoutInflater; 10 import android.view.View; 11 import android.view.ViewGroup; 12 import android.widget.BaseAdapter; 13 import android.widget.LinearLayout; 14 import android.widget.TextView; 15 16 public class NewAdapterView extends BaseAdapter { 17 18 @SuppressWarnings("unused") 19 private static final String TAG = NewAdapterView.class.getSimpleName(); 20 21 private List<MessageEnity> coll; 22 23 private Context context; 24 25 // 构造函数 26 public NewAdapterView(Context context, List<MessageEnity> list) { 27 this.context = context; 28 this.coll = list; 29 } 30 31 public boolean areAllItemsEnabled() { 32 return false; 33 } 34 35 public boolean isEnabled(int arg0) { 36 return false; 37 } 38 39 @Override 40 public int getCount() { 41 // TODO Auto-generated method stub 42 return coll.size(); 43 } 44 45 @Override 46 public Object getItem(int arg0) { 47 // TODO Auto-generated method stub 48 return coll.get(arg0); 49 } 50 51 @Override 52 public long getItemId(int arg0) { 53 // TODO Auto-generated method stub 54 return arg0; 55 } 56 57 public int getItemViewType(int position) { 58 return position; 59 } 60 61 @Override 62 public View getView(int positon, View convertView, ViewGroup parent) { 63 // TODO Auto-generated method stub 64 MessageEnity entity = coll.get(positon); 65 int itemLayout = entity.getLayoutID(); 66 67 LinearLayout layout = new LinearLayout(context); 68 LayoutInflater inflater = (LayoutInflater) context 69 .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 70 inflater.inflate(itemLayout, layout, true); 71 72 TextView tvName = (TextView) layout.findViewById(R.id.person_name); 73 tvName.setText(entity.getfromUser()); 74 75 TextView tvData = (TextView) layout.findViewById(R.id.time_say); 76 tvData.setText(entity.getTime()); 77 78 TextView tvItem = (TextView) layout.findViewById(R.id.item_say); 79 tvItem.setText(entity.getItem()); 80 81 return layout; 82 } 83 84 public int getViewTypeCount() { 85 return coll.size(); 86 } 87 88 public boolean hasStableIds() { 89 return false; 90 } 91 92 public boolean isEmpty() { 93 return false; 94 } 95 96 public void registerDataSetObserver(DataSetObserver observer) { 97 } 98 99 public void unregisterDataSetObserver(DataSetObserver observer) { 100 } 101 102 }
Adapter的构造过程
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.demo.Adapter; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 import com.tuisong.R; 6 7 import android.content.Context; 8 import android.util.Log; 9 import android.view.LayoutInflater; 10 import android.view.View; 11 import android.view.ViewGroup; 12 import android.widget.BaseAdapter; 13 import android.widget.TextView; 14 15 public class ListAdapter extends BaseAdapter { 16 17 private Context context; 18 private List<TalkListInfo> talklist = new ArrayList<TalkListInfo>(); 19 private LayoutInflater inflater = null; 20 21 public ListAdapter(Context context, List<TalkListInfo> talklist) { 22 this.context = context; 23 this.talklist = talklist; 24 Log.d("create", "!!!"); 25 } 26 27 @Override 28 public int getCount() { 29 // TODO Auto-generated method stub 30 return talklist.size(); 31 } 32 33 @Override 34 public Object getItem(int arg0) { 35 // TODO Auto-generated method stub 36 return talklist.get(arg0); 37 } 38 39 @Override 40 public long getItemId(int arg0) { 41 // TODO Auto-generated method stub 42 return arg0; 43 } 44 45 @Override 46 public View getView(int arg0, View arg1, ViewGroup arg2) { 47 // TODO Auto-generated method stub 48 49 inflater = LayoutInflater.from(this.context); 50 TalkHolder talk = new TalkHolder(); 51 if (arg1 == null) { 52 talk = new TalkHolder(); 53 arg1 = inflater.inflate(R.layout.talklistadapter, null); 54 talk.tv_name = (TextView) arg1.findViewById(R.id.tv_name); 55 talk.tv_time = (TextView) arg1.findViewById(R.id.tv_time); 56 talk.tv_item = (TextView) arg1.findViewById(R.id.tv_item); 57 arg1.setTag(talk); 58 } else { 59 talk = (TalkHolder) arg1.getTag(); 60 } 61 62 talk.tv_name.setText(talklist.get(arg0).getName()); 63 talk.tv_time.setText(talklist.get(arg0).getDate()); 64 talk.tv_item.setText(talklist.get(arg0).getItem()); 65 66 return arg1; 67 } 68 69 } 70 71 class TalkHolder { 72 public TextView tv_name; 73 public TextView tv_time; 74 public TextView tv_item; 75 }
同时,还需要写一个对应的布局来作为ListView的Adapter的布局
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="fill_parent" 5 android:layout_height="wrap_content" 6 android:background="#eeeeee" 7 android:orientation="horizontal" 8 tools:context="com.baidu.push.example.CustomActivity" > 9 10 <ImageView 11 android:layout_width="64dp" 12 android:layout_height="64dp" 13 android:background="@drawable/retouxiang" 14 android:contentDescription="@string/app_name" 15 android:scaleType="fitXY" /> 16 17 <LinearLayout 18 android:layout_width="fill_parent" 19 android:layout_height="64dp" 20 android:orientation="vertical" > 21 22 <LinearLayout 23 android:layout_width="fill_parent" 24 android:layout_height="32dp" 25 android:orientation="horizontal" > 26 27 <TextView 28 android:id="@+id/tv_name" 29 android:layout_width="0dp" 30 android:layout_height="32dp" 31 android:layout_weight="1" 32 android:text="@string/app_name" 33 android:textColor="#000000" /> 34 35 <TextView 36 android:id="@+id/tv_time" 37 android:layout_width="0dp" 38 android:layout_height="32dp" 39 android:layout_weight="1" 40 android:text="@string/app_name" 41 android:textColor="#000000" /> 42 </LinearLayout> 43 44 <TextView 45 android:id="@+id/tv_item" 46 android:layout_width="fill_parent" 47 android:layout_height="32dp" 48 android:text="@string/app_name" 49 android:textColor="#000000" /> 50 </LinearLayout> 51 52 </LinearLayout>
同时,因为只是个Demo,我的头像没有下载的功能,采用了一个空白的头像图片,取消了下载功能,效果如图
同时,因为聊天记录保存在SQLite中,所以,需要自己实现一个DBhelper的类继承SQLiteOpenHelper,代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.tuisong.db; 2 3 import java.util.ArrayList; 4 import java.util.HashSet; 5 import java.util.List; 6 import com.demo.Adapter.MessageEnity; 7 import com.demo.Adapter.TalkListInfo; 8 9 import android.annotation.SuppressLint; 10 import android.content.ContentValues; 11 import android.content.Context; 12 import android.database.Cursor; 13 import android.database.sqlite.SQLiteDatabase; 14 import android.database.sqlite.SQLiteOpenHelper; 15 16 public class DBHelpter extends SQLiteOpenHelper { 17 18 private final static String DATABASE_NAME = "chat_record_db"; 19 private final static String TABLE_NAME = "chat_table"; 20 private final static String FROM_USER = "fromuser"; 21 private final static String TO_USER = "touser"; 22 private final static String TIME = "time"; 23 private final static String CHAT_CONTENT = "content"; 24 private final static String LAYOUT_ID = "layoutid"; 25 @SuppressWarnings("unused") 26 private final static String CHAT_ID = "id"; 27 private String openid = null; 28 public DBHelpter help; 29 30 @SuppressLint("NewApi") 31 public DBHelpter(Context context) { 32 super(context, DATABASE_NAME, null, 1); 33 System.out.println("the data has been created"); 34 // TODO Auto-generated constructor stub 35 } 36 37 @Override 38 public void onCreate(SQLiteDatabase db) { 39 // TODO Auto-generated method stub 40 String sql = "CREATE TABLE if not exists chat_table ( id INTEGER PRIMARY KEY AUTOINCREMENT, fromuser TEXT, touser TEXT, time TEXT, content TEXT, layoutid TEXT);"; 41 42 db.execSQL(sql); 43 System.out.println(sql); 44 } 45 46 //更新数据库,因为我没有数据的修改,所以不需要实现此方法 47 @Override 48 public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) { 49 // TODO Auto-generated method stub 50 // db.execSQL("drop table if exists" + TABLE_NAME); 51 52 // onCreate(db); 53 } 54 //插入数据 55 public void Insert(MessageEnity message) { 56 SQLiteDatabase db = this.getWritableDatabase(); 57 ContentValues value = new ContentValues(); 58 value.put(FROM_USER, message.getfromUser()); 59 value.put(TO_USER, message.gettomUser()); 60 value.put(TIME, message.getTime()); 61 value.put(CHAT_CONTENT, message.getItem()); 62 value.put(LAYOUT_ID, message.getLayoutID()); 63 64 long ss = db.insert(TABLE_NAME, null, value); 65 System.out.println("has been insert in db " + ss); 66 } 67 68 // 消息内容 69 public List<MessageEnity> findPersonMessage(String openid, String userid) { 70 List<MessageEnity> messages = new ArrayList<MessageEnity>(); 71 SQLiteDatabase db = this.getReadableDatabase(); 72 System.out.println("dsdfsw" + db.toString()); 73 74 String sql = "select * from chat_table where (fromuser='" + openid 75 + "' and touser='" + userid + "') or (touser='" + openid 76 + "' and fromuser='" + userid + "') order by time "; 77 Cursor cursor = db.rawQuery(sql, null); 78 cursor.moveToFirst(); 79 System.out.println("the find message is " + cursor.getCount()); 80 if (cursor.getCount() > 0) { 81 if (cursor.getCount() > 10) { 82 cursor.moveToPosition(cursor.getCount() - 10); 83 for (int i = 0; i < 10; i++) { 84 MessageEnity message = new MessageEnity(); 85 message.setfroUser(cursor.getString(cursor 86 .getColumnIndex(FROM_USER))); 87 message.setItem(cursor.getString(cursor 88 .getColumnIndex(CHAT_CONTENT))); 89 message.setLayoutID(cursor.getInt(cursor 90 .getColumnIndex(LAYOUT_ID))); 91 message.setTime(cursor.getString(cursor 92 .getColumnIndex(TIME))); 93 message.settoUser(cursor.getString(cursor 94 .getColumnIndex(TO_USER))); 95 messages.add(message); 96 cursor.moveToNext(); 97 } 98 } else { 99 cursor.moveToFirst(); 100 for (int i = 0; i < cursor.getCount(); i++) { 101 MessageEnity message = new MessageEnity(); 102 message.setfroUser(cursor.getString(cursor 103 .getColumnIndex(FROM_USER))); 104 message.setItem(cursor.getString(cursor 105 .getColumnIndex(CHAT_CONTENT))); 106 message.setLayoutID(cursor.getInt(cursor 107 .getColumnIndex(LAYOUT_ID))); 108 message.setTime(cursor.getString(cursor 109 .getColumnIndex(TIME))); 110 message.settoUser(cursor.getString(cursor 111 .getColumnIndex(TO_USER))); 112 messages.add(message); 113 cursor.moveToNext(); 114 } 115 } 116 return messages; 117 } else { 118 return null; 119 } 120 121 } 122 123 // 列出消息列表 124 public List<TalkListInfo> findList(String touser) { 125 List<TalkListInfo> infos = new ArrayList<TalkListInfo>(); 126 SQLiteDatabase db = this.getReadableDatabase(); 127 System.out.println("the ver sion is" + db.getVersion()); 128 String sql = "select fromuser, time , content,count(distinct fromuser) from chat_table where touser='" 129 + touser + "' group by fromuser order by time desc"; 130 // Cursor cursor = db.query(TABLE_NAME, new String[] { FROM_USER, TIME, 131 // CHAT_CONTENT }, null, null, null, null, TIME); 132 Cursor cursor = db.rawQuery(sql, null); 133 System.out.println("the ver num is" + cursor.getCount()); 134 cursor.moveToFirst(); 135 if (cursor.getCount() > 0) { 136 System.out.println("the tag num "); 137 for (int i = 0; i < cursor.getCount(); i++) { 138 139 if (cursor.getString(cursor.getColumnIndex(FROM_USER)).equals( 140 openid) != true) { 141 TalkListInfo info = new TalkListInfo(); 142 143 info.setName(cursor.getString(cursor 144 .getColumnIndex(FROM_USER))); 145 146 info.setDate(cursor.getString(cursor.getColumnIndex(TIME))); 147 info.setItem(cursor.getString(cursor 148 .getColumnIndex(CHAT_CONTENT))); 149 150 infos.add(info); 151 cursor.moveToNext(); 152 } 153 } 154 155 System.out.println("tag2"); 156 removeDuplicate(infos); 157 return infos; 158 } else { 159 System.out.println("tag3"); 160 return infos; 161 } 162 163 } 164 165 public static void removeDuplicate(List<TalkListInfo> list) { 166 HashSet<TalkListInfo> h = new HashSet<TalkListInfo>(list); 167 list.clear(); 168 list.addAll(h); 169 System.out.println(list); 170 } 171 172 }
好了到了这里,准备工作已经基本完成了,现在就要编写界面的后台代码了
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 package com.baidu.push.example; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 8 import com.baidu.android.pushservice.PushConstants; 9 import com.baidu.android.pushservice.PushManager; 10 import com.demo.Adapter.ListAdapter; 11 import com.demo.Adapter.TalkListInfo; 12 import com.tuisong.R; 13 import com.tuisong.Save_Read; 14 import com.tuisong.Until; 15 import com.tuisong.db.DBHelpter; 16 17 import android.app.Activity; 18 import android.app.NotificationManager; 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.SharedPreferences; 23 import android.os.Bundle; 24 import android.view.Menu; 25 import android.view.MenuItem; 26 import android.view.View; 27 import android.widget.AdapterView.OnItemClickListener; 28 import android.widget.AdapterView; 29 import android.widget.ListView; 30 import android.widget.RelativeLayout; 31 32 public class PushDemoActivity extends Activity implements OnItemClickListener { 33 34 private static ListView list; 35 private static List<TalkListInfo> talk; 36 private static ListAdapter adapter; 37 RelativeLayout mainLayout = null; 38 public static int initialCnt = 0; 39 public Save_Read save = new Save_Read(); 40 public static Map<String, String> map; 41 public static DBHelpter help; 42 public static String userid; 43 public SharedPreferences sp; 44 public static NotificationManager manager; 45 46 @Override 47 public void onCreate(Bundle savedInstanceState) { 48 super.onCreate(savedInstanceState); 49 50 setContentView(R.layout.main); 51 @SuppressWarnings("unused") 52 NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 53 @SuppressWarnings("unused") 54 MyReceiver receiver = new MyReceiver(); 55 sp = this.getSharedPreferences("key", 0); 56 SharedPreferences.Editor edtior = sp.edit(); 57 edtior.putString("SSP", "1"); 58 edtior.commit(); 59 60 list = (ListView) findViewById(R.id.list); 61 help = new DBHelpter(this); 62 map = new HashMap<String, String>(); 63 64 userid = sp.getString("Login", null); 65 System.out.println("the login id is " + userid); 66 67 talk = new ArrayList<TalkListInfo>(); 68 69 talk = help.findList(userid); 70 71 if (talk != null) { 72 for (TalkListInfo t : talk) { 73 74 map.put("name", t.getName()); 75 map.put("time", t.getDate()); 76 map.put("content", t.getItem()); 77 } 78 adapter = new ListAdapter(this, talk); 79 list.setAdapter(adapter); 80 } 81 82 list.setOnItemClickListener(new OnItemClickListener() { 83 84 @Override 85 public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, 86 long arg3) { 87 // TODO Auto-generated method stub 88 Intent intent = new Intent(PushDemoActivity.this, 89 TalkActivity.class); 90 intent.putExtra("name", talk.get(arg2).getName()); 91 intent.putExtra("userid", userid); 92 Until.setString(talk.get(arg2).getName()); 93 startActivity(intent); 94 95 } 96 }); 97 98 // 以apikey的方式登录,一般放在主Activity的onCreate中 99 PushManager.startWork(getApplicationContext(), 100 PushConstants.LOGIN_TYPE_API_KEY, 101 Utils.getMetaValue(PushDemoActivity.this, "api_key")); 102 103 } 104 105 @Override 106 public void onStart() { 107 super.onStart(); 108 109 } 110 111 @Override 112 public void onResume() { 113 super.onResume(); 114 115 SharedPreferences.Editor edtior = sp.edit(); 116 edtior.putString("SSP", "0"); 117 edtior.commit(); 118 119 } 120 121 @Override 122 protected void onNewIntent(Intent intent) { 123 // 如果要统计Push引起的用户使用应用情况,请实现本方法,且加上这一个语句 124 setIntent(intent); 125 126 } 127 128 @Override 129 protected void onPause() { 130 // TODO Auto-generated method stub 131 super.onPause(); 132 133 SharedPreferences.Editor edtior = sp.edit(); 134 edtior.putString("SSP", "0"); 135 edtior.commit(); 136 } 137 138 @Override 139 public void onStop() { 140 super.onStop(); 141 PushManager.activityStoped(this); 142 // SharedPreferences.Editor edtior = sp.edit(); 143 // edtior.putString("Login", "-1"); 144 // edtior.commit(); 145 // } 146 } 147 148 @Override 149 protected void onDestroy() { 150 // TODO Auto-generated method stub 151 super.onDestroy(); 152 // SharedPreferences.Editor edtior = sp.edit(); 153 // edtior.putString("Login", "-1"); 154 // edtior.commit(); 155 } 156 157 @Override 158 public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { 159 // TODO Auto-generated method stub 160 161 } 162 163 public boolean onCreateOptionsMenu(Menu menu) { 164 // 调用父类方法来加入系统菜单 165 // 虽然目前android还没有系统菜单,但是为了兼容到以后的版本,最好加上 166 super.onCreateOptionsMenu(menu); 167 168 // 添加菜单项(多种方式) 169 // 1.直接指定标题 170 menu.add(1, 0, 1, "退出"); 171 172 // 3.显示指定菜单项的组号、ID、排序号、标题 173 174 // 如果希望显示菜单,请返回true 175 return true; 176 } 177 178 @Override 179 public boolean onOptionsItemSelected(MenuItem item) { 180 switch (item.getItemId()) { 181 // 响应每个菜单项(通过菜单项的ID) 182 183 case 0: 184 change(); 185 finish(); 186 // do something here 187 break; 188 default: 189 // 对没有处理的事件,交给父类来处理 190 return super.onOptionsItemSelected(item); 191 } 192 // 返回true表示处理完菜单项的事件,不需要将该事件继续传播下去了 193 return true; 194 } 195 196 197 //修改当前活动activity的状态 198 public void change() { 199 SharedPreferences.Editor edtior = sp.edit(); 200 edtior.putString("Login", "-1"); 201 edtior.commit(); 202 } 203 }
到这里,对话列表的界面搭建已经完成了,下一篇文章里面介绍聊天界面写法