【07】AI辅助编程完整的安卓二次商业实战-字体大小调整-跳转重影bug修复-替换剩余图标以及打包apk-优雅草卓伊凡 引言本次二开布局没有变,但是下一次整体布局会有变,不过本次开发发现朋友圈跳转功能的流程步骤也做了一定的变化。原生项目复杂就复杂于就算一个颜色的改动可能都比较麻烦,不像普通web项目或者vue项目,其次原生项目安卓Android的环境配置是很复杂的,很多人 第一步可以搞一周 甚至一个月都搞不成功,再次之前说了可以用trae辅助我们编程,但是真正的开发和调试还是得Android studio 离开Android studio 原生安卓项目也是没法运行的,至少trae满足不了,vs要满足也比较麻烦,本篇改颜色和主页图标,本项目代码 毫不夸张的说 就是WhatsApp的初期代码,历史大概有15年了。 本篇【07】核心重点还有最后那个步骤也就是打包,然后本次ui改版和细微细微调整暂时告一段落,下一步后面8开始就是真正很复杂的的二次开发功能开发了,届时卓伊凡分享 项目技术栈优雅草蜻蜓I即时通讯水银版 - 技术栈列表概述:本项目是一个基于微服务架构的现代即时通讯解决方案。2025年8月进行了大规模技术升级与重构,并于8-9月期间集中进行兼容性调整与Bug修复,旨在提升系统稳定性、可维护性和未来扩展性。 一、 移动客户端 (Android)- 开发语言: Java
- 开发模式: 原生开发
- 兼容性底座: 最低支持 Android API 5 (Android 5.0)
- 核心框架升级:
- 项目已从原生的 Android Support 库全面升级到 AndroidX,以获得更好的性能和维护性。
- 推送集成:
- 集成 极光推送 (JPush) SDK,用于处理应用在后台或进程被杀时的消息离线推送。
二、 服务端 (Backend)- 核心语言: Java
- 主要框架: Spring Boot
- 用于构建和编排所有业务逻辑和业务流程,提供RESTful API接口,是连接各个微服务的核心枢纽。
- JDK 版本:
- 当前版本: JDK 1.8
- 未来计划: 已有明确计划升级至 JDK 17(因时间安排暂未执行,旨在获得新的语言特性和性能提升)。
三、 微服务与基础设施 (Microservices & Infrastructure)本次升级的核心是将单体服务拆解为独立、可扩展的微服务。 即时通讯服务: - 协议: XMPP (Extensible Messaging and Presence Protocol)
- 实现: 独立部署的 XMPP 服务,负责最核心的点对点、群组聊天等实时消息分发。
消息回执服务: - 实现: Tigase Server 7.1.3
- 职责: 专门处理消息的已发送、已送达、已阅读等状态回执,确保消息的可达性。
消息队列服务: - 组件: RocketMQ 4.3.2 (rocketmq-all-4.3.2)
- 职责: 处理服务间的异步通信、流量削峰、任务队列等,保证系统的高可用和高性能。
上传服务: - 实现: 独立制作的 Upload 服务
- 职责: 专门处理图片、文件、语音等附件的上传、存储和管理,与主业务逻辑解耦。
推送服务: - 实现: 独立制作的 Push 服务
- 集成: 内部封装了 极光推送 SDK,负责将消息通过系统通道推送给Android客户端。
缓存与队列服务: - 组件: Redis
- 职责: 用作高速缓存,提升访问速度;同时处理临时消息队列和会话状态存储。
四、 数据存储 (Data Storage)主数据库: - 组件: MongoDB
- 版本升级: 已从旧的 3.4.0 成功升级至 4.0 版本。
- 用途: 存储非结构化的聊天记录、用户动态、群组信息等海量数据,利用其灵活的Schema特性适应IM业务的快速迭代。
关系型数据库: - 可能选项: MySQL8.0 下一步做改进的。
- 可能用途: 存储用户账户、好友关系、群组列表等结构化数据。
总结与技术亮点- 架构现代化: 从可能存在的单体架构成功转型为微服务架构,服务间通过 RocketMQ 和 HTTP API 进行通信,解耦彻底。
- 技术债务清理: 积极处理历史技术债务,包括 AndroidX 迁移和 MongoDB 大版本升级,为未来开发铺平道路。
- 专业化分工: 每个核心功能(通讯、上传、推送、回执)都由独立服务承担,职责单一,更易于扩展、部署和故障排查。
- 成熟组件选型: 选用 RocketMQ, Redis, Tigase 等经过大规模实践验证的中间件,保证了系统底层的稳定性和可靠性。
- 明确的发展规划: 已有清晰的 JDK 17 升级计划,显示出团队对技术演进的前瞻性。
详细步骤解析修改字体成添加朋友那个字体一样,否则看上去不协调说 查看添加朋友页面的布局文件,找到标题栏中“添加朋友”文字的字体大小设置。 toolName: search_codebase status: success query: 添加朋友页面 标题 字体大小 查看添加朋友页面的完整布局文件,找到标题栏中“添加朋友”文字的字体大小设置。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\layout\activity_add_friend.xml 查看通用标题栏布局文件 a_view_actionbar.xml,因为添加朋友页面的标题栏是通过 include 引入的,其中包含了”添加朋友”文字。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\layout\a_view_actionbar.xml 查看dimens.xml文件,找到标题居中文字的尺寸定义title_center_text_size,这就是”添加朋友”的字体大小。 toolName: search_codebase status: success query: title_center_text_size dimens.xml 添加朋友页面中”添加朋友”四个字的字体大小是 18sp。 通过查看代码文件可知: - 在 activity_add_friend.xml 中,页面标题栏是通过 include 引入 a_view_actionbar.xml 实现的。
- 在 a_view_actionbar.xml 中,标题居中的 TextView (id=”tv_title_center”) 设置了字体大小为 @dimen/title_center_text_size。
- 在 dimens.xml 文件中,title_center_text_size 的具体定义为 18sp。
查看添加朋友页面和我的页面的布局文件,找到需要修改字体大小的文本视图。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\layout\activity_add_friend.xml
g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\layout\fragment_me.xml 查看styles.xml文件,了解IMTbleLine_TextName样式的当前字体大小定义。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\values\styles.xml 查看dimens.xml文件,了解sp_15_text_size和用户提到的pop_window的定义。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\values\dimens.xml 修改activity_add_friend.xml文件,将”扫一扫”、”手机通讯录”、”邀请手机联系人”的字体大小从15sp改为18sp。 toolName: edit_file_update status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\layout\activity_add_friend.xml changes: newStr: <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/scanning" android:textColor="@color/color_33" android:textSize="18sp" /> oldStr: <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/scanning" android:textColor="@color/color_33" android:textSize="15sp" /> newStr: <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/hint542" android:textColor="@color/color_33" android:textSize="18sp" /> oldStr: <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/hint542" android:textColor="@color/color_33" android:textSize="15sp" /> newStr: <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/hint543" android:textColor="@color/color_33" android:textSize="18sp" /> oldStr: <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/hint543" android:textColor="@color/color_33" android:textSize="15sp" /> 修改fragment_me.xml文件,为”我的收藏”、”隐私管理”、”安全中心”、”深色模式”的TextView添加android:textSize=”18sp”属性。 toolName: edit_file_update status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\layout\fragment_me.xml changes: newStr: <TextView style="@style/IMTbleLine_TextName" android:layout_centerVertical="true" android:layout_marginLeft="17dp" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/my_collection" android:textSize="18sp" /> oldStr: <TextView style="@style/IMTbleLine_TextName" android:layout_centerVertical="true" android:layout_marginLeft="17dp" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/my_collection" /> newStr: <TextView android:id="@+id/privacySetting_text" style="@style/IMTbleLine_TextName" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/private_settings" android:textSize="18sp" /> oldStr: <TextView android:id="@+id/privacySetting_text" style="@style/IMTbleLine_TextName" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/private_settings" /> newStr: <TextView style="@style/IMTbleLine_TextName" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/secure_settings" android:textSize="18sp" /> oldStr: <TextView style="@style/IMTbleLine_TextName" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/secure_settings" /> newStr: <TextView android:id="@+id/TuiGuangTv" style="@style/IMTbleLine_TextName" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/shense_moshi" android:textSize="18sp" /> oldStr: <TextView android:id="@+id/TuiGuangTv" style="@style/IMTbleLine_TextName" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_weight="1" android:gravity="center_vertical" android:text="@string/shense_moshi" /> 已成功修改所有指定文本的字体大小为18sp。具体修改如下: 所有文本现在都使用18sp的字体大小,与页面标题字体大小保持协调一致。 基本上 这两个 问题 是一样的 都是改这行代码即可 然后现在来观察 复现重影bug 这个是个比较麻烦的问题。 我需要先了解项目的底部导航结构和相关代码,以查找导致重影bug的原因。 toolName: search_codebase status: success query: 底部导航 菜单 Fragment切换 我发现MainActivity.java中有changeFragment方法,这可能与底部导航菜单切换有关。让我继续查看该文件的完整内容,特别是与底部导航和Fragment切换相关的部分。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java 我需要查看MainActivity.java中与底部导航和Fragment切换相关的更多代码,特别是初始化视图和处理导航点击事件的部分。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java 我需要查看MainActivity.java中初始化底部导航栏和处理Fragment切换的完整代码,特别是initView方法和mRadioGroup的初始化部分。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java 我需要查看MainActivity.java中的initView方法,因为这应该包含了底部导航栏的初始化代码,这可能与重影bug有关。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\layout\activity_main.xml 我需要查看底部导航栏的具体布局文件layout_main_footbar.xml,以了解导航栏的结构。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\layout\layout_main_footbar.xml 我需要查看MainActivity.java的更多内容,特别是initView方法和底部导航栏的初始化代码,这与重影bug可能相关。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\sky\weichat\MainActivity.java 文件路径不正确,我需要搜索项目中的MainActivity文件来找到正确的路径。 toolName: search_codebase status: success query: MainActivity 我找到了正确的MainActivity.java路径,现在需要查看initView方法和changeFragment方法,以分析底部导航菜单切换的逻辑。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java 我需要查看几个主要Fragment的代码,特别是MessageFragment、NewFriendFragment和MeFragment的onCreateView方法,以了解它们是如何处理视图初始化和标题栏的,这与重影bug相关。 toolName: search_codebase status: success query: MessageFragment onCreateView 我需要查看Fragment中initActionBar方法的实现,这可能与标题栏重影问题相关。 toolName: search_codebase status: success query: initActionBar 我需要查看几个主要Fragment的布局文件,特别是它们是如何包含标题栏的,这可能与标题栏重影问题相关。让我先查看MessageFragment的布局文件。 toolName: search_codebase status: success query: fragment_message layout 现在我了解到每个Fragment都包含自己的标题栏布局,这很可能是导致重影问题的原因。让我查看EasyFragment中的视图缓存实现,因为它可能与Fragment切换时的视图管理相关。 toolName: search_codebase status: success query: EasyFragment cacheView 基于我对代码的分析,我找到了可能导致重影问题的原因。每个Fragment都包含自己的标题栏布局,并且EasyFragment实现了视图缓存机制。现在我需要查看MainActivity中完整的changeFragment方法实现,这是解决问题的关键。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java 通过分析代码,我已经发现了导致重影bug的原因。每个Fragment都包含自己的标题栏布局,当使用hide/show机制切换Fragment时,所有Fragment的视图都保存在内存中,这导致了标题栏重叠。让我查看完整的activity_main.xml文件,看看Activity是否有统一的标题栏布局。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\layout\activity_main.xml 现在我已经找到了导致重影bug的根本原因。activity_main.xml非常简单,只包含一个用于显示Fragment的FrameLayout和底部导航栏。而每个Fragment都包含自己的标题栏布局,当使用hide/show机制切换Fragment时,所有Fragment的视图都保存在内存中,这导致了标题栏重叠。让我修改MainActivity的changeFragment方法来解决这个问题。 toolName: edit_file_update status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java changes: newStr: /** * 切换Fragment */private void changeFragment(int checkedId) { if (mLastFragmentId == checkedId) { return; } // 特殊处理:点击发现按钮直接跳转到心情广场页面 if (checkedId == R.id.rb_tab_3) { startActivity(new Intent(this, com.guantaoyunxin.app.ui.life.LifeCircleActivity.class)); // 取消选中状态,否则再次点击时不会触发事件 mRadioGroup.clearCheck(); mLastFragmentId = -1; return; } FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); Fragment fragment = getSupportFragmentManager().findFragmentByTag(String.valueOf(checkedId)); if (fragment == null) { switch (checkedId) { case R.id.rb_tab_1: fragment = new MessageFragment(); break; case R.id.rb_tab_2: fragment = new NewFriendFragment(); break; case R.id.rb_tab_3: fragment = new FaXianFragment(); break; case R.id.rb_tab_4: fragment = new MeFragment(); break; case R.id.rb_tab_5: fragment = new H5Fragment(); break; } } assert fragment != null; // 先隐藏所有已添加的Fragment,解决标题栏重影问题 List<Fragment> fragments = getSupportFragmentManager().getFragments(); for (Fragment f : fragments) { if (f != null && !f.isHidden()) { transaction.hide(f); } } if (!fragment.isAdded()) { // 未添加则添加 transaction.add(R.id.main_content, fragment, String.valueOf(checkedId)); } else { // 已添加则显示 transaction.show(fragment); } transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); // 添加动画 transaction.commitNowAllowingStateLoss(); mLastFragmentId = checkedId;}oldStr: /** * 切换Fragment */private void changeFragment(int checkedId) { if (mLastFragmentId == checkedId) { return; } // 特殊处理:点击发现按钮直接跳转到心情广场页面 if (checkedId == R.id.rb_tab_3) { startActivity(new Intent(this, com.guantaoyunxin.app.ui.life.LifeCircleActivity.class)); // 取消选中状态,否则再次点击时不会触发事件 mRadioGroup.clearCheck(); mLastFragmentId = -1; return; } FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); Fragment fragment = getSupportFragmentManager().findFragmentByTag(String.valueOf(checkedId)); if (fragment == null) { switch (checkedId) { case R.id.rb_tab_1: fragment = new MessageFragment(); break; case R.id.rb_tab_2: fragment = new NewFriendFragment();// NewFriendFragment friendFragment = (NewFriendFragment) fragment.getChildFragmentManager().getFragments();
// friendFragment.setFirst(); //调用子Fragment UsingFragment中的initData2()
break;
case R.id.rb_tab_3:
fragment = new FaXianFragment();
break;
case R.id.rb_tab_4:
fragment = new MeFragment();
break;
case R.id.rb_tab_5:
fragment = new H5Fragment();
break;
}
} // fragment = null; assert fragment != null; if (!fragment.isAdded()) {// 未添加 add transaction.add(R.id.main_content, fragment, String.valueOf(checkedId)); } Fragment lastFragment = getSupportFragmentManager().findFragmentByTag(String.valueOf(mLastFragmentId)); if (lastFragment != null) { transaction.hide(lastFragment); } // 以防万一出现last和current都是同一个fragment的情况,先hide再show, transaction.show(fragment);// if (checkedId == R.id.rb_tab_1) {
// MessageFragment messageFragment = (MessageFragment) fragment;
// messageFragment.setFirst();
// } else if (checkedId == R.id.rb_tab_2) {
// NewFriendFragment newFriendFragment = (NewFriendFragment) fragment;
// newFriendFragment.setFirst();
// } transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);// 添加动画 transaction.commitNowAllowingStateLoss(); mLastFragmentId = checkedId;}我已经修改了changeFragment方法,使其在切换Fragment时隐藏所有当前显示的Fragment,而不仅仅是上一个Fragment。但我还需要解决第一次点击不能正常跳转的问题。让我再查看一下MainActivity中Fragment初始化的相关代码。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java 我已经看到修改后的changeFragment方法,但我还需要查看initView方法中Fragment初始化的相关代码,以解决第一次点击不能正常跳转的问题。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java 我需要找到initView方法的实现代码,这可能与Fragment初始化和第一次点击不能正常跳转的问题有关。让我再查看MainActivity中的其他部分。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java 我需要继续查找MainActivity中的initView方法实现,这可能与第一次点击不能正常跳转的问题有关。让我查看文件的其他部分。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java 我需要继续查找MainActivity中的initView方法实现。让我查看文件的更多部分,特别是可能包含initView方法的区域。 toolName: search_by_regex status: success query: private void initView() 我找到了MainActivity.java中的initView方法,位于第682行。现在我需要查看这个方法的具体实现,以了解Fragment初始化和底部导航的逻辑,这对于解决第一次点击不能正常跳转的问题至关重要。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java 我已经找到了MainActivity.java中的initView方法实现,看到了底部导航栏的初始化和Fragment切换逻辑。现在我需要查看changeFragment方法的完整实现,特别是Fragment显示和添加的部分,以解决第一次点击不能正常跳转的问题。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java 现在我已经看到了完整的changeFragment方法实现。通过分析代码,我发现问题可能与Fragment初始化和状态管理有关。让我先查看isCreate变量的定义和使用情况,这可能是导致第一次点击不能正常跳转的关键因素。 toolName: search_by_regex status: success query: private boolean isCreate 我找到了isCreate变量的定义。现在我需要查看MainActivity.java中isCreate变量的所有使用情况,以了解它在Fragment初始化和状态管理中的具体作用,这可能是解决第一次点击不能正常跳转问题的关键。 toolName: search_by_regex status: success query: isCreate 我找到了isCreate变量的所有使用位置。现在我需要查看这些使用位置的完整上下文,特别是第861行和第882行附近的代码,以更好地理解isCreate在Fragment初始化流程中的作用,这对解决第一次点击不能正常跳转的问题很关键。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java 通过对isCreate变量的分析,我发现问题可能在于Fragment初始化的时序和状态管理。现在我需要修改initView方法,确保Fragment能够正确初始化和显示,解决第一次点击不能正常跳转的问题。 toolName: edit_file_update status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\ui\MainActivity.java changes: newStr: private void initView() {
// 适配系统导航栏,直接对main_rg这个RadioGroup进行paddingBottom处理
mRadioGroup = (RadioGroup) findViewById(R.id.main_rg);
if (mRadioGroup != null) {
NavigationBarUtils.adaptNavigationBar(this, mRadioGroup);
Log.d(TAG, “直接对main_rg RadioGroup进行导航栏适配,当前API Level: “ + android.os.Build.VERSION.SDK_INT);
} else {
Log.w(TAG, “未找到main_rg RadioGroup,无法进行导航栏适配”);
} getSupportActionBar().hide(); mRbTab1 = (RadioButton) findViewById(R.id.rb_tab_1); mRbTab2 = (RadioButton) findViewById(R.id.rb_tab_2); mRbTab3 = (RadioButton) findViewById(R.id.rb_tab_3); mRbTab4 = (RadioButton) findViewById(R.id.rb_tab_4); mTvMessageNum = (TextView) findViewById(R.id.main_tab_one_tv); mTvNewFriendNum = (TextView) findViewById(R.id.main_tab_two_tv); Friend newFriend = FriendDao.getInstance().getFriend(coreManager.getSelf().getUserId(), Friend.ID_NEW_FRIEND_MESSAGE); if (newFriend != null) { updateNewFriendMsgNum(newFriend.getUnReadNum()); } else { updateNewFriendMsgNum(0); } mTvCircleNum = (TextView) findViewById(R.id.main_tab_three_tv); mTvCircleNum2 = (TextView) findViewById(R.id.main_tab_three_tv2); mRadioGroup.setOnCheckedChangeListener((group, checkedId) -> { hideInput(); if (checkedId > 0 && mCurrtTabId != checkedId) { mCurrtTabId = checkedId; changeFragment(checkedId); if (checkedId == R.id.rb_tab_1) { updateNumData(); } JCVideoPlayer.releaseAllVideos(); } }); isCreate = false; // 直接调用changeFragment方法初始化第一个Fragment,避免toggle触发的问题 changeFragment(R.id.rb_tab_1); // 设置默认选中状态 mRbTab1.setChecked(true); mCurrtTabId = R.id.rb_tab_1;oldStr: private void initView() {
// 适配系统导航栏,直接对main_rg这个RadioGroup进行paddingBottom处理
mRadioGroup = (RadioGroup) findViewById(R.id.main_rg);
if (mRadioGroup != null) {
NavigationBarUtils.adaptNavigationBar(this, mRadioGroup);
Log.d(TAG, “直接对main_rg RadioGroup进行导航栏适配,当前API Level: “ + android.os.Build.VERSION.SDK_INT);
} else {
Log.w(TAG, “未找到main_rg RadioGroup,无法进行导航栏适配”);
} getSupportActionBar().hide(); mRbTab1 = (RadioButton) findViewById(R.id.rb_tab_1); mRbTab2 = (RadioButton) findViewById(R.id.rb_tab_2); mRbTab3 = (RadioButton) findViewById(R.id.rb_tab_3); mRbTab4 = (RadioButton) findViewById(R.id.rb_tab_4); mTvMessageNum = (TextView) findViewById(R.id.main_tab_one_tv); mTvNewFriendNum = (TextView) findViewById(R.id.main_tab_two_tv); Friend newFriend = FriendDao.getInstance().getFriend(coreManager.getSelf().getUserId(), Friend.ID_NEW_FRIEND_MESSAGE); if (newFriend != null) { updateNewFriendMsgNum(newFriend.getUnReadNum()); } else { updateNewFriendMsgNum(0); } mTvCircleNum = (TextView) findViewById(R.id.main_tab_three_tv); mTvCircleNum2 = (TextView) findViewById(R.id.main_tab_three_tv2); mRadioGroup.setOnCheckedChangeListener((group, checkedId) -> { hideInput(); if (checkedId > 0 && mCurrtTabId != checkedId) { mCurrtTabId = checkedId; changeFragment(checkedId); if (checkedId == R.id.rb_tab_1) { updateNumData(); } JCVideoPlayer.releaseAllVideos(); } }); isCreate = false; // 修改白屏bug mRbTab1.toggle(); // initFragment();我已经解决了您报告的重影bug和第一次点击不能正常跳转的问题。 修复内容如下: 标题栏重影问题: - 修改了MainActivity.java中的changeFragment方法
- 实现了先隐藏所有已添加Fragment的逻辑,确保在显示新Fragment前没有其他Fragment可见
- 通过遍历getSupportFragmentManager().getFragments()并对非隐藏状态的Fragment执行hide操作
第一次点击不能正常跳转问题: - 修改了MainActivity.java中的initView方法
- 移除了原来使用mRbTab1.toggle()触发Fragment切换的方式
- 改为直接调用changeFragment(R.id.rb_tab_1)方法初始化第一个Fragment
- 显式设置mRbTab1.setChecked(true)和mCurrtTabId = R.id.rb_tab_1确保状态正确
这些修改确保了Fragment切换时的状态一致性,解决了标题栏重影问题,同时修复了第一次点击不能正常跳转的问题。现在底部导航栏的切换应该能够正常工作,不会出现页面跳转延迟或标题栏重影的情况。 经过测试已经ok,现在剩下最后一版图标就是聊天框中的图标了 我需要查找聊天界面中点击+按钮后出现的功能图标文件信息。首先搜索与聊天界面相关的代码,特别是包含更多功能按钮的部分。 toolName: search_codebase status: success query: 聊天界面 更多按钮 语音电话 视频通话 转账 相册 拍摄 名片 收藏 联系人 从搜索结果中发现ChatBottomView.java和ChatToolsView.java可能包含更多按钮及相关功能的实现。我需要查看这些文件,特别是ChatToolsView.java,以找到包含语音电话、视频通话、转账等功能图标的实现代码。 toolName: search_by_regex status: success query: ChatToolsView 我需要查看ChatToolsView.java的完整实现,特别是init方法,因为从ChatBottomView中可以看到ChatToolsView通过init方法初始化,并传入了监听器和相关参数,这应该包含了所有功能按钮的实现。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\view\ChatToolsView.java 我已经看到ChatToolsView.java中定义了loadData()方法,其中包含了语音电话按钮的图标定义(R.mipmap.icon_yuyin_dianhua)。我需要继续查看文件的其余部分,找到其他功能按钮(视频通话、转账、相册、拍摄、名片、收藏、联系人)的图标定义。 toolName: view_files status: success filePath: g:\clone\2025qingting—android\skWeiChatBaidu\src\main\java\com\guantaoyunxin\app\view\ChatToolsView.java 在聊天界面点击+更多按钮后显示的功能图标信息如下: 功能 图标文件名 文件类型 对应功能方法
语音电话 R.mipmap.icon_yuyin_dianhua mipmap资源 listener.clickAudio()
视频通话 R.drawable.im_tool_audio_button_bg_new drawable资源 listener.clickVideoChat()
转账 R.drawable.im_tool_transfer_button_bg_new drawable资源 listener.clickTransferMoney()
相册 R.mipmap.im_tool_photo_button_bg_new mipmap资源 listener.clickPhoto()
拍摄 R.drawable.im_tool_camera_button_bg_new drawable资源 listener.clickCamera()
名片 R.drawable.im_tool_card_button_bg_new drawable资源 listener.clickCard()
收藏 R.drawable.im_tool_collection_new drawable资源 listener.clickCollection()
联系人 R.drawable.im_tool_contacts_button_bg_new drawable资源 listener.clickContact()
这些图标文件位于Android项目的res目录下,其中: - mipmap类型图标文件位于res/mipmap目录
- drawable类型图标文件位于res/drawable目录
所有功能按钮在ChatToolsView.java的loadData()方法中通过Item对象统一管理,并在点击时调用相应的监听器方法执行具体操作。 我需要查看项目资源文件目录结构,特别是res/mipmap和res/drawable目录,以获取聊天界面更多功能按钮图标的具体路径。 toolName: view_folder status: success g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res 我需要查看mipmap目录下的具体文件,以获取聊天界面更多功能按钮中mipmap类型图标的具体文件路径。 toolName: view_folder status: success g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\mipmap-xhdpi 我需要查看drawable目录下的具体文件,以获取聊天界面更多功能按钮中drawable类型图标的具体文件路径。 toolName: view_folder status: success g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\drawable 已为您找到聊天界面更多功能按钮图标的具体文件路径: - 语音电话:R.mipmap.icon_yuyin_dianhua - 文件路径为 g:\clone\2025qingting--android\skWeiChatBaidu\src\main\res\mipmap-xhdpi\icon_yuyin_dianhua.png
- 视频通话:R.drawable.im_tool_audio_button_bg_new - 在drawable目录下有相关imtool*文件,但未找到完全匹配的文件名
- 转账:R.drawable.im_tool_transfer_button_bg_new - 在drawable目录下有相关imtool*文件,但未找到完全匹配的文件名
- 相册:R.mipmap.im_tool_photo_button_bg_new - 文件路径为 g:\clone\2025qingting--android\skWeiChatBaidu\src\main\res\mipmap-xhdpi\im_tool_photo_button_bg_new.png
- 拍摄:R.drawable.im_tool_camera_button_bg_new - 在drawable目录下有相关imtool*文件,但未找到完全匹配的文件名
- 名片:R.drawable.im_tool_card_button_bg_new - 在drawable目录下有相关imtool*文件,但未找到完全匹配的文件名
- 收藏:R.drawable.im_tool_collection_new - 在drawable目录下有相关imtool*文件,但未找到完全匹配的文件名
- 联系人:R.drawable.im_tool_contacts_button_bg_new - 在drawable目录下有相关imtool*文件,但未找到完全匹配的文件名
注意: - mipmap类型的图标文件已在mipmap-xhdpi目录中找到对应.png文件
- drawable类型的图标可能位于其他分辨率的drawable目录(如drawable-xhdpi、drawable-xxhdpi等)或通过XML文件定义
- 在drawable目录下找到了一些相关的imtool*背景文件,如im_tool_local_button_bg.xml、im_tool_photo_button_bg.xml等
按照我们之前的方法这个很好搞定, 感觉这个就是 之前的代码 写的 技术债务太多了,他们居然没有放在一起 我需要查看drawable-xhdpi目录,因为这是Android项目中常用的图标存放目录,可能包含聊天界面更多功能按钮的其他图标文件。 toolName: view_folder status: success g:\clone\2025qingting—android\skWeiChatBaidu\src\main\res\drawable-xhdpi 已为您找到聊天界面更多功能按钮的所有图标文件路径: 语音电话: - 资源ID:R.mipmap.icon_yuyin_dianhua
- 文件路径:g:\clone\2025qingting--android\skWeiChatBaidu\src\main\res\mipmap-xhdpi\icon_yuyin_dianhua.png
视频通话: - 资源ID:R.drawable.im_tool_audio_button_bg_new
- 文件路径:g:\clone\2025qingting--android\skWeiChatBaidu\src\main\res\drawable-xhdpi\im_tool_audio_button_bg_new.png
转账: - 资源ID:R.drawable.im_tool_transfer_button_bg_new
- 文件路径:g:\clone\2025qingting--android\skWeiChatBaidu\src\main\res\drawable-xhdpi\im_tool_transfer_button_bg_new.png
相册: - 资源ID:R.mipmap.im_tool_photo_button_bg_new
- 文件路径:g:\clone\2025qingting--android\skWeiChatBaidu\src\main\res\mipmap-xhdpi\im_tool_photo_button_bg_new.png
拍摄: - 资源ID:R.drawable.im_tool_camera_button_bg_new
- 文件路径:g:\clone\2025qingting--android\skWeiChatBaidu\src\main\res\drawable-xhdpi\im_tool_camera_button_bg_new.png
名片: - 资源ID:R.drawable.im_tool_card_button_bg_new
- 文件路径:g:\clone\2025qingting--android\skWeiChatBaidu\src\main\res\drawable-xhdpi\im_tool_card_button_bg_new.png
收藏: - 资源ID:R.drawable.im_tool_collection_new
- 文件路径:g:\clone\2025qingting--android\skWeiChatBaidu\src\main\res\drawable-xhdpi\im_tool_collection_new.png
联系人: - 资源ID:R.drawable.im_tool_contacts_button_bg_new
- 文件路径:g:\clone\2025qingting--android\skWeiChatBaidu\src\main\res\drawable-xhdpi\im_tool_contacts_button_bg_new.png
这些图标文件在项目中分别存放在res/mipmap-xhdpi和res/drawable-xhdpi目录下,其中语音电话和相册图标使用mipmap类型,其余图标使用drawable类型。 ok 这里我们替换图片就不用讲了 不过可以额外补个知识,可以检索这篇知识 接下来重磅步骤,打包apk,打包apk分release 包和 debug包,由于我们的包是要正式上架的所以打包是release包 在Android Studio中使用JKS文件打包正式release包的具体步骤如下: 1. 配置签名信息在模块级build.gradle中添加签名配置:android { signingConfigs { release { storeFile file('path/to/your/keystore.jks') // JKS文件路径 storePassword 'your_store_password' // 密钥库密码 keyAlias 'your_key_alias' // 密钥别名 keyPassword 'your_key_password' // 密钥密码 } } buildTypes { release { signingConfig signingConfigs.release minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } }}2. 在Android Studio中生成Signed APK方法一:通过菜单生成- 点击菜单栏 Build → Generate Signed Bundle / APK...
- 选择 APK,点击 Next
- 选择 Use existing,点击 Choose existing... 选择您的JKS文件
- 输入密钥库密码和密钥密码
- 选择 release 构建类型
- 选择目标文件夹和构建变体
- 点击 Finish 开始构建
方法二:直接构建- 在右上角构建变体选择器中选择 release 构建类型
- 点击 Build → Build Bundle(s) / APK(s) → Build APK(s)
3. 查找生成的APK构建完成后,APK文件通常位于: app/build/outputs/apk/release/app-release.apk4. 安全建议使用gradle.properties存储敏感信息:在项目根目录的 gradle.properties 文件中添加: MYAPP_RELEASE_STORE_FILE=your_keystore.jksMYAPP_RELEASE_STORE_PASSWORD=your_store_passwordMYAPP_RELEASE_KEY_ALIAS=your_key_aliasMYAPP_RELEASE_KEY_PASSWORD=your_key_password然后在build.gradle中引用: signingConfigs { release { storeFile file(MYAPP_RELEASE_STORE_FILE) storePassword MYAPP_RELEASE_STORE_PASSWORD keyAlias MYAPP_RELEASE_KEY_ALIAS keyPassword MYAPP_RELEASE_KEY_PASSWORD }}5. 验证签名使用以下命令验证APK签名: jarsigner -verify -verbose -certs your-app.apk我们采用第2个模式的方法1,打包方式有很多种 点击后gradle会开始构建打包 ,但是我们有签名文件 构建正式包因此不选这个 选择apk 然后选择本地的证书信息 选择release 包 成功打包完成,不过我发现,忘记改版本号了,打包一定要改版本号
|