当前位置: 首页 > news >正文

底部导航栏新增功能按键

场景需求:

在底部导航栏添加power案件,单击息屏,长按 关机

如下实现图
在这里插入图片描述

借此需求,需要掌握技能:

  • 底部导航栏如何实现
  • 新增、修改、删除底部导航栏流程
  • 对底部导航栏部分样式如何修改。 比如放不下、顺序排列、坑点如何修改等

修改-新增文件:

新增

\vendor\mediatek\proprietary\packages\apps\SystemUI\res\layout\power.xml         [新增底部导航 power 功能按键布局文件]
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\drawable\ic_lock_power_off.xml  [新增power按键icon图标]

修改

\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\navigationbar\NavigationBarView.java
\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\navigationbar\NavigationBar.java
\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\navigationbar\NavigationBarInflaterView.java需改:新增 power 功能菜单
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\values\config.xml      
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\values-sw900dp\config.xml
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\values-sw600dp\config.xml//按键太多,设置按键宽度,让竖屏情况下多个功能虚拟按键能够正常显示出来:我们对应的dimens 文件为values-sw600dp  故,只修改这个文件即可
/vendor/mediatek/proprietary/packages/apps/SystemUI/res/values-sw600dp/dimens.xml

具体修改点

修改点 一)
功能按键添加:power

<string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,wb_sunny,volume_add,power,screenshot;right</string>

修改点 二)
虚拟按键宽度和padding 重写设置:

<dimen name="navigation_key_width">90dp</dimen>

修改点 三)

NavigationBarView.java            [设置按键图标、按键放到集合中,便于封装操作]
NavigationBar.java                 [点触事件 长按、短按事件]
NavigationBarInflaterView.java   [加载布局,加载功能按键view]
见修改文件  wang 相关 add 和 end 结束位置
下文 详细说明

参考资料

Android 8.1平台SystemUI 导航栏加载流程解析:
Android 9.0 SystemUI NavigationBar
Android13 关于SystemUI更新Nav Bar add volume button && other button
Android 导航栏功能项的显示与屏蔽
Android 12 自定义底部导航栏
Android11 底部导航栏添加虚拟按钮-问题合集

实现思路和具体方案

在实现方案之前,一脸蒙蔽,那是缺乏一定的知识储备,实现后发现思路很清晰的,理解流程,一步一步实现即可。可以参考现有的实现方案,比如:home/back/recent 部分Android版本
本身就已经有的功能,照葫芦画瓢。

主要思路如下:

  • 创建功能按键布局layout[对应 xml]:参考已有的功能按键
  • 配置文件中,新增功能按键菜单,只有有了默认的配置才会加载上面的布局View
  • NavigationBar为系统加载的组件,在组件中实现点击事件,在关联的加载布局View 类
    NavigationBarInflaterView.java 和 NavigationBarView.java 实现布局的功能按键View的添加和功能view 的获取/设置View背景等,最终实现功能按键的加载。

布局创建

比如我们的power.xml

<?xml version="1.0" encoding="utf-8"?>
<com.android.systemui.navigationbar.buttons.KeyButtonViewxmlns:android="http://schemas.android.com/apk/res/android"xmlns:systemui="http://schemas.android.com/apk/res-auto"android:id="@+id/power"android:layout_width="@dimen/navigation_key_width"android:layout_height="match_parent"android:layout_weight="0"systemui:keyCode="26"android:scaleType="center"android:contentDescription="@string/accessibility_home"android:paddingStart="@dimen/navigation_key_padding"android:paddingEnd="@dimen/navigation_key_padding"/>

那为什么这么创建? 找一下 已有的 功能按键 比如Home 按键:

<com.android.systemui.navigationbar.buttons.KeyButtonViewxmlns:android="http://schemas.android.com/apk/res/android"xmlns:systemui="http://schemas.android.com/apk/res-auto"android:id="@+id/home"android:layout_width="@dimen/navigation_key_width"android:layout_height="match_parent"android:layout_weight="0"systemui:keyCode="3"android:scaleType="center"android:contentDescription="@string/accessibility_home"android:paddingStart="@dimen/navigation_key_padding"android:paddingEnd="@dimen/navigation_key_padding"/>

这里有三个点需要注意:

  • layout_width 值的设置,底部导航栏功能按键过多,会出现不会显示全的问题,需要适配。
  • keyCode,有keyCode设置,会根据KeyButtonView 监听到keyCode
    按键值,这样可以监听并执行对应逻辑。【此需求暂无用到】
  • id: 这个id 在NavigationBarView,中的 mButtonDispatchers.put(R.id.power, new
    ButtonDispatcher(R.id.power)); 对应 匹配,不然找不到id。

布局加载

添加到NavigationBarInflaterView中去,NavigationBarInflaterView 见名知意。本身代码量不多的,就是一个View,加载功能按键子View

NavigationBarInflaterView extends FrameLayout ,正常的一个FragmentLayout ,如下举例几个简单方法

加载配置

 protected String getDefaultLayout() {//wangfangchen add /*final int defaultResource = QuickStepContract.isGesturalMode(mNavBarMode)? R.string.config_navBarLayoutHandle: mOverviewProxyService.shouldShowSwipeUpUI()? R.string.config_navBarLayoutQuickstep: R.string.config_navBarLayout;*/final int defaultResource =		 R.string.config_navBarLayout;Log.d(TAG,"getDefaultLayout  "+getContext().getString(defaultResource));//wangfangchen end  return getContext().getString(defaultResource);}

所以我们需要新增功能按键就需要在配置 文件中添加功能按键:power

<string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,wb_sunny,volume_add,power,screenshot;right</string>

加载子View

@Overrideprotected void onFinishInflate() {super.onFinishInflate();inflateChildren();clearViews();inflateLayout(getDefaultLayout());}protected void inflateLayout(String newLayout) {mCurrentLayout = newLayout;if (newLayout == null) {newLayout = getDefaultLayout();}String[] sets = newLayout.split(GRAVITY_SEPARATOR, 3);Log.d(TAG, "inflateLayout  newLayout:"+newLayout);if (sets.length != 3) {Log.d(TAG, "Invalid layout.");newLayout = getDefaultLayout();sets = newLayout.split(GRAVITY_SEPARATOR, 3);}String[] start = sets[0].split(BUTTON_SEPARATOR);String[] center = sets[1].split(BUTTON_SEPARATOR);String[] end = sets[2].split(BUTTON_SEPARATOR);// Inflate these in start to end order or accessibility traversal will be messed up.inflateButtons(start, mHorizontal.findViewById(R.id.ends_group),false /* landscape */, true /* start */);inflateButtons(start, mVertical.findViewById(R.id.ends_group),true /* landscape */, true /* start */);inflateButtons(center, mHorizontal.findViewById(R.id.center_group),false /* landscape */, false /* start */);inflateButtons(center, mVertical.findViewById(R.id.center_group),true /* landscape */, false /* start */);addGravitySpacer(mHorizontal.findViewById(R.id.ends_group));addGravitySpacer(mVertical.findViewById(R.id.ends_group));inflateButtons(end, mHorizontal.findViewById(R.id.ends_group),false /* landscape */, false /* start */);inflateButtons(end, mVertical.findViewById(R.id.ends_group),true /* landscape */, false /* start */);updateButtonDispatchersCurrentView();}private void inflateButtons(String[] buttons, ViewGroup parent, boolean landscape,boolean start) {for (int i = 0; i < buttons.length; i++) {Log.d(TAG,"inflateButtons buttons[i]:"+buttons[i]+"  landscape:"+landscape+"    start:"+start);inflateButton(buttons[i], parent, landscape, start);}}

创建 子view:createView

@Nullableprotected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape,boolean start) {LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;View v = createView(buttonSpec, parent, inflater);if (v == null) return null;v = applySize(v, buttonSpec, landscape, start);parent.addView(v);addToDispatchers(v);View lastView = landscape ? mLastLandscape : mLastPortrait;View accessibilityView = v;if (v instanceof ReverseRelativeLayout) {accessibilityView = ((ReverseRelativeLayout) v).getChildAt(0);}if (lastView != null) {accessibilityView.setAccessibilityTraversalAfter(lastView.getId());}if (landscape) {mLastLandscape = accessibilityView;} else {mLastPortrait = accessibilityView;}return v;}

根据配置中的功能按键 名字字符串,加载对应的布局,也就是加载了view 到 NavigationBarView

View createView(String buttonSpec, ViewGroup parent, LayoutInflater inflater) {Log.d(TAG,"createView   buttonSpec:"+buttonSpec);View v = null;String button = extractButton(buttonSpec);if (LEFT.equals(button)) {button = extractButton(NAVSPACE);} else if (RIGHT.equals(button)) {button = extractButton(MENU_IME_ROTATE);}if (HOME.equals(button)) {v = inflater.inflate(R.layout.home, parent, false);} else if (BACK.equals(button)) {v = inflater.inflate(R.layout.back, parent, false);} else if (RECENT.equals(button)) {v = inflater.inflate(R.layout.recent_apps, parent, false);} else if (MENU_IME_ROTATE.equals(button)) {v = inflater.inflate(R.layout.menu_ime, parent, false);} else if (NAVSPACE.equals(button)) {v = inflater.inflate(R.layout.nav_key_space, parent, false);} else if (CLIPBOARD.equals(button)) {v = inflater.inflate(R.layout.clipboard, parent, false);} else if (CONTEXTUAL.equals(button)) {v = inflater.inflate(R.layout.contextual, parent, false);} else if (HOME_HANDLE.equals(button)) {v = inflater.inflate(R.layout.home_handle, parent, false);} else if (IME_SWITCHER.equals(button)) {v = inflater.inflate(R.layout.ime_switcher, parent, false);//huanghb add} else if (VOLUME_ADD.equals(button)) {v = inflater.inflate(R.layout.volume_add, parent, false);} else if (VOLUME_SUB.equals(button)) {v = inflater.inflate(R.layout.volume_sub, parent, false);} else if (SCREENSHOT.equals(button)) {v = inflater.inflate(R.layout.screenshot, parent, false);} //wangfangchen add else if (POWER.equals(button)) {v = inflater.inflate(R.layout.power, parent, false);} //wangfangchen end else if (WB_SUNNY.equals(button)) {v = inflater.inflate(R.layout.wb_sunny, parent, false);} else if (button.startsWith(KEY)) {Log.d(TAG,"createView   buttonSpec:"+buttonSpec+"   button:"+button+"   KEY:"+KEY);String uri = extractImage(button);int code = extractKeycode(button);v = inflater.inflate(R.layout.custom_key, parent, false);((KeyButtonView) v).setCode(code);if (uri != null) {if (uri.contains(":")) {((KeyButtonView) v).loadAsync(Icon.createWithContentUri(uri));} else if (uri.contains("/")) {int index = uri.indexOf('/');String pkg = uri.substring(0, index);int id = Integer.parseInt(uri.substring(index + 1));((KeyButtonView) v).loadAsync(Icon.createWithResource(pkg, id));}}}return v;}

加载布局View NavigationBarInflaterView

上面已经分析了NavigationBarInflaterView 如何加载子功能按键,那么这个View 是在哪里已经并初始化呢?
看布局:navigation_bar.xm


<?xml version="1.0" encoding="utf-8"?>
<com.android.systemui.navigationbar.NavigationBarViewxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/navigation_bar_view"android:layout_height="match_parent"android:layout_width="match_parent"android:clipChildren="false"android:clipToPadding="false"android:background="@drawable/system_bar_background"><com.android.systemui.navigationbar.NavigationBarInflaterViewandroid:id="@+id/navigation_inflater"android:layout_width="match_parent"android:layout_height="match_parent"android:clipChildren="false"android:clipToPadding="false" /></com.android.systemui.navigationbar.NavigationBarView>

找navigation_bar.xml 加载地方
1)NavigationBar.java oreateView 方法
在这里插入图片描述

备注:NavigationBar 就暂时不分析了,可以参考其它博客或自己的System UI加载流程。

NavigationBarView View的封装

上面分析 NavigationBarView 嵌套了 NavigationBarInflaterView,也就是对NavigationBarInflaterView 的一层封装,

private final SparseArray<ButtonDispatcher> mButtonDispatchers = new SparseArray<>();
放置:view 到数组//huanghb addmButtonDispatchers.put(R.id.volume_add, new ButtonDispatcher(R.id.volume_add));mButtonDispatchers.put(R.id.volume_sub, new ButtonDispatcher(R.id.volume_sub));mButtonDispatchers.put(R.id.screenshot, new ButtonDispatcher(R.id.screenshot));mButtonDispatchers.put(R.id.wb_sunny, new ButtonDispatcher(R.id.wb_sunny));//huanghb end//wangfangchen add		mButtonDispatchers.put(R.id.power, new ButtonDispatcher(R.id.power));//wangfangchen end		

从通过view 数组,获取子view

      return mButtonDispatchers.get(R.id.recent_apps);}public ButtonDispatcher getBackButton() {return mButtonDispatchers.get(R.id.back);}public ButtonDispatcher getHomeButton() {return mButtonDispatchers.get(R.id.home);}public ButtonDispatcher getImeSwitchButton() {return mButtonDispatchers.get(R.id.ime_switcher);}public ButtonDispatcher getAccessibilityButton() {return mButtonDispatchers.get(R.id.accessibility_button);}这不就是对子菜单功能按键的一层封装吗?	

子布局显示并控制NavigationBar

在上面已经通过分析了布局,反向关联了NavigationBarInflaterView 加载->NavigationBar 加载。就从这个角度来分析布局显示出来后如何控制。

看部分相关方法并分析

准备View prepareNavigationBarView()

  private void prepareNavigationBarView() {Log.d(TAG,"prepareNavigationBarView");mNavigationBarView.reorient();ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();recentsButton.setOnClickListener(this::onRecentsClick);recentsButton.setOnTouchListener(this::onRecentsTouch);ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();homeButton.setOnTouchListener(this::onHomeTouch);reconfigureHomeLongClick();ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton();accessibilityButton.setOnClickListener(this::onAccessibilityClick);accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick);updateAccessibilityServicesState(mAccessibilityManager);ButtonDispatcher imeSwitcherButton = mNavigationBarView.getImeSwitchButton();imeSwitcherButton.setOnClickListener(this::onImeSwitcherClick);updateScreenPinningGestures();//huanghb add//Log.d("huanghb","prepareNavigationBarView");ShowVolumeButton();ShowScreenShotButton();ShowWbSunnyButton();//huanghb end//wangfangchen add ShowPowerButton();//wangfangchen end }

设置点击事件 长按事件

//wangfangchen add private void ShowPowerButton(){Log.d(TAG,"ShowPowerButton");ButtonDispatcher powerButton = mNavigationBarView.getPowerButton();// String customScreenshot = SystemProperties.get("persist.fise.screenshot.icon","0");powerButton.setOnClickListener(this::onPowerClick);//powerButton.setOnTouchListener(this::onScreenShotTouch);powerButton.setOnLongClickListener(this::onPowerLongClick);powerButton.setVisibility(View.VISIBLE); }//wangfangchen end 	//wangfangchen add private void onPowerClick(View v) {Log.d(TAG,"onPowerClick");mHandler.removeCallbacks(mPower);mHandler.postDelayed(mPower , 200);}private boolean onPowerLongClick(View v) {Log.d(TAG,"onPowerLongClick");setActionNavigationbar();mHandler.removeCallbacks(mPowerReboot);mHandler.postDelayed(mPowerReboot, 200);return  true;}//wangfangchen end 

在对应的线程里面执行逻辑即可

总结

上面分析就很明朗了,需要搞清楚
1)功能按键 布局,如何加载
2)配置 功能菜单 ,如何配置
2)三个类:NavigationBarView NavigationBar NavigationBarInflaterView 联系

相关文章:

底部导航栏新增功能按键

场景需求&#xff1a; 在底部导航栏添加power案件&#xff0c;单击息屏&#xff0c;长按 关机 如下实现图 借此需求&#xff0c;需要掌握技能&#xff1a; 底部导航栏如何实现新增、修改、删除底部导航栏流程对底部导航栏部分样式如何修改。 比如放不下、顺序排列、坑点如…...

Mac安装MINIO服务器实现本地上传和下载服务

0.MINIO学习文档 Minio客户端mc使用 | Elibaron学习笔记 1.Mac安装MINIO 中文官方网址&#xff1a;MinIO下载和安装 | 用于创建高性能对象存储的代码和下载内容 (1) brew 安装 brew install minio/stable/minio &#xff08;2&#xff09;安装完成&#xff0c;执行brew i…...

SpringMVC:参数传递之日期类型参数传递

环境准备和参数传递请见&#xff1a;SpringMVC参数传递环境准备 日期类型比较特殊&#xff0c;因为对于日期的格式有N多中输入方式&#xff0c;比如: 2088-08-182088/08/1808/18/2088… 针对这么多日期格式&#xff0c;SpringMVC该如何接收&#xff0c;它能很好的处理日期类…...

【C语言基础】斐波那契数列

相信你是最棒哒&#xff01;&#xff01;&#xff01; 文章目录 题目描述 正确代码&#xff1a; 总结 题目描述 菲波那契数列是指这样的数列: 数列的第一个和第二个数都为1&#xff0c;接下来每个数都等于前面2个数之和。 给出一个正整数k&#xff0c;要求菲波那契数列中第k个数…...

Ubuntu无法连接Linux

检查网络连接 确保你的机器能够正常连接互联网。你可以尝试 ping 一下 GitHub 或其他网站&#xff0c;确认是否有网络问题&#xff1a; ping github.com如果无法 ping 通 GitHub&#xff0c;检查一下你的网络连接。 检查 GitHub 状态 有时候 GitHub 本身可能会出现服务故障。你…...

T5模型、GPT和BERT

目录 T5模型、GPT和BERT 一、T5模型 二、GPT模型 三、BERT模型(词嵌入模型,一个单词4096维度) 四、区别与联系 T5模型、GPT和BERT T5模型、GPT模型和BERT模型都是基于Transformer架构的预训练语言模型,但它们在设计目标、架构和应用上存在一些区别和联系: 1. **模型架…...

51c自动驾驶~合集39

我自己的原文哦~ https://blog.51cto.com/whaosoft/12707676 #DiffusionDrive 大幅超越所有SOTA&#xff01;地平线DiffusionDrive&#xff1a;生成式方案或将重塑端到端格局&#xff1f; 近年来&#xff0c;由于感知模型的性能持续进步&#xff0c;端到端自动驾驶受到了来…...

ThinkPHP场景动态验证

一、缘由 今天在用thinkphp8写东西的时候发现&#xff0c;写验证器规则和场景优点费时间&#xff0c;就算用tinkphp的命令行生成也是生成一个空壳。内容还是要自己填写感觉麻烦。 就突发奇想能不能自动生成验证器&#xff0c;也不能是说自动生成验证器&#xff0c;生成验证其的…...

