android 仿微信demo——微信消息界面實現(xiàn)(移動端)
移動端微信消息頁實現(xiàn)
在上一篇中主界面實現(xiàn)說過微信四個頁面中間都是是fragment的,并且四個fragment的布局都還沒實現(xiàn),所以這一篇主要實現(xiàn)微信消息界面的實現(xiàn)(第一個fragment)
微信消息頁是可以上下滑動,每一個列表最多都有可顯示五個數(shù)據(jù),還可以點擊列表

要實現(xiàn)上訴功能只需要在fragment布局中使用ListView,然后給ListView指定一個Item布局即可
修改微信消息界面fragment布局
weixin_fragment.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@drawable/main_list_divider_line"
android:dividerHeight="1.5px"
android:layout_marginBottom="50dp">
</ListView>
</LinearLayout>
上述代碼自定義了一個分割線
微信消息頁每一個列表都有分割線,而系統(tǒng)自帶的分割線是充滿屏幕寬度的,所以要自己定義一個分割線
自定義分割線main_list_divider_line.xml


main_list_divider_line.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:left="80dp"
android:right="0dp">
<shape android:shape="rectangle" >
<solid android:color="#33000000" />
</shape>
</item>
</layer-list>
創(chuàng)建微信消息界面fragment中ListView對應(yīng)的item布局
weixin_item.xml
<?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="80dp"
android:layout_marginTop="300dp"
android:padding="10dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/img1"
android:layout_width="20dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"/>
<LinearLayout
android:orientation="vertical"
android:layout_marginLeft="23dp"
android:layout_width="8dp"
android:layout_height="match_parent"
android:layout_weight="4">
<TextView
android:id="@+id/title"
android:textColor="#000000"
android:textSize="18dp"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2.5"/>
<TextView
android:id="@+id/content"
android:textColor="#A8A8A8"
android:gravity="center_vertical"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1.5"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingRight="-50dp"
android:layout_weight="1"
android:gravity="right"
android:orientation="vertical">
<TextView
android:id="@+id/time"
android:textColor="#A8A8A8"
android:textSize="15dp"
android:layout_gravity="right"
android:layout_marginRight="1dp"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"/>
<ImageView
android:id="@+id/code"
android:background="@color/white"
android:layout_gravity="right"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"/>
</LinearLayout>
</LinearLayout>
修改微信消息界面fragment.java代碼
package com.example.wxchatdemo;
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import com.example.wxchatdemo.adapter.ImageAdapter;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SuppressLint("ValidFragment")
public class WeixinFragment extends Fragment {
//微信號,用于查找微信消息列表
private String number;
// 聲明組件
private ListView listView;
// 創(chuàng)建集合用于存儲服務(wù)器發(fā)來的顯示微信消息列表的一些信息
private List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
//自定義的一個Hander消息機(jī)制
private MyHander myhander = new MyHander();
/*有參構(gòu)造方法,參數(shù)為微信號*/
@SuppressLint("ValidFragment")
WeixinFragment(String number) {
this.number = number;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// 開一個線程完成網(wǎng)絡(luò)請求操作
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
httpUrlConnPost(String.valueOf(number));
}
});
thread1.start();
/*等待網(wǎng)絡(luò)請求線程完成*/
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
//獲取fragment布局
View view = inflater.inflate(R.layout.weixin_fragment, container, false);
//初始化組件
listView = view.findViewById(R.id.listView);
//創(chuàng)建自定義的適配器,用于把數(shù)據(jù)顯示在組件上
BaseAdapter adapter = new ImageAdapter(getActivity().getApplicationContext(), list);
//設(shè)置適配器
listView.setAdapter(adapter);
return view;
}
// 1.編寫一個發(fā)送請求的方法
// 發(fā)送請求的主要方法
public void httpUrlConnPost(String number) {
HttpURLConnection urlConnection = null;
URL url;
try {
// 請求的URL地地址
url = new URL(
"http://100.2.178.10:8080/AndroidServer_war_exploded/WeixinInformation");
urlConnection = (HttpURLConnection) url.openConnection();// 打開http連接
urlConnection.setConnectTimeout(3000);// 連接的超時時間
urlConnection.setUseCaches(false);// 不使用緩存
// urlConnection.setFollowRedirects(false);是static函數(shù),作用于所有的URLConnection對象。
urlConnection.setInstanceFollowRedirects(true);// 是成員函數(shù),僅作用于當(dāng)前函數(shù),設(shè)置這個連接是否可以被重定向
urlConnection.setReadTimeout(3000);// 響應(yīng)的超時時間
urlConnection.setDoInput(true);// 設(shè)置這個連接是否可以寫入數(shù)據(jù)
urlConnection.setDoOutput(true);// 設(shè)置這個連接是否可以輸出數(shù)據(jù)
urlConnection.setRequestMethod("POST");// 設(shè)置請求的方式
urlConnection.setRequestProperty("Content-Type",
"application/json;charset=UTF-8");// 設(shè)置消息的類型
urlConnection.connect();// 連接,從上述至此的配置必須要在connect之前完成,實際上它只是建立了一個與服務(wù)器的TCP連接
JSONObject json = new JSONObject();// 創(chuàng)建json對象
//json.put("title", URLEncoder.encode(title, "UTF-8"));// 使用URLEncoder.encode對特殊和不可見字符進(jìn)行編碼
json.put("number", URLEncoder.encode(number, "UTF-8"));// 把數(shù)據(jù)put進(jìn)json對象中
String jsonstr = json.toString();// 把JSON對象按JSON的編碼格式轉(zhuǎn)換為字符串
// ------------字符流寫入數(shù)據(jù)------------
OutputStream out = urlConnection.getOutputStream();// 輸出流,用來發(fā)送請求,http請求實際上直到這個函數(shù)里面才正式發(fā)送出去
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));// 創(chuàng)建字符流對象并用高效緩沖流包裝它,便獲得最高的效率,發(fā)送的是字符串推薦用字符流,其它數(shù)據(jù)就用字節(jié)流
bw.write(jsonstr);// 把json字符串寫入緩沖區(qū)中
bw.flush();// 刷新緩沖區(qū),把數(shù)據(jù)發(fā)送出去,這步很重要
out.close();
bw.close();// 使用完關(guān)閉
Log.i("aa", urlConnection.getResponseCode() + "");
//以下判斷是否訪問成功,如果返回的狀態(tài)碼是200則說明訪問成功
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {// 得到服務(wù)端的返回碼是否連接成功
// ------------字符流讀取服務(wù)端返回的數(shù)據(jù)------------
InputStream in = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(in));
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = br.readLine()) != null) {// BufferedReader特有功能,一次讀取一行數(shù)據(jù)
System.out.println("測試:" + str);
buffer.append(str);
}
in.close();
br.close();
JSONObject rjson = new JSONObject(buffer.toString());
String str1 = rjson.getJSONObject("json").get("titleimg").toString();
String[] pic = str1.split("\r\n");
String str2 = rjson.getJSONObject("json").get("title").toString();
String[] title = str2.split("\r\n");
String str3 = rjson.getJSONObject("json").get("content").toString();
String[] content = str3.split("\r\n");
String str4 = rjson.getJSONObject("json").get("time").toString();
String[] time = str4.split("\r\n");
String str5 = rjson.getJSONObject("json").get("showcode").toString();
String[] pic2 = str5.split("\r\n");
for (int i = 0; i < pic.length; i++) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("pic", pic[i]);
System.out.println("網(wǎng)址:" + pic[i]);
map.put("title", title[i]);
System.out.println("網(wǎng)址:" + title[i]);
map.put("content", content[i]);
map.put("time", time[i]);
map.put("code", pic2[i]);
list.add(map);//將map放到list集合中
}
boolean result = rjson.getBoolean("json");// 從rjson對象中得到key值為"json"的數(shù)據(jù),這里服務(wù)端返回的是一個boolean類型的數(shù)據(jù)
System.out.println("json:===" + result);
//如果服務(wù)器端返回的是true,則說明跳轉(zhuǎn)微信頁成功,跳轉(zhuǎn)微信頁失敗
if (result) {// 判斷結(jié)果是否正確
//在Android中http請求,必須放到線程中去作請求,但是在線程中不可以直接修改UI,只能通過hander機(jī)制來完成對UI的操作
myhander.sendEmptyMessage(1);
Log.i("用戶:", "跳轉(zhuǎn)微信頁成功");
} else {
myhander.sendEmptyMessage(2);
System.out.println("222222222222222");
Log.i("用戶:", "跳轉(zhuǎn)微信頁失敗");
}
} else {
myhander.sendEmptyMessage(2);
}
} catch (Exception e) {
e.printStackTrace();
Log.i("aa", e.toString());
System.out.println("11111111111111111");
myhander.sendEmptyMessage(2);
} finally {
urlConnection.disconnect();// 使用完關(guān)閉TCP連接,釋放資源
}
}
// 在Android中不可以在線程中直接修改UI,只能借助Handler機(jī)制來完成對UI的操作
class MyHander extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//判斷hander的內(nèi)容是什么,如果是1則說明跳轉(zhuǎn)微信頁成功,如果是2說明跳轉(zhuǎn)微信頁失敗
switch (msg.what) {
case 1:
Log.i("aa", msg.what + "");
break;
case 2:
Log.i("aa", msg.what + "");
}
}
}
}
上述代碼具體的內(nèi)容就不闡述了,代碼都有注釋。主要說一下上面給ListView設(shè)置適配器,它是自定義的適配器,通過繼承系統(tǒng)自帶適配器BaseAdapter,重寫相應(yīng)方法,把數(shù)據(jù)顯示在LlistView對應(yīng)的item布局相應(yīng)組件上,至于為什么要自定義,因為微信消息頁每一個列表都有至少兩個圖片數(shù)據(jù),而要把圖片加載到組件上需要用到工具類(后面會給出)
上面fragment.java代碼自定義了一個適配器,現(xiàn)在就來創(chuàng)建它,創(chuàng)建之前,可以先創(chuàng)建包單獨存放適配器,方便管理;


ImageAdapter.java
package com.example.wxchatdemo.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.wxchatdemo.tools.GetImageByUrl;
import com.example.wxchatdemo.R;
import java.util.List;
import java.util.Map;
public class ImageAdapter extends BaseAdapter {
// 要顯示的數(shù)據(jù)的集合
private List<Map<String, Object>> data;
// 接受上下文
private Context context;
// 聲明內(nèi)部類對象
private ViewHolder viewHolder;
public ImageAdapter(Context context, List<Map<String, Object>> data) {
this.context = context;
this.data = data;
}
// 返回的總個數(shù)
@Override
public int getCount() {
// TODO Auto-generated method stub
return data.size();
}
// 返回每個條目對應(yīng)的數(shù)據(jù)
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return data.get(position);
}
// 返回的id
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
// 返回這個條目對應(yīng)的控件對象
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 判斷當(dāng)前條目是否為null
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = View.inflate(context, R.layout.weixin_item, null);
viewHolder.img1 = (ImageView) convertView
.findViewById(R.id.img1);
viewHolder.title = (TextView) convertView
.findViewById(R.id.title);
viewHolder.content = (TextView) convertView
.findViewById(R.id.content);
viewHolder.time = (TextView) convertView
.findViewById(R.id.time);
viewHolder.code = (ImageView) convertView
.findViewById(R.id.code);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
// 獲取List集合中的map對象
Map<String, Object> map = data.get(position);
// 獲取圖片的url路徑
String pic = map.get("pic").toString();
// 這里調(diào)用了圖片加載工具類的setImage方法將圖片直接顯示到控件上
GetImageByUrl getImageByUrl = new GetImageByUrl();
getImageByUrl.setImage(viewHolder.img1, pic);
String title = map.get("title").toString();
viewHolder.title.setText(title);
String content = map.get("content").toString();
viewHolder.content.setText(content);
String time = map.get("time").toString();
viewHolder.time.setText(time);
// 獲取圖片的url路徑
String code = map.get("code").toString();
// 這里調(diào)用了圖片加載工具類的setImage方法將圖片直接顯示到控件上
GetImageByUrl getImageByUrl2 = new GetImageByUrl();
getImageByUrl2.setImage(viewHolder.code, code);
return convertView;
}
/**
* 內(nèi)部類 記錄單個條目中所有屬性
*
*
*
*/
class ViewHolder {
public ImageView img1;
public TextView title;
public TextView content;
public TextView time;
public ImageView code;
}
}
上面用到圖片加載工具類,后面會給出
在工具包tools中創(chuàng)建圖片加載工具類GetImageByUrl.java
GetImageByUrl.java
package com.example.wxchatdemo.tools;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* 根據(jù)圖片url路徑獲取圖片
*
*
*
*/
public class GetImageByUrl {
private PicHandler pic_hdl;
private ImageView imgView;
private String url;
/**
* 通過圖片url路徑獲取圖片并顯示到對應(yīng)控件上
*
*
*
*/
public void setImage(ImageView imgView, String url) {
this.url = url;
this.imgView = imgView;
pic_hdl = new PicHandler();
Thread t = new LoadPicThread();
t.start();
}
class LoadPicThread extends Thread {
@Override
public void run() {
Bitmap img = getUrlImage(url);
System.out.println(img + "---");
Message msg = pic_hdl.obtainMessage();
msg.what = 0;
msg.obj = img;
pic_hdl.sendMessage(msg);
}
}
class PicHandler extends Handler {
@Override
public void handleMessage(Message msg) {
Bitmap myimg = (Bitmap) msg.obj;
imgView.setImageBitmap(myimg);
}
}
public Bitmap getUrlImage(String url) {
Bitmap img = null;
try {
URL picurl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) picurl
.openConnection();
conn.setConnectTimeout(6000);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.connect();
InputStream is = conn.getInputStream();
img = BitmapFactory.decodeStream(is);
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return img;
}
}
總結(jié)
到此微信消息頁移動端就完成了,由于服務(wù)端功能還沒實現(xiàn),所以測試時微信消息頁顯示的是空白的,因為ListView對應(yīng)Item布局默認(rèn)是沒有數(shù)據(jù)的,數(shù)據(jù)是從服務(wù)器獲取的,下一篇會完善服務(wù)端功能,也希望大家可以關(guān)注腳本之家其他內(nèi)容!
相關(guān)文章
studio碰到問題:java.lang.UnsatisfiedLinkError解決辦法
這篇文章主要介紹了studio碰到問題:java.lang.UnsatisfiedLinkError解決辦法的相關(guān)資料,需要的朋友可以參考下2017-02-02
android 自定義ScrollView實現(xiàn)背景圖片伸縮的實現(xiàn)代碼及思路
本文純屬個人見解,是對前面學(xué)習(xí)的總結(jié),如有描述不正確的地方還請高手指正~,首先還是按照通例給大家看下示例.2013-05-05
Android使用OKHttp庫實現(xiàn)視頻文件的上傳到服務(wù)器功能
這篇文章主要介紹了Android使用OKHttp庫實現(xiàn)視頻文件的上傳到服務(wù)器功能,需要的朋友可以參考下2018-03-03
Android編程之PopupWindow隱藏及顯示方法示例(showAtLocation,showAsDropDown
這篇文章主要介紹了Android編程之PopupWindow隱藏及顯示方法,結(jié)合實例形式分析了showAtLocation及showAsDropDown方法實現(xiàn)PopupWindow控件隱藏及顯示功能相關(guān)操作技巧,需要的朋友可以參考下2017-02-02
Android Studio 3.1.3升級至3.6.1后舊項目的兼容操作方法
這篇文章主要介紹了Android Studio 3.1.3升級至3.6.1后舊項目的兼容操作方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03
OpenGL ES 矩陣變換及其數(shù)學(xué)原理詳解(五)
這篇文章主要為大家詳細(xì)介紹了OpenGL ES 矩陣變換及其數(shù)學(xué)原理的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-05-05

