android 仿微信demo——微信消息界面实现(移动端)
在上一篇中主界面实现说过微信四个页面中间都是是fragment的,并且四个fragment的布局都还没实现,所以这一篇主要实现微信消息界面的实现(第一个fragment)
微信消息页是可以上下滑动,每一个列表最多都有可显示五个数据,还可以点击列表
要实现上诉功能只需要在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'> <ListViewandroid: 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>
上述代码自定义了一个分割线
微信消息页每一个列表都有分割线,而系统自带的分割线是充满屏幕宽度的,所以要自己定义一个分割线
自定义分割线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' > <itemandroid:left='80dp'android:right='0dp'><shape android:shape='rectangle' > <solid android:color='#33000000' /></shape> </item></layer-list>
创建微信消息界面fragment中ListView对应的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'> <ImageViewandroid: android:layout_width='20dp'android:layout_height='wrap_content'android:layout_weight='0.5'/> <LinearLayoutandroid:orientation='vertical'android:layout_marginLeft='23dp'android:layout_width='8dp'android:layout_height='match_parent'android:layout_weight='4'><TextView android: 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: 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> <LinearLayoutandroid:layout_width='wrap_content'android:layout_height='match_parent'android:paddingRight='-50dp'android:layout_weight='1'android:gravity='right'android:orientation='vertical'><TextView android: 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: 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; // 创建集合用于存储服务器发来的显示微信消息列表的一些信息 private List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); //自定义的一个Hander消息机制 private MyHander myhander = new MyHander(); /*有参构造方法,参数为微信号*/ @SuppressLint('ValidFragment') WeixinFragment(String number) {this.number = number; } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {// 开一个线程完成网络请求操作Thread thread1 = new Thread(new Runnable() { @Override public void run() {httpUrlConnPost(String.valueOf(number)); }});thread1.start();/*等待网络请求线程完成*/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);//创建自定义的适配器,用于把数据显示在组件上BaseAdapter adapter = new ImageAdapter(getActivity().getApplicationContext(), list);//设置适配器listView.setAdapter(adapter);return view; } // 1.编写一个发送请求的方法 // 发送请求的主要方法 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函数,作用于所有的URLConnection对象。 urlConnection.setInstanceFollowRedirects(true);// 是成员函数,仅作用于当前函数,设置这个连接是否可以被重定向 urlConnection.setReadTimeout(3000);// 响应的超时时间 urlConnection.setDoInput(true);// 设置这个连接是否可以写入数据 urlConnection.setDoOutput(true);// 设置这个连接是否可以输出数据 urlConnection.setRequestMethod('POST');// 设置请求的方式 urlConnection.setRequestProperty('Content-Type', 'application/json;charset=UTF-8');// 设置消息的类型 urlConnection.connect();// 连接,从上述至此的配置必须要在connect之前完成,实际上它只是建立了一个与服务器的TCP连接 JSONObject json = new JSONObject();// 创建json对象 //json.put('title', URLEncoder.encode(title, 'UTF-8'));// 使用URLEncoder.encode对特殊和不可见字符进行编码 json.put('number', URLEncoder.encode(number, 'UTF-8'));// 把数据put进json对象中 String jsonstr = json.toString();// 把JSON对象按JSON的编码格式转换为字符串 // ------------字符流写入数据------------ OutputStream out = urlConnection.getOutputStream();// 输出流,用来发送请求,http请求实际上直到这个函数里面才正式发送出去 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));// 创建字符流对象并用高效缓冲流包装它,便获得最高的效率,发送的是字符串推荐用字符流,其它数据就用字节流 bw.write(jsonstr);// 把json字符串写入缓冲区中 bw.flush();// 刷新缓冲区,把数据发送出去,这步很重要 out.close(); bw.close();// 使用完关闭 Log.i('aa', urlConnection.getResponseCode() + ''); //以下判?嗍欠裨L??成功,如果返回的状态码是200则说明访问成功 if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {// 得到服务端的返回码是否连接成功// ------------字符流读取服务端返回的数据------------InputStream in = urlConnection.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(in));String str = null;StringBuffer buffer = new StringBuffer();while ((str = br.readLine()) != null) {// BufferedReader特有功能,一次读取一行数据 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('rn');String str2 = rjson.getJSONObject('json').get('title').toString();String[] title = str2.split('rn');String str3 = rjson.getJSONObject('json').get('content').toString();String[] content = str3.split('rn');String str4 = rjson.getJSONObject('json').get('time').toString();String[] time = str4.split('rn');String str5 = rjson.getJSONObject('json').get('showcode').toString();String[] pic2 = str5.split('rn');for (int i = 0; i < pic.length; i++) { Map<String, Object> map = new HashMap<String, Object>(); map.put('pic', pic[i]); System.out.println('网址:' + pic[i]); map.put('title', title[i]); System.out.println('网址:' + 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'的数据,这里服务端返回的是一个boolean类型的数据System.out.println('json:===' + result);//如果服务器端返回的是true,则说明跳转微信页成功,跳转微信页失败if (result) {// 判断结果是否正确 //在Android中http请求,必须放到线程中去作请求,但是在线程中不可以直接修改UI,只能通过hander机制来完成对UI的操作 myhander.sendEmptyMessage(1); Log.i('用户:', '跳转微信页成功');} else { myhander.sendEmptyMessage(2); System.out.println('222222222222222'); Log.i('用户:', '跳转微信页失败');} } else {myhander.sendEmptyMessage(2); }} catch (Exception e) { e.printStackTrace(); Log.i('aa', e.toString()); System.out.println('11111111111111111'); myhander.sendEmptyMessage(2);} finally { urlConnection.disconnect();// 使用完关闭TCP连接,释放资源} } // 在Android中不可以在线程中直接修改UI,只能借助Handler机制来完成对UI的操作 class MyHander extends Handler {@Overridepublic void handleMessage(Message msg) { super.handleMessage(msg); //判断hander的内容是什么,如果是1则说明跳转微信页成功,如果是2说明跳转微信页失败 switch (msg.what) {case 1: Log.i('aa', msg.what + ''); break;case 2: Log.i('aa', msg.what + ''); }} }}
上述代码具体的内容就不阐述了,代码都有注释。主要说一下上面给ListView设置适配器,它是自定义的适配器,通过继承系统自带适配器BaseAdapter,重写相应方法,把数据显示在LlistView对应的item布局相应组件上,至于为什么要自定义,因为微信消息页每一个列表都有至少两个图片数据,而要把图片加载到组件上需要用到工具类(后面会给出)
上面fragment.java代码自定义了一个适配器,现在就来创建它,创建之前,可以先创建包单独存放适配器,方便管理;
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 { // 要显示的数据的集合 private List<Map<String, Object>> data; // 接受上下文 private Context context; // 声明内部类对象 private ViewHolder viewHolder; public ImageAdapter(Context context, List<Map<String, Object>> data) {this.context = context;this.data = data; } // 返回的总个数 @Override public int getCount() {// TODO Auto-generated method stubreturn data.size(); } // 返回每个条目对应的数据 @Override public Object getItem(int position) {// TODO Auto-generated method stubreturn data.get(position); } // 返回的id @Override public long getItemId(int position) {// TODO Auto-generated method stubreturn position; } // 返回这个条目对应的控件对象 @Override public View getView(int position, View convertView, ViewGroup parent) {// 判断当前条目是否为nullif (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();// 这里调用了图片加载工具类的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();// 这里调用了图片加载工具类的setImage方法将图片直接显示到控件上GetImageByUrl getImageByUrl2 = new GetImageByUrl();getImageByUrl2.setImage(viewHolder.code, code);return convertView; } /** * 内部类 记录单个条目中所有属性 * * * */ class ViewHolder {public ImageView img1;public TextView title;public TextView content;public TextView time;public ImageView code; }}
上面用到图片加载工具类,后面会给出
在工具包tools中创建图片加载工具类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;/** * 根据图片url路径获取图片 * * * */public class GetImageByUrl { private PicHandler pic_hdl; private ImageView imgView; private String url; /** * 通过图片url路径获取图片并显示到对应控件上 * * * */ 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 {@Overridepublic 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 {@Overridepublic 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; }}总结
到此微信消息页移动端就完成了,由于服务端功能还没实现,所以测试时微信消息页显示的是空白的,因为ListView对应Item布局默认是没有数据的,数据是从服务器获取的,下一篇会完善服务端功能,也希望大家可以关注好吧啦网其他内容!
相关文章: