android 仿微信demo—微信消息界面实现(移动端)【转载】

462 阅读8分钟

android 仿微信demo————微信启动界面实现

android 仿微信demo————注册功能实现(移动端)

android 仿微信demo————注册功能实现(服务端)

android 仿微信demo————登录功能实现(移动端)

android 仿微信demo————登录功能实现(服务端)

android 仿微信demo————微信主界面实现

android 仿微信demo————微信消息界面实现(移动端)

android 仿微信demo————微信消息界面实现(服务端)

android 仿微信demo————微信通讯录界面功能实现(移动端,服务端)

android 仿微信demo————微信发现界面实现

android 仿微信demo————微信顶部操作栏界面实现

android 仿微信demo————微信顶部操作栏搜索按钮实现(查询通讯录好友功能)

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">
    <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>

上述代码自定义了一个分割线

微信消息页每一个列表都有分割线,而系统自带的分割线是充满屏幕宽度的,所以要自己定义一个分割线

自定义分割线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>

创建微信消息界面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">
    <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;
    // 创建集合用于存储服务器发来的显示微信消息列表的一些信息
    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() + "");
            //以下判斷是否訪問成功,如果返回的状态码是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("\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("网址:" + 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 {
        @Override
        public 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 stub
        return data.size();
    }

    // 返回每个条目对应的数据
    @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;
    }

    // 返回这个条目对应的控件对象
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // 判断当前条目是否为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();
        // 这里调用了图片加载工具类的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 {
        @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;
    }
}

到此微信消息页移动端就完成了,由于服务端功能还没实现,所以测试时微信消息页显示的是空白的,因为ListView对应Item布局默认是没有数据的,数据是从服务器获取的,下一篇会完善服务端功能

本文转自 blog.csdn.net/weixin_4276…,如有侵权,请联系删除。