安卓应用开发 MyWeChat(二)

  • 往期回顾
  • 项目gitee仓库
  • weixinFragment初步界面效果展示
  • 实现weixinFragment初步界面(RecycleView)
    • 静态消息列表
    • 点击确认已读
    • 下拉刷新
  • 实现weixinFragment界面的滑动置顶与删除效果
    • 添加相应依赖
    • 修改layout_chat_item.xml
    • 修改ChatAdapter.java
    • 修改weixinFragment.java
  • 一些小细节
    • 消息列表的头像图片处理
    • 按钮颜色不能修改的处理

往期回顾

安卓应用开发 MyWeChat(一)

项目gitee仓库

相应项目gitee地址 免费的虎粮shong yi shong 免费的星星点一点

weixinFragment初步界面效果展示

要实现的初步界面效果如下所示:

实现weixinFragment初步界面(RecycleView)

首先实现消息列表与确认已读功能,根据想要完成的效果将整个界面分为三步:静态消息列表、点击确认已读、下拉刷新(由于是静态数据,仅有刷新动效)。


在完成layout_chat_item和fragment_weixin两个xml后需要重写RecycleView.Adapter的ChatAdapter类以及编写weixinFragment的静态数据。

静态消息列表

要实现静态的消息列表,需要先完成单一消息的布局(需要对单一消息设计功能,所以需要区分相应的消息,显然不可能编写总体列表),即layout_chat_item.xml。在winxinFragment中通过获取编写的item显示出消息列表,以下为layout_chat_item.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/layout_chat_item1"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><ImageViewandroid:id="@+id/layout_chat_item_imageView"android:layout_width="70dp"android:layout_height="70dp"android:layout_marginLeft="10dp"android:layout_marginTop="5dp"android:scaleType="centerCrop"tools:srcCompat="@drawable/chat_item_pic0" /><LinearLayoutandroid:id="@+id/layout_chat_item2"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><LinearLayoutandroid:id="@+id/layout_chat_item3"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:id="@+id/layout_chat_item_textView1"android:layout_width="230dp"android:layout_height="wrap_content"android:layout_marginLeft="15dp"android:layout_marginTop="10dp"android:layout_marginBottom="10dp"android:text="TextView1"android:textSize="24sp"android:textStyle="bold" /><TextViewandroid:id="@+id/layout_chat_item_textView3"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="6dp"android:gravity="center_horizontal"android:text="TextView3"android:textSize="12sp" /></LinearLayout><TextViewandroid:id="@+id/layout_chat_item_textView2"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="15dp"android:text="TextView2"android:textSize="16sp" /><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:layout_marginTop="20dp"android:background="@color/black" /></LinearLayout></LinearLayout>


以下为fragment_weixin.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/fragment_chat"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".weixinFragment"><!-- TODO: Update blank fragment layout --><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/fragment_chat_recyclerView"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout>

在ChatAdapter中完成静态数据的获取方法(holder获取再绑定数据)

public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ChatViewHolder> {private Context context;private LayoutInflater mInfalter;private List<Map<String, Object>> data;public ChatAdapter(Context context, List<Map<String, Object>> data) {this.context = context;mInfalter = LayoutInflater.from(context);this.data = data;}@NonNull@Overridepublic ChatViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {return new ChatViewHolder(mInfalter.inflate(R.layout.layout_chat_item, parent, false));}@Overridepublic void onBindViewHolder(@NonNull ChatViewHolder holder, int position) {holder.textView1.setText(data.get(position).get("name").toString());holder.textView2.setText(data.get(position).get("message").toString());holder.textView3.setText(data.get(position).get("time").toString());holder.imageView.setImageResource(Integer.parseInt(data.get(position).get("avatars").toString()));}@Overridepublic int getItemCount() {return data.size();}public class ChatViewHolder extends RecyclerView.ViewHolder {TextView textView1, textView2, textView3;ImageView imageView;LinearLayout linearLayout;public ChatViewHolder(@NonNull View itemView) {super(itemView);textView1 = itemView.findViewById(R.id.layout_chat_item_textView1);textView2 = itemView.findViewById(R.id.layout_chat_item_textView2);textView3 = itemView.findViewById(R.id.layout_chat_item_textView3);imageView = itemView.findViewById(R.id.layout_chat_item_imageView);linearLayout = itemView.findViewById(R.id.layout_chat_item1);}}
}

随后在weixinFragment中加载静态数据

public class weixinFragment extends Fragment {private View view;private RecyclerView fragment_chat_recyclerView;private ChatAdapter chatAdapter;private Context context;private List<Map<String, Object>> chatData = new ArrayList<>();public weixinFragment(Context context) {this.context = context;}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// Inflate the layout for this fragmentview = inflater.inflate(R.layout.fragment_weixin, container, false);fragment_chat_recyclerView = view.findViewById(R.id.fragment_chat_recyclerView);initData();chatAdapter = new ChatAdapter(context, chatData);LinearLayoutManager manager = new LinearLayoutManager(context);manager.setOrientation(RecyclerView.VERTICAL);fragment_chat_recyclerView.setLayoutManager(manager);fragment_chat_recyclerView.setAdapter(chatAdapter);return view;}private void initData() {String[] name = {"Ranni", "Melina", "Ada", "Madeline", "Zelda"};String[] message = {"在吗在吗", "zgm", ": )", "hhh", ": P"};String[] time = {"12:10", "昨天", "3月15日", "01:24", "3月26日"};Integer[] avatars = {R.drawable.chat_item_pic0, R.drawable.chat_item_pic1, R.drawable.chat_item_pic2,R.drawable.chat_item_pic3, R.drawable.chat_item_pic4};for (int i = 0; i < name.length; i++) {HashMap<String, Object> d = new HashMap<>();d.put("name", name[i]);d.put("message", message[i]);d.put("time", time[i]);d.put("avatars", avatars[i]);chatData.add(d);}}
}

至此,weixinFragment页面的静态消息列表已经完成。

点击确认已读

完成静态消息列表后在ChatAdapter的OnBindViewHolder中添加

holder.linearLayout.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {ImageView avatars = view.findViewById(R.id.layout_chat_item_imageView);TextView name = view.findViewById(R.id.layout_chat_item_textView1);TextView message = view.findViewById(R.id.layout_chat_item_textView2);TextView time = view.findViewById(R.id.layout_chat_item_textView3);AlertDialog.Builder builder = new AlertDialog.Builder(context);builder.setIcon(avatars.getDrawable());builder.setTitle(name.getText() + ":");builder.setMessage("Date:" + time.getText() + "\n" + message.getText());builder.setPositiveButton("确认已读",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {}});AlertDialog dialog = builder.create();dialog.show();}});

下拉刷新

在weixinFragment中添加相应依赖(需要在类的函数头添加implements)

public class weixinFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {

随后在类中添加

private SwipeRefreshLayout swipeRefreshLayout;
swipeRefreshLayout = view.findViewById(R.id.fragment_chat_swipeRefreshLayout);
configSwipeRefreshLayout();
private void configSwipeRefreshLayout() {swipeRefreshLayout.setSize(CircularProgressDrawable.LARGE);swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright,android.R.color.system_accent1_200, android.R.color.system_neutral2_300);swipeRefreshLayout.setOnRefreshListener(this);}@Overridepublic void onRefresh() {//延时2snew Handler().postDelayed(new Runnable() {@Overridepublic void run() {swipeRefreshLayout.setRefreshing(false);}}, 3000);}

实现weixinFragment界面的滑动置顶与删除效果

滑动置顶与删除是通过SwipeDelMenuLayout实现的,参考相应文章。

添加相应依赖

首先在setting.gradle中添加JitPack仓库依赖。

repositories {/*...*/maven { url "https://jitpack.io" }}

然后在build.gradle(:app)中添加依赖。

dependencies {/*...*/implementation 'com.github.mcxtzhang:SwipeDelMenuLayout:V1.3.0'
}

修改layout_chat_item.xml

在之前最外层的LinearLayout外再包一层com.mcxtzhang.swipemenulib.SwipeMenuLayout并添加置顶和删除的两个按钮。

<com.mcxtzhang.swipemenulib.SwipeMenuLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"app:ios="false"app:leftSwipe="true"app:swipeEnable="true"android:layout_width="match_parent"android:layout_height="100dp"android:clickable="true"android:paddingBottom="1dp"><!-- 之前的内容 --><!-- 以下都是侧滑菜单的内容依序排列 --><Buttonandroid:id="@+id/btnTop"android:layout_width="100dp"android:layout_height="match_parent"android:background="#d9dee4"android:text="置顶"android:textSize="18sp"android:textColor="@android:color/white"/><Buttonandroid:id="@+id/btnDelete"android:layout_width="100dp"android:layout_height="match_parent"android:background="@color/red_ff4a57"android:text="删除"android:textSize="18sp"android:textColor="@android:color/white"/></com.mcxtzhang.swipemenulib.SwipeMenuLayout>

修改ChatAdapter.java

在ChatViewHolder中添加两个按钮的声明。

 btnDelete = itemView.findViewById(R.id.btnDelete);btnTop = itemView.findViewById(R.id.btnTop);

在onBindViewHolder中添加点击事件。

     //删除按钮holder.btnDelete.setOnClickListener (new View.OnClickListener() {@Overridepublic void onClick(View view) {if (null != mOnSwipeListener) {//如果删除时,不使用mAdapter.notifyItemRemoved(pos),则删除没有动画效果,//且如果想让侧滑菜单同时关闭,需要同时调用 ((CstSwipeDelMenu) holder.itemView).quickClose();//((CstSwipeDelMenu) holder.itemView).quickClose();mOnSwipeListener.onDel(holder.getAdapterPosition());}}});//置顶按钮holder.btnTop.setOnClickListener (new View.OnClickListener() {@Overridepublic void onClick(View view) {if (null!=mOnSwipeListener){mOnSwipeListener.onTop(holder.getAdapterPosition());}}});

在ChatAdapter中添加。

 public interface onSwipeListener {void onDel(int pos);void onTop(int pos);}private onSwipeListener mOnSwipeListener;public onSwipeListener getOnDelListener() {return mOnSwipeListener;}public void setOnDelListener(onSwipeListener mOnDelListener) {this.mOnSwipeListener = mOnDelListener;}

修改weixinFragment.java

在onCreateView中重写setOnDelListener的onDel和onTop方法。

     chatAdapter.setOnDelListener(new ChatAdapter.onSwipeListener(){@Overridepublic void onDel(int pos) {if (pos >= 0 && pos < chatData.size()) {chatData.remove(pos);chatAdapter.notifyItemRemoved(pos);}}@Overridepublic void onTop(int pos) {if (pos > 0 && pos < chatData.size()) {Map map = chatData.get(pos);chatData.remove(map);chatAdapter.notifyItemInserted(0);chatData.add(0, map);chatAdapter.notifyItemRemoved(pos + 1);if (manager.findFirstVisibleItemPosition() == 0) {fragment_chat_recyclerView.scrollToPosition(0);}}}});

至此,想要完成的效果已完成。

一些小细节

消息列表的头像图片处理

ImageView的scaleType属性选择centerCrop,简单来说就是按比例用ImageView的大小居中截取该图片。

android:scaleType="centerCrop"

按钮颜色不能修改的处理

在themes.xml中改成下图所示,按钮颜色就不会是默认颜色了。

安卓应用开发 MyWeChat(二)相关推荐

  1. 安卓应用开发 MyWeChat(一)

    安卓应用开发 MyWeChat(一) 项目gitee仓库 实现MyWeChat初步静态界面 静态界面首部(top) 静态界面底部(bottom) 静态界面中部(fragment) 综合整理静态界面 实 ...

  2. 安卓USB开发教程 二 USB Host

    USB Host(主机模式) 当 Android 设备处于 USB 主机模式时,它充当 USB 主机,为总线供电,并枚举连接的 USB 设备.Android 3.1 及更高版本支持 USB 主机模式. ...

  3. 安卓TV开发(九) Android模拟事件 遥控器变身成鼠标来操作TV

    本文出处:http://blog.csdn.net/sk719887916/article/details/40348853,作者:skay      阅读此文建议先阅读 安卓Tv开发(二)移动智能电 ...

  4. 安卓TV开发(三) 移动智能设备之实现主流TV电视盒子焦点可控UI

    前言:移动智能设备的发展,推动了安卓另一个领域,包括智能电视和智能家居,以及可穿戴设备的大量使用,但是这些设备上的开发并不是和传统手机开发一样,特别是焦点控制和用户操作体验上有很大的区别,本系列博文主 ...

  5. 从零开始安卓端相机功能开发(二)让我们来开发一个相机

    目前已有章节大家可以去学习也可以参考一下 1.从零开始安卓端相机功能开发(一)了解用什么去开发以及流程 2.从零开始安卓端相机功能开发(二)让我们来开发一个相机 3.从零开始开发Android相机ap ...

  6. [安卓开发笔记二]android Studio通过jni调用C++代码

    [安卓开发笔记二]android Studio通过jni调用C++代码 16/12/11 更新 此博客基于安卓android studio 1.5所写,现在已经有了android studio2.2的 ...

  7. 【Vuforia AR Unity 2018.3.12f1】MikuAR安卓程序开发实践(二)MMD篇_2019.4.23

    Unity平台 + Vuforia SDK实现的AR程序开发 !版权声明 项目源码 关于Github项目下载过慢的解决方法 关于Gitee下载报错的问题 一.解析 1 源码目录 2 Unity项目目录 ...

  8. 大疆无人机安卓Mobile Sdk开发(二)连接无人机,获取无人机信息

    大疆无人机安卓Mobile Sdk开发(一)简单介绍 大疆无人机安卓Mobile Sdk开发(二)连接无人机,获取无人机信息 大疆无人机安卓Mobile Sdk开发(三)制定航点任务WaypointM ...

  9. v-html解析的相对地址img 显示不出来_人工智能专题作品解析——APPInventor安卓应用开发AI图像识别简单应用...

    人工智能专题作品解析-- APPInventor安卓应用开发 <AI图像识别简单应用> 本程序使用APPInventor 2019桌面板. 一.思路 平时忙于工作和学习,很少涉猎其它领域的 ...

最新文章

  1. 福利模块功能实现及考勤模块准备
  2. 在哪个公众号学python好_怎么通过公众号来快速学习python编程?
  3. 基础回顾(正则、循环、和、 int和Integer、String /StringBuffer、Array和ArrayList、值传递和引用传递、 Lamda、java8)
  4. shell脚本编译规范(编写第一个脚本,脚本变量的作用,类型 ,了解read命令,let命令,环境变量和预定义变量)
  5. 1869. 哪种连续子字符串更长
  6. 杭电 1233 最小生成树 kruskal()算法
  7. 2 数据源配置_论多数据源(读写分离)的实现方案
  8. IDEA——常用基础设置
  9. 《Linux高性能服务器编程》——2.4 IP路由
  10. cisco路由器基本实验之六 CHAP and RIP (Boson NetSim)
  11. toString和valueOf使得对象访问时显示一个特定格式的字符串,但是可以进行数字运算...
  12. python pip 安装 win10 解决anacoda代理错误 ProxyError: Conda cannot proxy configuration
  13. 同义词转换不再有效_1秒变电脑,手机吃鸡新体验,北通E1键鼠转换器上手体验!...
  14. 20151210编译高通的qca9531的wireless版本 修改版本4
  15. 儿童节特刊 | 如何练好手眼协调能力(手眼标定详解,附源码)
  16. 实名认证失败_身份证在国政通进行实名认证失败怎么办?
  17. Handler之消息屏障你应该知道的
  18. 淘宝开放平台技术历程----学习转载
  19. iPhone手机在Apple启动logo处卡住,无法开机该怎么办?
  20. MySQL中的锁机制、MyISAM表锁、MyISAM表级锁争用情况、MyISAM并发插入Concurrent Inserts、MyISAM的锁调度

热门文章

  1. linux 用谷歌浏览器总是崩溃,谷歌浏览器显示喔唷崩溃啦(谷歌浏览器经常崩溃怎么办)...
  2. 键盘属于计算机主机吗,这是键盘?不,这是一台电脑主机
  3. idea安装及学生邮箱获取一年使用权
  4. Calendar类-日历类常用方法(JAVA)
  5. 太平洋电脑网左边菜单的实现
  6. 各编程语言中的注释格式
  7. MATLAB 数据分析方法(第2版)1.2 MATLAB基础概述
  8. html 注销 按钮,用户登录/注销时隐藏/替换菜单项
  9. kafka搭建,演示
  10. android go 小米1,小米首款Android Go入门机红米Redmi Go发布,1GB+8GB运存