3D基因组工具(HiC可视化)trackc--bioinfomatics tools 35

01 3D genome data analysis guides 茶树三维基因组-文献精读19 https://trackc.readthedocs.io/en/latest/install.html #官网 https://github.com/seqyuan/trackc #官网https://trackc.readthedocs.io/en/latest/analysis_guide/index.html #HiC可视化案例 …...

Maven进阶

前言 我们这一节讲一下Maven 1. 分模块开发的意义 同一个程序我们按功能划分为不同的模块 同一个模块导成jar之类的&#xff0c;这样就可以共享数据了 2. 分模块开发与设计 我们以原来的ssm整合的模块来考虑 我们来把domain这个模块搞消失&#xff0c;重新制造一个模块 我们…...

【k8s】kubelet 的相关证书

在 Kubernetes 集群中&#xff0c;kubelet 使用的证书通常存放在节点上的特定目录。这些证书用于 kubelet 与 API 服务器之间的安全通信。具体的位置可能会根据你的 Kubernetes 安装方式和配置有所不同&#xff0c;下图是我自己环境【通过 kubeadm 安装的集群】中的kubelet的证…...

我们来学mysql -- 事务并发之脏写(原理篇)

事务并发之脏写 题记脏写防止脏写题记 在《事务之概念》提到事务对应现实世界的状态转换,这个过程要满足4个特性这世界,真理只在大炮射程之类,通往和平的道路,非“常人”可以驾驭一个人生活按部就班,人多起来,难免鸡飞狗跳同理现实世界的状态转换映射到数据库,满足4个特…...

AI×5G 市场前瞻及应用现状

本文为《5GAI时代&#xff1a;生活方式和市场的裂变》一书读后总结及研究。 本书的上架建议是“经营”&#xff0c;内容也更偏向于市场分析。书出版于2021年&#xff0c;现在是2024年&#xff0c;可以收集整理一些例子&#xff0c;看看书里的前瞻性5GAI应用预测&#xff0c;到…...

LLM:模拟o1的思维链实现

本文项目地址&#xff1a;https://github.com/stay-leave/enhance_llm/tree/main/like-o1 运行的流程&#xff1a; 1.输入用户消息&#xff0c;query 2.组装消息列表&#xff0c;包括系统提示词&#xff08;关键&#xff09;&#xff0c;用户消息&#xff0c;助手消息&#xff…...

vue3+vite 批量引入组件动态使用

import { ref, reactive, toRaw, markRaw, defineAsyncComponent, onMounted } from vue import type { Component } from vue// vue3vite 批量引入组件动态使用 const modules import.meta.glob<Component>(./details/*.vue) // 明确指定导入的模块类型为Component con…...

PyQt 中的无限循环后台任务

在 PyQt 中实现一个后台无限循环任务&#xff0c;需要确保不会阻塞主线程&#xff0c;否则会导致 GUI 无响应。常用的方法是利用 线程&#xff08;QThread&#xff09; 或 任务&#xff08;QRunnable 和 QThreadPool&#xff09; 来运行后台任务。以下是一些实现方式和关键点&a…...

【python使用kazoo连ZooKeeper基础使用】

from kazoo.client import KazooClient, KazooState from kazoo.exceptions import NoNodeError,NodeExistsError,NotEmptyError import json# 创建 KazooClient 实例&#xff0c;连接到 ZooKeeper 服务器 zk KazooClient(hosts127.0.0.1:2181) zk.start()# 定义节点路径 path…...

【MySQL】内置函数

MySQL中的内置函数 一、日期函数1.1 current_date函数1.2 current_time函数1.3 current_timestamp函数1.4 date_add函数1.5 date_sub函数1.6 datediff函数1.7 now函数综合使用1综合使用2 二、字符串函数2.1 charset函数2.2 concat函数2.3 length函数2.4 replace函数2.5 substri…...

机器学习面试八股总结

下面是本人在面试中整理的资料和文字&#xff0c;主要针对机器学习面试八股做浅显的总结&#xff0c;大部分来源于ChatGPT&#xff0c;中间有借鉴一些博主的优质文章&#xff0c;已经在各文中指出原文。有任何问题&#xff0c;欢迎随时不吝指正。 文章系列图像使用动漫 《星游…...

【Android Debug Bridge】adb常用指令(更新中)

adb常用指令 ADB&#xff08;Android Debug Bridge&#xff09;是一个强大的命令行工具&#xff0c;用于与连接的Android设备进行通信。 1&#xff1a;安装软件包&#xff0c;假设app安装包为apk adb install [apk]2&#xff1a;查看当前连接PC的安卓设备编号 adb devices3…...

贵州大学oj平台软工24-11-27第5次小测

题目&#xff1a;阶乘和函数 题目描述 设计一个计算阶乘和的函数&#xff0c;用于求1!2!...n!并返回结果。 其中n是函数的参数。 程序的开始部分及main函数已经写好如下&#xff1a; #include <stdio.h> double factSum(int n); int main(){ int n; scanf("…...

【GPT】代谢概念解读

以下是对代谢中分解代谢和合成代谢两个概念的深入解读&#xff0c;用简单易懂的方式展开说明&#xff1a; 1. 分解代谢&#xff08;Catabolism&#xff09; 什么是分解代谢&#xff1f; 分解代谢是身体把大分子“拆开”的过程。就像把一个三明治分解成面包片、肉片和菜叶&#…...

Flutter如何适配RTL

阿拉伯语和希伯来语等是使用的从右到左书写的文字系统。世界上估计有4.22亿人以阿拉伯语做为母语。使用从右至左的人口可以说是更多了。所以对于出海项目来说&#xff0c;是不能忽视的一部分。 RTL可以说是本地化适配中比较麻烦的一项&#xff0c;并没有多语言适配来的简单。RT…...

Java中的“接口“详解

1.接口的概念 在Java中接口可以看成是:多个类的公共规范,是一种引用数据类型 2.语法规则 接口的定义格式与类的定义格式相同,将"class"关键字换成"interface"关键字,就定义了一个接口. //接口的关键字"interface"定义了一个名称为"USB&…...

Windows 10电脑无声问题的全面解决方案

Windows 10操作系统以其强大的功能和用户友好的界面赢得了广大用户的青睐&#xff0c;但在使用过程中&#xff0c;有时会遇到电脑突然没有声音的问题。这一问题可能由多种原因引起&#xff0c;包括音频驱动程序问题、音频设置错误、系统更新冲突等。本文将详细介绍Windows 10无…...

ElasticSearch学习篇19_《检索技术核心20讲》搜推广系统设计思想

目录 主要是包含搜推广系统的基本模块简单介绍&#xff0c;另有一些流程、设计思想的分析。 搜索引擎 基本模块检索流程 查询分析查询纠错 广告引擎 基于标签倒排索引召回基于向量ANN检索召回打分机制&#xff1a;非精确打分精准深度学习模型打分索引精简&#xff1a;必要的…...

IPv6 NA RTR/SOL/OVR标志位,单播多播选择,ndppd代理和kernel配置

NA消息用单播还是多播的判断理由 单播回复&#xff08;Unicast&#xff09;&#xff1a; 如果客户端发送 RS 消息时&#xff0c;使用的是一个全局地址或链路本地地址作为源地址&#xff0c;则 RA 消息会单播回复到客户端的源地址。这种方式减少了网络中的广播流量&#xff0c;…...

LearnOpenGL 学习(入门--三角形,着色器,纹理)

你好&#xff0c;三角形 下面&#xff0c;你会看到一个图形渲染管线的每个阶段的抽象展示。要注意蓝色部分代表的是我们可以注入自定义的着色器的部分。 图形渲染管线的第一个部分是顶点着色器(Vertex Shader)&#xff0c;它把一个单独的顶点作为输入。顶点着色器主要的目的是…...

前端开发入门指南Day12:ES6进阶:面向对象的编程(Class类、继承、模块化)

今天&#xff0c;让我们探索ES6中面向对象编程的革新。想象一下&#xff0c;如果传统的JavaScript是一个手工作坊&#xff0c;那么ES6的类和模块化就是一个现代化工厂&#xff0c;让代码的组织和复用变得更加规范和高效。 一、为什么需要Class类的革新 &#x1f3af; 在ES6之…...

深入探索进程间通信:System V IPC的机制与应用

目录 1、System V概述 2.共享内存&#xff08;shm&#xff09; 2.1 shmget — 创建共享内存 2.1.2 ftok&#xff08;为shmmat创建key值&#xff09; 2.1.3 为什么一块共享内存的标志信息需要用户来传递 2.2 shmat — 进程挂接共享内存 2.3 shmdt — 断开共享内存连接 2.4…...

跨 CA 签发多个证书的 Nginx mTLS 配置

研究过用同一个 CA 签发的服务端和客户端证书的 Nginx mTLS 配置&#xff0c;本文要试验一番服务端和客户端证书由不同 CA 机构签发的情形。这是常有事&#xff0c;比如与客户间采用 mTLS 加密方式&#xff0c;需要文件交付可能是 客户端证书由甲方生成&#xff0c;发送客户端…...

CentOS7 虚拟机 双网卡绑定

一、网卡绑定模式 模式类型特点mode0round-robin&#xff08;平衡轮询策略&#xff09;基于per packet方式&#xff0c;轮询往每条链路发送报文。提供负载均衡和容错的能力&#xff0c;当有链路出问题&#xff0c;会把流量切换到正常的链路上。交换机端需要配置聚合口。mode1a…...

设计模式——方法链or流式接口

方法链或流式接口是一种编程模式或设计模式。核心思想是通过返回对象自身的应用&#xff0c;使得可以在一个表达式中连续调用多个方法。 c中实现这种模式 1.基本语法规则 &#xff08;1&#xff09;每个可链接的方法都返回对象自身的引用&#xff08;通常是*this&#xff09…...

BioDeepAV:一个多模态基准数据集,包含超过1600个深度伪造视频,用于评估深度伪造检测器在面对未知生成器时的性能。

2024-11-29, 由罗马尼亚布加勒斯特大学创建BioDeepAV数据集&#xff0c;它专门设计来评估最先进的深度伪造检测器在面对未见过的深度伪造生成器时的泛化能力&#xff0c;这对于提高检测器的鲁棒性和适应性具有重要意义。 数据集地址&#xff1a;biodeep 一、研究背景&#xff1…...

winform 程序添加API接口

假定你有这么一个winform程序&#xff0c;现在有需求开放一个接口&#xff0c;供外部调用&#xff0c;则你可以这样实现 安装需要的依赖包 Microsoft.AspNetCore.App 2.1.34 Microsoft.Extensions.Hosting 8.0.1使用线程在主窗体loading时候启动webhost publi…...

vscode 怎么下载 vsix 文件?

参考&#xff1a;https://marketplace.visualstudio.com/items?itemNameMarsCode.marscode-extension 更好的办法&#xff1a;直接去相关插件的 github repo 下载老版本 https://github.com/VSCodeVim/Vim/releases?page5 或者&#xff0c;去 open-vsx.org 下载老版本 点击这…...

jupyter-lab 环境构建

我平时用来调试各种代码的。 创建环境&#xff0c;安装库 conda create --name jupyterlab python3.12 -y conda activate jupyterlab conda install -c conda-forge jupyterlab nodejs之前用的是3.10的&#xff0c;但是最近安装的时候&#xff0c;发现3.10的python里面的jup…...

Mysql事务常见面试题 -- 事务的特性 ,并发事务问题 , undo_log和redo_log , 分布式事务

一. 事务的特性 ACID 原子性 --> 事务操作被视为一个整体 , 要么全部成功 , 要么全部失败一致性 --> 事务操作前后数据的变化是一致的隔离性 --> 事务的执行不受其他事务的影响持久性 --> 事务执行完毕会对数据永久保存 比如我们在转账的过程中 , A给B转账1000元…...

C# 线程--Thread类

