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布局默认是没有数据的,数据是从服务器获取的,下一篇会完善服务端功能,也希望大家可以关注我们其他内容!

(0)

相关推荐

  • Android仿微信语音消息的录制和播放功能

    一.简述 效果: 实现功能: 长按Button时改变Button显示文字,弹出Dialog(动态更新音量),动态生成录音文件,开始录音: 监听手指动作,规定区域.录音状态下手指划出规定区域取消录音,删除生成的录音文件: 监听手指动作.当手指抬起时,判断是否开始录音,录音时长是否过短,符合条件则提示录音时长过短:正常结束时通过回调返回该次录音的文件路径和时长. 4.点击录音列表的item时,播放动画,播放对应的音频文件. 主要用到4个核心类: 自定义录音按钮(AudioRecordButton):

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

    目录 服务端微信消息页实现 测试 总结 上一篇实现了移动端微信消息界面功能,以此为基础继续完善服务端功能 服务端微信消息页实现 微信消息界面的实现,和登录,注册是类似的,无非就是接受客户端数据,然后通过这个数据去数据库查找,如果查得到话,返回相应值给客户端. 在移动端中,当用户输入表单后点击登陆,如果登陆成功,则会把微信号通过Itent传给主界面activity,而在微信主界面点击微信消息界面时,会把微信号作为fragment的参数传给微信消息界面,然后通过把微信号数据发送给服务器,服务器接受到

  • Android实现类似qq微信消息悬浮窗通知功能

    实现方法:(需要开启悬浮窗通知权限.允许应用在其他应用上显示) 一.利用headsup 悬挂式Notification,他是5.0中新增的,也就是API中的Headsup的Notification,可以在不打断用户操作的时候,给用户通知 二.使用Window创建悬浮窗 当window属性设置为FLAGE_NOT_FOCUSABLE表示不需要获取焦点,也不需要接受各种输入事件,此标记会同时启用FLAGE_NOT_TOUCH_MODEL,最终事件会直接传递给下层具有焦点的Widow FLAGE_NO

  • Android采用消息推送实现类似微信视频接听

    本文实例为大家分享了Android实现类似微信视频接听的具体代码,供大家参考,具体内容如下 1.背景需求:业务需要接入视频审核功能,在PC 端发起视频通话,移动端显示通话界面点击接听后进行1对1视频通话. 2.解决方案:因为项目没有IM功能.只集成了极光消息推送(极光消息推送接入参考官方文档,经过跟需求沟通,采用消息推送调起通话接听界面.再集成腾讯实时音视频SDK(具体集成方式参考官方文档).最终实现类似微信1对1通话功能. 3.技术实现: A:编写一个广播接收器,并且在 AndroidMani

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

    目录 移动端微信通讯录界面功能实现 服务端微信通讯录界面功能实现 测试 总结 前面我们实现了微信消息界面的实现,这篇继续完善微信功能,实现微信通讯录界面 移动端微信通讯录界面功能实现 微信通讯录,头部是四个标签(不进行分组),下面是好友信息且根据呢称首字母进行排序分组,底部还统计了好友个数,右边是一组英文字母导航,可滑动并且还可以点击跳转到相应的分组 微信好友和顶部的四个标签,可以用ListViw实现并指定一个item布局,分组效果只需要在代码段进行判断即可 右边的字母操作行可以自定义一个组件继

  • Android仿硬币转动微信红包动画效果

    项目需要研究了一下微信红包动画,即硬币转动的效果,原理其实就是三张不同角度的图片利用AnimationDrawable帧动画进行播放,在参考了案例之后,给自己记录一下完成的过程. 1,在XML文件中定义动画: 步骤如下: ①新建 Android 项目 ②在drawable目录中新建一个anim.xml(注意文件名小写) <?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:andr

  • android 仿ios数字密码解锁界面的实例

    如下所示: 每个Android开发人员都知道,现在android的解锁最常用的就是九宫格解锁,ios的解锁常用的是数字密码解锁.而我们在开发工程中,很多时候,都需要android和ios进行结合.有的时候我们就需要把我们的解锁界面弄成像ios一样的数字键盘. 这里我就实现了一个仿照ios的数字密码解锁界面.在这里我采用了两种方式来实现,第一种就是使用自定义控件的形式,第二种就是使用我们的布局来实现的.这里我就着重讲一下使用自定义控件形式实现的思路.至于使用布局文件实现的方式,我就不进行具体的讲解

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

    目录 移动端微信消息页实现 总结 移动端微信消息页实现 在上一篇中主界面实现说过微信四个页面中间都是是fragment的,并且四个fragment的布局都还没实现,所以这一篇主要实现微信消息界面的实现(第一个fragment) 微信消息页是可以上下滑动,每一个列表最多都有可显示五个数据,还可以点击列表 要实现上诉功能只需要在fragment布局中使用ListView,然后给ListView指定一个Item布局即可 修改微信消息界面fragment布局 weixin_fragment.xml <L

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

    以往文章中实现微信启动页,登录注册功能,此基础上继续完善仿微信功能. 主界面实现 (1)整体采用RelativeLayout相对布局 (2)最上面是toolbar操作栏,搜索框SearchView,Overflow(含有4个单选菜单项) (3)中间使用Fragment组件(不使用ViewPager,有兴趣可以自己添加实现下). (4)最下面是水平的LinearLayout线性布局:含有4个自定义的控件 这一篇主要是实现主界面,其他像顶部(toolbar,SearchView,Overflow),

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

    微信启动界面 创建项目 android studio创建移动端项目 微信启动界面实现 当第一次点击微信时会看到微信出现启动界面(不包括两个按钮)停留大概一秒的时间,然后才进入包括两个按钮的启动界面.按钮在没有获取和获取焦点时都有不同的图片显示,所以下面要实现这些功能 创建两个activity其对应的布局,一个activity显示停留的界面(布局就是一张图片),另一个activity显示真正的启动界面(布局包括图片及两个按钮),创建两个selector文件实现按钮在没有获取和获取焦点时显示不同图片

  • Android仿QQ未读消息--红点拖拽删除【源代码】

    本Demo是一款仿qq未读消息拖拽删除的例子,继承RelativeLayout的WaterDrop实现了圆形图标功能.继承ImageView的CircleImageView圆形图片功能.效果非常不错.很适合有圆形设计的哥们.效果图片如下 CircleImageView核心代码 private void updateShaderMatrix() { float scale; float dx = 0; float dy = 0; mShaderMatrix.set(null); if (mBitm

  • Android仿iOS侧滑退出当前界面功能

    我们都知道在ios手机上面,有一个侧滑退出当前界面的功能,但是在安卓手机上系统没有给我们提供这样的功能,但是这依然阻挡不了强大的安卓的定制功能,我们完全可以自己定制一套这样的功能. 首先看下效果图: 分析: (1)要想模仿ios的这种效果,因为我们通过手指的滑动,所以这里肯定跟我们的滑动事件有关系(onInterceptTouchEvent,onTouchEvent这两个方法的关系,如果不清楚,请直接查阅事件传递机制原理) (2)我们要想直接拦截我们的所有触摸事件,我们可以在上层父级布局中进行拦

  • Android仿QQ、微信聊天界面长按提示框效果

    先来看看效果图 如何使用 示例代码 PromptViewHelper pvHelper = new PromptViewHelper(mActivity); pvHelper.setPromptViewManager(new ChatPromptViewManager(mActivity)); pvHelper.addPrompt(holder.itemView.findViewById(R.id.textview_content)); 使用起来还是很简单的 首先new一个PromptViewH

随机推荐