【Android项目开发】聊天功能-主界面设计(对标企业需求)

文章目录

    • 一、引言
    • 二、详细设计
      • 1、解决需求
        • (1)图形问题
        • (2)文本长度问题
        • (3)时间转换问题
      • 2、UI设计
        • (1)主界面
        • (2)适配器
      • 3、Adapter适配器
      • 4、测试参数
    • 三、附录
      • 1、源代码

一、引言

  • 描述:写一个聊天模块UI
  • 需求:
    1、将一个正方形 or 长方形的图片渲染成圆形图片,并且能保持原先的图片内容。
    2、预显示文本要自适应屏幕宽度,不能叠加成两行或者多行,多出的部分可以用"…"表示。
    3、近三天的时间转换为 “上午”、“下午”、“昨天”、“前天”。
  • 难度:初级
  • 知识点:
    1、简单的按需时间转换算法
    2、Adapter适配器的使用
    3、继承ImageView重写方法
  • 效果图

在这里插入图片描述

优化后的界面

在这里插入图片描述

二、详细设计

1、解决需求

(1)图形问题

创建一个类CircleImageView继承ImageView,通过Canvas进行图形操作

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;public class CircleImageView extends ImageView {private Paint paint; // 画笔private int radius; // 半径private float scale; // 缩放比例public CircleImageView(Context context) {super(context);}public CircleImageView(Context context, AttributeSet attrs) {super(context, attrs);}public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);// 宽高保持一致int size = Math.min(getMeasuredWidth(), getMeasuredHeight());radius = size / 2;setMeasuredDimension(size, size);}@Overrideprotected void onDraw(Canvas canvas) {paint = new Paint();Bitmap bitmap = drawableToBitmap(getDrawable());// 初始化BitmapShaderBitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);// 缩放比例scale = (radius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());Matrix matrix = new Matrix();matrix.setScale(scale, scale);bitmapShader.setLocalMatrix(matrix);paint.setShader(bitmapShader);// 圆形操作 定中心点坐标、半径、画笔canvas.drawCircle(radius, radius, radius, paint);}/*** Drawable转 BitMap* @param drawable* @return*/private Bitmap drawableToBitmap(Drawable drawable) {if (drawable instanceof BitmapDrawable) {BitmapDrawable bd = (BitmapDrawable) drawable;return bd.getBitmap();}int w = drawable.getIntrinsicWidth();int h = drawable.getIntrinsicHeight();Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);drawable.setBounds(0, 0, w, h);drawable.draw(canvas);return bitmap;}}

(2)文本长度问题

	// 获取手机屏幕宽度,建议是放在主函数里,只计算一遍// WindowManager manager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);// int width = manager.getDefaultDisplay().getWidth();/*** 防止文本过长,影响UI美观* @param text* @return*/private String handleText(String text) {int endIndex = width/90;// 根据屏幕宽度,截取预显示文字String string = text;if (string.length() > endIndex) {string = string.substring(0, endIndex) + "...";}return string;}

(3)时间转换问题

	/*** 时间转换                  Calendar ca = Calendar.getInstance();* @param mYear 获取系统年   ca.get(Calendar.YEAR)* @param mMonth 获取系统月  ca.get(Calendar.MONTH) + 1* @param mDay 获取系统日    ca.get(Calendar.DAY_OF_MONTH)* @param time chat.getTime()* @return*/private String algTime(int mYear, int mMonth, int mDay, String time) {String temp = "";// 切割时间 例:2023-6-2 9:00String[] times = time.split(" ");// 判断时间正确性if (times.length == 2) {String[] strings = times[0].split("\\-");int year = Integer.valueOf(strings[0]);int month = Integer.valueOf(strings[1]);int day = Integer.valueOf(strings[2]);// 如果日期为每月前两天,则需要欠上一个月int d;if (mMonth - month == 1 && mDay < 3) {d = mDay + algDay(year, month) - day;} else {d = mDay - day;}if (year == mYear && mMonth - month < 2  && d < 3) {  // 判断年月String[] mHour = times[1].split("\\:");switch (d) {case 0:if (Integer.valueOf(mHour[0]) <= 12) {temp += "上午 " + times[1];} else {temp += "下午 " + (Integer.valueOf(mHour[0]) - 12) + ":" + mHour[1];}break;case 1:temp = "昨天 " + times[1];break;case 2:temp = "前天 " + times[1];break;default:break;}} else {temp = times[0];}}return temp;}/*** 计算:当前年月的天数* @param year* @param month* @return*/private int algDay(int year, int month) {boolean isRunYear;int day = 0;// 判断是否为闰年if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {isRunYear = true;} else {isRunYear = false;}// 判断月份if (month > 0 && month < 13) {if (month != 2) {switch (month) {case 1:case 3:case 5:case 7:case 8:case 10:case 12:day = 31;break;case 4:case 6:case 9:case 11:day = 30;break;default:break;}} else {if (isRunYear) {day = 29;} else {day = 28;}}}return day;}

2、UI设计

(1)主界面

在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:padding="10dp"android:background="#F0F0F0"><com.hngy.xpq.chatdemo.view.CircleImageViewandroid:layout_width="45dp"android:layout_height="45dp"android:layout_marginTop="20dp"android:src="@drawable/index"/><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="20dp"android:layout_marginTop="20dp"android:orientation="vertical"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="云端new守夜人"android:textSize="14dp"android:textStyle="bold"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:text="[5G在线]"android:textSize="12dp"/></LinearLayout></LinearLayout><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/chat"android:layout_width="match_parent"android:layout_height="wrap_content"android:paddingLeft="8dp"android:paddingRight="8dp"android:background="#FFF"/></LinearLayout>

(2)适配器

在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="10dp"android:orientation="horizontal"><com.hngy.xpq.chatdemo.view.CircleImageViewandroid:id="@+id/chatImage"android:layout_width="60dp"android:layout_height="60dp"android:src="@drawable/c"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:layout_marginLeft="20dp"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:id="@+id/chatName"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="20dp"android:textStyle="bold"android:text="学习群"/><TextViewandroid:id="@+id/chatTime"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="right"android:text="上午 9:00"/></LinearLayout><TextViewandroid:id="@+id/chatText"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="14dp"android:text="许...:小卷不是卷"/></LinearLayout></LinearLayout>

3、Adapter适配器

老是将重复的代码粘贴进来,就显得博客很水,那么学习地址:http://t.csdn.cn/fdLea

4、测试参数

	private List<Chat> getListChat() {// 获取聊天数据(本地数据获取<推荐> or 服务器数据获取)// 图片按道理应该是String -> 存储地址 or Url -> 网络地址,这里使用drawable取代List<Chat> list = new ArrayList<>();Chat chat1 = new Chat((long) 1001, String.valueOf(R.drawable.d), "学习群", "许...:小卷不算卷", "2023-6-2 9:00");list.add(chat1);Chat chat2 = new Chat((long) 1002, String.valueOf(R.drawable.a), "Man", "Man:儿子,吃饭没?", "2023-6-2 18:00");list.add(chat2);Chat chat3 = new Chat((long) 1003, String.valueOf(R.drawable.b), "Dad", "Dad:过的怎么样,没人欺负你吧.有什么事,都和我说.", "2023-6-1 21:00");list.add(chat3);Chat chat4 = new Chat((long) 1004, String.valueOf(R.drawable.c), "导师", "收到", "2023-5-31 18:10");list.add(chat4);Chat chat5 = new Chat((long) 1005, String.valueOf(R.drawable.c), "导师2-测试时间计算", "收到", "2023-5-30 18:10");list.add(chat5);// 获取系统时间Calendar ca = Calendar.getInstance();int mYear = ca.get(Calendar.YEAR);int mMonth = ca.get(Calendar.MONTH) + 1;int mDay = ca.get(Calendar.DAY_OF_MONTH);// 处理数据for (Chat c:list) {c.setTime(algTime(mYear, mMonth, mDay, c.getTime()));}return list;}

三、附录

1、源代码

下载地址:https://download.csdn.net/download/weixin_48916759/87855518

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/50466.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件建模概述 UML模型图

软件建模 什么是软件建模 将想法通过模型可视化地表达出来&#xff0c;方便记忆和进一步分析&#xff0c;方便团队/同事交流&#xff0c;口语交流容易失真。 软件建模体现了软件设计的思想&#xff0c;在需求和实现之间架起了一座桥梁&#xff0c;通过模型指导软件系统的具体…

ChatGPT-4竟已经学会说谎——聪明又危险的AI

时间回到2023年3月&#xff0c;OpenAI正式发表GPT-4的最新模型&#xff0c;除了展示聊天机器人如何完成各种任务&#xff0c;还在官网发了一份90多页报告&#xff0c;提及各项特性与可能存在的风险。同时&#xff0c;OpenAI为了检测它可能带来的“潜在的威胁”&#xff0c;而让…

前 Twitter CEO 炮轰 Web 3,马斯克也来“掺和一脚”

前 Twitter CEO 的 Jack Dorsey 今日又登上了外网头条&#xff0c;但与上个月宣布辞任时的祝福不同&#xff0c;这次 Jack Dorsey 引起了很大的争议&#xff1a;他连续发推批评 Web 3 及加密风投&#xff0c;引得许多加密行业人士不满并反驳。 “你们并不拥有 Web 3&#xff0…

马斯克特斯拉内部邮件火了:痛恨开会,少说黑话

金磊 羿阁 发自 凹非寺量子位 | 公众号 QbitAI 马斯克给员工的一封内部邮件火了。 鼓励员工拒绝开会、公司规定不合理可以不遵守……俨然一个为员工着想的好老板。 一开始人们还奇怪马斯克的画风怎么变这么快&#xff0c;后来才发现原来这是他6年前写的。 对象也不是推特员工&a…

对csdn inscode产品对工作3年内的程序员的体验改进与思考

前言&#xff1a; inscode 的初衷就 在线IDE运行环境 ai辅助 &#xff0c;能够通过云原生运行项目&#xff0c;帮助用户实现分享和学习创意。 InsCode支持AI编程,代码提问 、添加注释、优化代码应有尽有 inscode slogan 让你的灵感立刻落地 编程可以很有趣 InsCode 是一个无需…

20+ Prompt工具网站汇总;我用AI工具开了一家「无人公司」;如何10分钟上线一个AI导航网站;第一部AIGC中英双语图文辞典 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 『MidJourney Prompt工具网站』加速生成与优化&#xff0c;持续更新中 ShowMeAI知识星球 | 资源标签&#xff1a;找工具 这是一个总结…

百度正式推出“文心一言”

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 备受瞩目的中国版ChatGPT&#xff0c;百度“文心一言”今日正式发布了。由百度老大李彦宏亲自主持&#xff0c;亲自讲解。可见“文心一言”已经在百度得到了举足轻重的地位。 也是从3月16日起&am…

百度语音接口调用详解

1.获取的API Key及Secret Key 1.1 在控制台中选择语音 1.2 进入到如下界面进行创建应用(“接口选择”这一项不用填写) 1.3 创建应用之后在“应用列表”中查看对应应用的AppID、API Key、Secret Key的值。 2.调用接口 2.1 pycharm中新建一个python文件(voice1.py)&#xff0c;…

API网关|JD|pinduoduoAPI接入

API网关是什么 在日常工作中&#xff0c;不同的场合下&#xff0c;我们可能听说过很多次网关这个名称&#xff0c;这里说的网关特指API网关&#xff08;API Gataway&#xff09;。字面意思是指将所有API的调用统一接入API网关层&#xff0c;由网关层负责接入和输出。 那么在什…

主控全志R58-百度小度在家智能音箱拆解

*本文转自我爱音频网 作为一个还处于萌芽阶段的产品&#xff0c;近期智能音箱迎来了一种新的形态演化阶段&#xff0c;市面上不断出现像亚马逊Echo Show、京东叮咚Play等搭载触摸显示屏的智能音箱&#xff0c;屏幕的加入&#xff0c;让音箱的交互逐渐变得更加变得可视化&#…

拥有自我意识的AI:AutoGPT | 得物技术

1.引言 ChatGPT在当下已经风靡一时&#xff0c;作为自然语言处理模型的佼佼者&#xff0c;ChatGPT的优势在于其能够生成流畅、连贯的对话&#xff0c;同时还能够理解上下文并根据上下文进行回答。针对不同的应用场景可以进行快速定制&#xff0c;例如&#xff0c;在客服、教育…

移动端IM产品RainbowChat[专业版] iOS端 v6.0版已发布!

关于MobileIMSDK MobileIMSDK 是一套专门为移动端开发的开源IM即时通讯框架&#xff0c;超轻量级、高度提炼&#xff0c;一套API优雅支持UDP 、TCP 、WebSocket 三种协议&#xff0c;支持iOS、Android、H5、标准Java平台&#xff0c;服务端基于Netty编写。 工程开源地址是&…

Android与IOS的相爱相杀之客户端测试

一、Android Android 是google公司主导的一个开放的手机操作系统&#xff0c;不过目前已经超过了手机的局限&#xff0c;而定位于移动设备的操作系统。目前用于手机,平板,智能电视,智能导航,智能手环,智能眼镜以及智能家居设备 底层以Linux内核工作为基础&#xff0c;由C语言开…

[iPhone高级] 基于XMPP的IOS聊天客户端程序(IOS端三)

前两篇介绍了如何通过XMPP来发送消息和接收消息,这一篇我们主要介绍如何来美化我们的聊天程序,看一下最终效果呢,当然源程序也会在最后放出 好了,我们来看一下我们写的程序 这里我们自定义了TableViewCell 一行是显示发布日期,一行是显示发送的消息,还有一个是背景 -(id…

写综述如何降低查重率?

经过好几个月的打磨&#xff0c;论文终于写完了&#xff0c;你以为这就完事了&#xff1f;MO!下面就来到了很重要的一步——查重。很多小伙伴写完后还蛮开心的&#xff0c;可是看到这查重率&#xff0c;很多人是欲哭无泪。辛辛苦苦写的综述怎可重复率那么高&#xff01;重复率过…

多智能体强化学习-G2ANet

Multi-Agent Game Abstraction via Graph Attention Neural Network 论文地址 代码地址 摘要 本文通过一个完整的图来建模智能体之间的关系&#xff0c;并创新性地提出一种基于两阶段注意力网络&#xff08;G2ANet&#xff09;的游戏抽象机制&#xff0c;表明两个智能体之间…

chatgpt赋能python:Python画轨迹图:认识、用法与优势

Python画轨迹图: 认识、用法与优势 Python的数据可视化能力十分强大。画图工具虽然千千万&#xff0c;但其中&#xff0c;轨迹图是同时准确又美观的图形表现。本文将向读者介绍Python画轨迹图的好处、如何使用以及如何在项目合适的地方使用轨迹图。 了解Python轨迹图 为了更…

爬取古诗文网的推荐古诗

爬取古诗文网的推荐古诗 思路分析完整代码结果展示 思路分析 本次的主要目的是练习使用正则表达式提取网页中的数据。 该网站的推荐古诗文一共有10页&#xff0c;页码可以在URL中进行控制&#xff0c;比如说&#xff0c;下面的URL指的是第一页。 https://www.gushiwen.org/def…

Python程序写诗【训练1分钟】古诗生成

原创AI程序写诗&#xff1a;训练 一分钟&#xff0c;诗词一秒成&#xff01; 先看看写出来什么诗~ 文章目录 来看看程序语料下载地址关于程序的一些基础更多诗词创作山水田园宫廷别塞战争抒情春节 来看看程序 from gensim.models import Word2Vec # 词向量 from random impor…

最全中华古诗词数据库,收录30多万诗词

诗词诗人数据库 mysql文件 收录13136个诗人 305131个诗词&#xff0c;还有诗词赏析和注解等&#xff0c;需要的同学可以下载 可以搜索微信小程序 诗词成语大全 看数据效果 下载地址 人们习惯用史料来描述文学史的高峰状态&#xff0c;而在当今大数据时代&#xff0c;我们或可尝…