目录 什么是线程&#xff1f; Thread类的定义 创建和启动线程 使用 ThreadStart 委托 使用 ParameterizedThreadStart 委托 Lambda简写 使用线程池&#xff08;ThreadPool&#xff09; 使用线程池的优点 使用 ThreadPool 的一般步骤 常用方法 Start() Join() Slee…...

【RK3588 Linux 5.x 内核编程】-内核高分辨率定时器

内核高分辨率定时器 文章目录 内核高分辨率定时器1、高分辨率定时器介绍2、高分辨率定时器API2.1 初始化定时器2.2 启动定时器2.3 停止定时器2.4 改变定时器超时时间2.5 定时器状态检查3、驱动实现4、驱动验证在前面的文章中,我们知道了如果在Linux内核中使用定时器。本文将详…...

论文阅读与源码解析:MogaNet

论文阅读与源码解析&#xff1a;MogaNet: Multi-order Gated Aggregation Network 论文地址&#xff1a;https://arxiv.org/pdf/2211.03295 GitHub项目地址&#xff1a;https://github.com/Westlake-AI/MogaNet 源码&#xff1a;https://github.com/Westlake-AI/MogaNet/blob/…...

长、宽数据表格转换

excel数据读取 使用 readxl 包读取 Excel 文件 library(readxl) 读取 Excel 文件&#xff1a; 使用 read_excel() 函数读取 .xlsx 或 .xls 格式的文件。可以选择指定工作表名或工作表索引。 # 读取 Excel 文件的默认工作表 data <- read_excel("path_to_y…...

华为 Mate 70 系列智能手机将运行不兼容 Android 的鸿蒙

华为宣布其 Mate 70 系列新智能手机将搭载不兼容 Android 的 HarmonyOS Next 操作系统。虽然是基于安卓系统的&#xff0c;但是该分叉树将正式分离。以后将不再兼容安卓系统软件。 HarmonyOS Next 可运行的应用数量仍然远远逊于 Android。华为表示 HarmonyOS Next 获得了逾 1.…...

【Halcon】 derivate_gauss

1、derivate_gauss Halcon中的derivate_gauss算子是一个功能强大的图像处理工具,它通过将图像与高斯函数的导数进行卷积,来计算各种图像特征。这些特征在图像分析、物体识别、图像增强等领域具有广泛的应用。 参数解释 Sigma:高斯函数的标准差,用于控制平滑的程度。Sigma…...

原型模式的理解和实践

引言 在软件开发中&#xff0c;我们经常需要创建具有相同属性或状态的对象。如果采用传统的构造函数或工厂模式来创建对象&#xff0c;那么每次创建对象时都需要重新设置对象的属性&#xff0c;这无疑增加了代码的冗余和复杂性。为了解决这一问题&#xff0c;原型模式&#xff…...

封装loding加载动画的请求

图片 /*** Loading 状态管理类*/ export class Loading {constructor(timer300) {this.value falsethis.timer timer}/*** 执行异步操作并自动管理 loading 状态* param {Promise|Function|any} target - Promise、函数或其他值* returns {Promise} - 返回请求结果*/async r…...

特种设备相关管理A全国通用试题

1.下列&#xff08;&#xff09;类型的起重机械的定期检验每年1次。 A.机械式停车设备 B.施工升降机 C.门式起重机 D.桅杆式起重机 答案:B 2.压力容器安全技术监察规程中所指的容积&#xff0c;应为&#xff08; &#xff09;。 A.应当扣除永久连接在压力容器内部的内件…...

ES语法(一)概括

一、语法 1、请求方式 Elasticsearch&#xff08;ES&#xff09;使用基于 JSON 的查询 DSL&#xff08;领域特定语言&#xff09;来与数据交互。 一个 ElasticSearch 请求和任何 HTTP 请求一样由若干相同的部件组成&#xff1a; curl -X<VERB> <PROTOCOL>://&l…...

反射的作用

只要不是写死在程序里的对象的创建和调用&#xff0c;都可以用反射来实现。 例如&#xff0c;依据注解或配置信息动态生成并注入对象的需求场景&#xff0c;生成动态代理的需求场景。...

KARE:知识图谱社区级检索,增强 LLM 推理能力的医疗预测框架

KARE&#xff1a;知识图谱社区级检索&#xff0c;增强 LLM 推理能力的医疗预测框架 论文大纲理解要点全流程分析核心模式解法拆解知识图谱社区检索和普通检索有什么本质区别&#xff1f;为什么要同时使用专家LLM和本地LLM&#xff1f;动态知识检索中的评分机制是如何平衡多个因…...