【HarmonyOS】富文本編輯器RichEditor詳解

【HarmonyOS】富文本編輯器RichEditor詳解

一、前言

在信息化高速發展的今天,普通的文本容器,已經不能夠承載用戶豐富的表達欲。富文本展示已經是移動開發中,必備要解決的問題,在鴻蒙中,通過在系統層提供RichEditor控件,來解決富文本展示的問題。

HarmonyOS推出的RichEditor控件,提供了從基礎文本輸入到復雜圖文混排的完整解決方案。

從API version 10開始支持的RichEditor控件,不僅具備文本輸入、樣式設置等基礎能力,還創新性地支持自定義鍵盤、圖文混排、事件回調等高級特性。

隨著版本迭代,RichEditor不斷進化,從API version 11開始支持元服務調用,到API version 20引入AI菜單和撤銷樣式保留等功能,已發展為一個成熟穩定的富文本解決方案。

本文將從實際使用流程和完整實戰Demo出發,詳細解析RichEditor控件的核心功能與應用場景,幫助開發者快速掌握這一強大工具的使用方法。

二、使用流程

1、組件創建方式

RichEditor控件提供了兩種創建方式:

(1)使用屬性字符串構建

在這里插入圖片描述

這種方式一般用于比較簡單的富文本場景,例如上圖顏色不同的一段話。
基于屬性字符串(StyledString/MutableStyledString)構建,持有屬性字符串對象來管理數據,通過修改屬性字符串對象的內容、樣式,再傳遞給組件,實現對富文本組件內容的更新。
相比于使用controller接口進行內容樣式更新,使用起來更加靈活便捷。


@Entry
@Component
struct Index {// 定義字體樣式對象,設置字體顏色為粉色fontStyle: TextStyle = new TextStyle({fontColor: Color.Pink});// 創建可變樣式字符串,用于存儲富文本內容及其樣式// 初始文本為"使用屬性字符串構建的RichEditor組件"// 并為前5個字符("使用屬性字")應用上面定義的粉色字體樣式mutableStyledString: MutableStyledString = new MutableStyledString("使用屬性字符串構建的RichEditor組件",[{start: 0,          // 樣式起始位置(從0開始)length: 5,         // 樣式作用的字符長度styledKey: StyledStringKey.FONT,  // 樣式類型為字體樣式styledValue: this.fontStyle       // 具體的樣式值}]);// 初始化屬性字符串模式的RichEditor控制器// 該控制器專門用于處理基于屬性字符串的富文本操作controller: RichEditorStyledStringController = new RichEditorStyledStringController();// 配置RichEditor組件的選項,將控制器傳入options: RichEditorStyledStringOptions = { controller: this.controller };build() {Column() {// 構建RichEditor組件,使用上面配置的選項RichEditor(this.options)// 組件初始化完成回調// 當RichEditor組件準備好后,將之前創建的可變樣式字符串設置到編輯器中.onReady(() => {this.controller.setStyledString(this.mutableStyledString);})}.height('100%')  // Column高度占滿整個父容器.width('100%')   // Column寬度占滿整個父容器.justifyContent(FlexAlign.Center)  // 垂直方向居中對齊子組件}
}
(2)使用RichEditorController構建

在這里插入圖片描述

這種方式一般用于復雜內容場景,通過RichEditorController提供的接口實現內容、樣式的管理。


@Entry
@Component
struct IndexPage2 {// 初始化富文本編輯器控制器,用于管理RichEditor組件controller: RichEditorController = new RichEditorController();// 配置RichEditor組件選項,傳入控制器實例options: RichEditorOptions = { controller: this.controller };build() {Column() {Column() {// 創建RichEditor組件并應用配置選項RichEditor(this.options)// 組件初始化完成回調,用于設置初始內容.onReady(() => {// 1. 添加第一段文本內容// 使用addTextSpan方法添加文本,并設置橙色字體、16px大小this.controller.addTextSpan('使用RichEditorController', {style: {fontColor: Color.Orange,fontSize: 16}});// 2. 添加符號內容// 使用addSymbolSpan方法添加系統內置符號(籃球圖標)// 設置符號大小為30pxthis.controller.addSymbolSpan($r("sys.symbol.basketball_fill"), {style: {fontSize: 30}});// 3. 添加第二段文本內容// 使用addTextSpan方法添加文本,并設置紅色字體、20px大小this.controller.addTextSpan('構建富文本!!!', {style: {fontColor: Color.Red,fontSize: 20}});})}.width('100%')  // 內部Column寬度占滿父容器}.height('100%')  // 外部Column高度占滿父容器}
}

2、組件的屬性配置參數效果

RichEditor提供了豐富的屬性來定制編輯體驗,下面介紹幾個常用屬性的配置方法。

(1)自定義選擇菜單

通過bindSelectionMenu屬性可以設置自定義選擇菜單,替代組件默認的文本選擇菜單,實現更豐富的菜單功能,如翻譯、加粗等。

// 自定義菜單構建器
@Builder
CustomMenu() {Column() {Menu() {MenuItemGroup() {MenuItem({startIcon: $r('app.media.icon_bold'),content: "加粗"})MenuItem({startIcon: $r('app.media.icon_italic'),content: "斜體"})MenuItem({startIcon: $r('app.media.icon_underline'),content: "下劃線"})}}.radius(8).backgroundColor(Color.White).width(200)}
}// 在RichEditor中綁定自定義菜單
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('長按觸發自定義菜單', {style: {fontColor: Color.Black,fontSize: 16}})}).bindSelectionMenu(RichEditorSpanType.TEXT, this.CustomMenu, ResponseType.LongPress).width(300).height(200)
(2)光標和手柄顏色設置

通過caretColor屬性可以設置輸入框光標和手柄的顏色,提高視覺辨識度,使光標顏色與應用整體風格相協調。

RichEditor(this.options).onReady(() => {this.controller.addTextSpan('設置了橙色光標和手柄的富文本', {style: {fontColor: Color.Black,fontSize: 16}})}).caretColor(Color.Orange).width(300).height(100)
(3)占位文本設置

通過placeholder屬性可以設置無輸入時的提示文本,引導用戶正確操作。

RichEditor(this.options).placeholder("請輸入您的內容...", {fontColor: Color.Gray,font: {size: 14,family: "HarmonyOS Sans"}}).width(300).height(80)

3、組件的事件監聽與交互控制邏輯

RichEditor提供了豐富的事件監聽接口,實現更靈活的編輯交互邏輯。

(1)初始化完成事件

初始化回調函數,一般在這里進行數據的加載,或者組件文本的拼接等。

RichEditor(this.options).onReady(() => {console.info('RichEditor初始化完成');})
(2)選擇變化事件

內容選擇區域或光標位置變化時觸發,可用于實時更新工具欄狀態。

RichEditor(this.options).onSelectionChange((range) => {console.info(`選中范圍變化: start=${range.start}, end=${range.end}`);// 根據選中范圍更新工具欄按鈕狀態this.updateToolbarState(range);})
(3)粘貼事件

粘貼操作前觸發,可用于自定義粘貼內容處理。

RichEditor(this.options).onPaste((event) => {// 阻止默認粘貼行為event.preventDefault();// 自定義粘貼處理邏輯this.handleCustomPaste(event);})

4、內容操作與管理

通過控制器可以實現對編輯內容的程序化操作。

添加文本內容
// 添加普通文本
this.controller.addTextSpan('新添加的文本內容', {style: {fontSize: 16,fontColor: Color.Blue}
});// 在指定位置添加文本
this.controller.addTextSpan('在指定位置添加的文本', {style: {fontSize: 16,fontStyle: FontStyle.Italic},offset: 10 // 在偏移量10的位置添加
});
5、添加圖片內容
this.controller.addImageSpan($r('app.media.image'), {imageStyle: {size: [300, 200], // 圖片大小objectFit: ImageFit.Contain, // 圖片縮放類型verticalAlign: ImageSpanAlignment.MIDDLE // 垂直對齊方式}
});
6、更新文本樣式
// 更新指定范圍的文本樣式
this.controller.updateSpanStyle({start: 0,end: 5,textStyle: {fontWeight: 700, // 加粗decoration: {type: TextDecorationType.Underline, // 下劃線color: Color.Red}}
});

三、DEMO源碼

DEMO實現了一個富文本編輯器界面,支持字體樣式設置、段落縮進控制、內容選中與編輯等功能,并通過自定義標記生成器實現列表縮進的可視化展示。
在這里插入圖片描述

const canvasWidth = 1000;
const canvasHeight = 100;
const Indentation = 40;// 段落縮進標記生成器類
class LeadingMarginCreator {private settings: RenderingContextSettings = new RenderingContextSettings(true); // 渲染上下文設置private offscreenCanvas: OffscreenCanvas = new OffscreenCanvas(canvasWidth, canvasHeight); // 離屏畫布private offContext: OffscreenCanvasRenderingContext2D = this.offscreenCanvas.getContext("2d", this.settings); // 離屏畫布渲染上下文public static instance: LeadingMarginCreator = new LeadingMarginCreator(); // 單例實例// 獲得字體字號級別(0-4級)public getFontSizeLevel(fontSize: number) {const fontScaled: number = Number(fontSize) / 16; // 字體縮放比例(相對于16px基準)enum FontSizeScaleThreshold {SMALL = 0.9,      // 小字體閾值NORMAL = 1.1,     // 正常字體閾值LEVEL_1_LARGE = 1.2, // 1級大字體閾值LEVEL_2_LARGE = 1.4, // 2級大字體閾值LEVEL_3_LARGE = 1.5  // 3級大字體閾值}let fontSizeLevel: number = 1; // 初始字號級別為1// 根據縮放比例確定字號級別if (fontScaled < FontSizeScaleThreshold.SMALL) {fontSizeLevel = 0;} else if (fontScaled < FontSizeScaleThreshold.NORMAL) {fontSizeLevel = 1;} else if (fontScaled < FontSizeScaleThreshold.LEVEL_1_LARGE) {fontSizeLevel = 2;} else if (fontScaled < FontSizeScaleThreshold.LEVEL_2_LARGE) {fontSizeLevel = 3;} else if (fontScaled < FontSizeScaleThreshold.LEVEL_3_LARGE) {fontSizeLevel = 4;} else {fontSizeLevel = 1;}return fontSizeLevel;}// 獲得縮進級別比例(根據縮進寬度計算比例)public getmarginLevel(width: number) {let marginlevel: number = 1; // 初始縮進比例為1// 根據不同縮進寬度設置對應的比例if (width === 40) {marginlevel = 2.0;} else if (width === 80) {marginlevel = 1.0;} else if (width === 120) {marginlevel = 2/3;} else if (width === 160) {marginlevel = 0.5;} else if (width === 200) {marginlevel = 0.4;}return marginlevel;}// 生成文本標記(將文本轉換為像素圖)public genStrMark(fontSize: number, str: string): PixelMap {this.offContext = this.offscreenCanvas.getContext("2d", this.settings); // 重新獲取渲染上下文this.clearCanvas(); // 清空畫布this.offContext.font = fontSize + 'vp sans-serif'; // 設置字體樣式this.offContext.fillText(str + '.', 0, fontSize * 0.9); // 繪制文本(末尾加點以確保寬度)// 獲取像素圖(根據文本長度計算寬度)return this.offContext.getPixelMap(0, 0, fontSize * (str.length + 1) / 1.75, fontSize);}// 生成方形標記(繪制正方形并轉換為像素圖)public genSquareMark(fontSize: number): PixelMap {this.offContext = this.offscreenCanvas.getContext("2d", this.settings); // 重新獲取渲染上下文this.clearCanvas(); // 清空畫布const coordinate = fontSize * (1 - 1 / 1.5) / 2; // 計算起始坐標const sideLength = fontSize / 1.5; // 計算正方形邊長this.offContext.fillRect(coordinate, coordinate, sideLength, sideLength); // 繪制正方形// 獲取正方形像素圖return this.offContext.getPixelMap(0, 0, fontSize, fontSize);}// 生成圓圈符號標記(根據縮進級別、字體大小等參數繪制圓形標記)public genCircleMark(fontSize: number, width: number, level?: number): PixelMap {const indentLevel = level ?? 1; // 縮進級別(默認1)const offsetLevel = [22, 28, 32, 34, 38]; // 不同字號級別的垂直偏移量const fontSizeLevel = this.getFontSizeLevel(fontSize); // 獲取字號級別const marginlevel = this.getmarginLevel(width); // 獲取縮進比例const newCanvas = new OffscreenCanvas(canvasWidth, canvasHeight); // 創建新的離屏畫布const newOffContext: OffscreenCanvasRenderingContext2D = newCanvas.getContext("2d", this.settings); // 新畫布的渲染上下文const centerCoordinate = 50; // 圓心水平坐標基準const radius = 10; // 圓半徑基準this.clearCanvas(); // 清空畫布// 繪制橢圓(根據參數計算位置和大小)newOffContext.ellipse(100 * (indentLevel + 1) - centerCoordinate * marginlevel, // 圓心x坐標offsetLevel[fontSizeLevel], // 圓心y坐標(根據字號級別)radius * marginlevel, // 水平半徑(根據縮進比例)radius, // 垂直半徑0, 0, 2 * Math.PI // 橢圓參數(起始角度、結束角度));newOffContext.fillStyle = '66FF0000'; // 填充顏色(半透明紅色)newOffContext.fill(); // 填充圖形// 獲取圓形標記的像素圖(根據縮進級別計算寬度)return newOffContext.getPixelMap(0, 0, 100 + 100 * indentLevel, 100);}private clearCanvas() {this.offContext.clearRect(0, 0, canvasWidth, canvasHeight); // 清空畫布}
}@Entry
@Component
struct IndexPage3 {// 富文本控制器(用于操作編輯器內容和樣式)controller: RichEditorController = new RichEditorController();options: RichEditorOptions = { controller: this.controller }; // 富文本編輯器選項// 縮進標記生成器實例(使用單例模式)private leadingMarkCreatorInstance = LeadingMarginCreator.instance;private fontNameRawFile: string = 'MiSans-Bold'; // 自定義字體名稱// 狀態變量(用于界面交互和數據展示)@State fs: number = 30; // 字體大小@State cl: number = Color.Black; // 字體顏色@State start: number = -1; // 選中起始位置@State end: number = -1; // 選中結束位置@State message: string = "[-1, -1]"; // 選中范圍提示信息@State content: string = ""; // 選中內容private leftMargin: Dimension = 0; // 左縮進量private richEditorTextStyle: RichEditorTextStyle = {}; // 富文本樣式// 新增:光標顏色和選中背景色狀態@State cursorColor: Color|string = Color.Black; // 光標顏色@State selectionColor: Color|string = Color.Gray; // 選中背景色aboutToAppear() {// 注冊自定義字體(應用啟動時加載字體文件)this.getUIContext().getFont().registerFont({familyName: 'MiSans-Bold',familySrc: '/font/MiSans-Bold.ttf'});}build() {Scroll() {Column() {// 顏色控制區域(切換界面主題顏色)Row() {Button("紅色主題").onClick(() => {this.cursorColor = Color.Red; // 設置紅色光標this.selectionColor = "#FFCCCC"; // 設置紅色選中背景}).width("30%");Button("綠色主題").onClick(() => {this.cursorColor = Color.Green; // 設置綠色光標this.selectionColor = "#CCFFCC"; // 設置綠色選中背景}).width("30%");Button("藍色主題").onClick(() => {this.cursorColor = Color.Blue; // 設置藍色光標this.selectionColor = "#CCCCFF"; // 設置藍色選中背景}).width("30%");}.width("100%").justifyContent(FlexAlign.SpaceBetween).margin({ bottom: 10 });// 選中范圍和內容顯示區域(展示當前選中的位置和內容)Column() {Text("selection range:").width("100%").fontSize(16); // 選中范圍標題Text() {Span(this.message) // 顯示選中范圍信息}.width("100%").fontSize(16);Text("selection content:").width("100%").fontSize(16); // 選中內容標題Text() {Span(this.content) // 顯示選中內容}.width("100%").fontSize(16);}.borderWidth(1).borderColor(Color.Red).width("100%").padding(10).margin({ bottom: 10 });// 樣式操作按鈕區域(對選中內容進行樣式修改)Row() {Button("加粗").onClick(() => {// 更新選中區域文本樣式(設置為加粗)this.controller.updateSpanStyle({start: this.start,end: this.end,textStyle: { fontWeight: FontWeight.Bolder }});}).width("25%");Button("獲取選中內容").onClick(() => {this.content = ""; // 清空內容顯示// 獲取選中范圍內的所有文本片段this.controller.getSpans({ start: this.start, end: this.end }).forEach(item => {if (typeof(item as RichEditorImageSpanResult)['imageStyle'] !== 'undefined') {// 處理圖片片段this.content += (item as RichEditorImageSpanResult).valueResourceStr + "\n";} else {if (typeof(item as RichEditorTextSpanResult)['symbolSpanStyle'] !== 'undefined') {// 處理符號片段(顯示字號)this.content += (item as RichEditorTextSpanResult).symbolSpanStyle?.fontSize + "\n";} else {// 處理普通文本片段(顯示文本內容)this.content += (item as RichEditorTextSpanResult).value + "\n";}}});}).width("25%");Button("刪除選中內容").onClick(() => {// 刪除選中區域內容this.controller.deleteSpans({ start: this.start, end: this.end });this.start = -1; // 重置選中起始位置this.end = -1; // 重置選中結束位置this.message = "[" + this.start + ", " + this.end + "]"; // 更新選中范圍提示}).width("25%");Button("設置樣式1").onClick(() => {// 設置輸入時的默認樣式this.controller.setTypingStyle({fontWeight: 'medium', // 中等粗細fontFamily: this.fontNameRawFile, // 自定義字體fontColor: Color.Blue, // 藍色fontSize: 50, // 字號50fontStyle: FontStyle.Italic, // 斜體decoration: { type: TextDecorationType.Underline, color: Color.Green } // 綠色下劃線});}).width("25%");}.borderWidth(1).borderColor(Color.Red).width("100%").height("10%").margin({ bottom: 10 });// 富文本編輯器區域(核心編輯界面)Column() {RichEditor(this.options).onReady(() => {// 編輯器準備就緒時初始化內容this.controller.addTextSpan("0123456789\n", {style: {fontWeight: 'medium', // 中等粗細fontFamily: this.fontNameRawFile, // 自定義字體fontColor: Color.Red, // 紅色fontSize: 50, // 字號50fontStyle: FontStyle.Italic, // 斜體decoration: { type: TextDecorationType.Underline, color: Color.Green } // 綠色下劃線}});this.controller.addTextSpan("abcdefg", {style: {fontWeight: FontWeight.Lighter, // 更細fontFamily: 'HarmonyOS Sans', // HarmonyOS默認字體fontColor: 'rgba(0,128,0,0.5)', // 半透明綠色fontSize: 30, // 字號30fontStyle: FontStyle.Normal, // 正常樣式decoration: { type: TextDecorationType.Overline, color: 'rgba(169, 26, 246, 0.50)' } // 半透明紫色上劃線}});}).onSelect((value: RichEditorSelection) => {// 選中事件回調(更新選中范圍狀態)this.start = value.selection[0];this.end = value.selection[1];this.message = "[" + this.start + ", " + this.end + "]";}).caretColor(this.cursorColor)  // 設置光標顏色(來自狀態變量).selectedBackgroundColor(this.selectionColor)  // 設置選中背景色(來自狀態變量).borderWidth(1).borderColor(Color.Green).width("100%").height("30%").margin({ bottom: 10 });}.borderWidth(1).borderColor(Color.Red).width("100%").padding(10);// 縮進操作按鈕區域(控制段落縮進)Column() {Row({ space: 5 }) {Button("向右列表縮進").onClick(() => {let margin = Number(this.leftMargin); // 當前左縮進量if (margin < 200) {margin += Indentation; // 增加縮進量(40像素)this.leftMargin = margin;}// 更新段落樣式(設置帶標記的縮進)this.controller.updateParagraphStyle({start: -10,end: -10,style: {leadingMargin: {pixelMap: this.leadingMarkCreatorInstance.genCircleMark(100, margin, 1), // 圓形縮進標記size: [margin, 40] // 縮進標記大小}}});}).width("48%");Button("向左列表縮進").onClick(() => {let margin = Number(this.leftMargin); // 當前左縮進量if (margin > 0) {margin -= Indentation; // 減少縮進量(40像素)this.leftMargin = margin;}// 更新段落樣式(設置帶標記的縮進)this.controller.updateParagraphStyle({start: -10,end: -10,style: {leadingMargin: {pixelMap: this.leadingMarkCreatorInstance.genCircleMark(100, margin, 1), // 圓形縮進標記size: [margin, 40] // 縮進標記大小}}});}).width("48%");}.margin({ bottom: 10 });Row({ space: 5 }) {Button("向右空白縮進").onClick(() => {let margin = Number(this.leftMargin); // 當前左縮進量if (margin < 200) {margin += Indentation; // 增加縮進量(40像素)this.leftMargin = margin;}// 更新段落樣式(設置純空白縮進)this.controller.updateParagraphStyle({start: -10,end: -10,style: { leadingMargin: margin } // 僅設置縮進寬度});}).width("48%");Button("向左空白縮進").onClick(() => {let margin = Number(this.leftMargin); // 當前左縮進量if (margin > 0) {margin -= Indentation; // 減少縮進量(40像素)this.leftMargin = margin;}// 更新段落樣式(設置純空白縮進)this.controller.updateParagraphStyle({start: -10,end: -10,style: { leadingMargin: margin } // 僅設置縮進寬度});}).width("48%");}.margin({ bottom: 10 });Button("獲取當前樣式").onClick(() => {this.richEditorTextStyle = this.controller.getTypingStyle();console.info("RichEditor getTypingStyle:" + JSON.stringify(this.richEditorTextStyle));}).width("100%").margin({ bottom: 10 });}.width("100%").padding(10);}.width("100%").padding(10);}}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/87956.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/87956.shtml
英文地址,請注明出處:http://en.pswp.cn/web/87956.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【MySQL進階】在一臺機器上運行多個MySQL實例

目錄 1.使用MySQL Installer安裝MySQL實例 1.1.去官網下載MySQL Installer 1.2.停止mysql服務 1.3.為不同的版本指定不同的安裝目錄 2.配置不同版本的選項文件 2.1.修改數據目錄 2.2.修改基本目錄 2.3.修改端口號 2.4.設置?志?錄 2.5.配置臨時目錄 2.6.修改綁定地…

verilog中timescale指令的使用

1.timescale指令格式timescale <時間單位> / <時間精度>時間單位&#xff1a;它確定了仿真中時間值的基本單位。比如 1ns 就意味著時間值是以納秒為單位來計量的。 時間精度&#xff1a;該參數決定了時間值能夠表示的最小分辨率。例如 1ps 表示時間可以精確到皮秒級…

08_Excel 導入 - 用戶信息批量導入

08_Excel 導入 - 用戶信息批量導入 1. VO 類 java復制編輯Data AllArgsConstructor NoArgsConstructor public class UserInfoBatch4ExcelReq {ExcelProperty(value "用戶姓名")Schema(description "用戶姓名")private String userName;ExcelProperty(va…

【深度學習新浪潮】什么是世界模型?

世界模型(World Model)是人工智能領域中一類通過構建環境的抽象表示來理解和預測外部世界的系統。它通過整合多模態數據(如視覺、語言、傳感器信號)形成對環境的動態認知,并支持智能體在復雜場景中進行決策與規劃。以下從核心概念、解決的問題、關鍵研究、技術路線、現狀與…

React + Express 傳輸加密以及不可逆加密

一、傳輸加密這里用 對稱加密模式 ASE實現。React 前端const CryptoJS require("crypto-js");// 示例1&#xff1a;ECB模式&#xff08;無需IV&#xff09; const encryptECB (plainText, key) > {return CryptoJS.AES.encrypt(plainText, key, {mode: CryptoJS…

瀏覽器(Chrome /Edge)高效使用 - 內部命令/快捷鍵/啟動參數

今天在CSDN上傳文件,提交總是提示續傳失敗,重試了五六次才想到獲取是科學上網的問題,這個時候其實只要重啟瀏覽器即可,但如果手動關閉瀏覽器再次打開,瀏覽器不會恢復之前的多開窗口(會恢復最后一個窗口內多開的標簽頁,但不會恢復其他窗口)。想了想記得 Chrome 流行的時…

【PTA數據結構 | C語言版】連續子序列最大和

本專欄持續輸出數據結構題目集&#xff0c;歡迎訂閱。 文章目錄 題目代碼 題目 給定 n 個整數組成的序列 { a1 ,a2 ,?,an }&#xff0c;“連續子序列”被定義為 { ai ,ai1 ,?,aj }&#xff0c;其中 1≤i≤j≤n。“連續子序列最大和”則被定義為所有連續子序列元素的和中最大…

Vrrp配置和原理

Vrrp配置和原理 文章目錄Vrrp配置和原理概述物理與邏輯拓撲重點vrid虛擬路由器虛擬IP地址及虛擬MAC地址超時時間計算-MASTER_DOWNvip 管理員手動指定方法Master路由器Backup路由器PriorityVRRP報文格式VRRP狀態機從Backup到masterVRRP協議狀態二.優先級一樣比較接口IPVRRP優先級…

可編輯59頁PPT | 某大型集團人工智能數字化轉型SAP解決方案

薦言摘要&#xff1a;某大型集團人工智能數字化轉型中&#xff0c;SAP解決方案扮演著智能中樞角色&#xff0c;深度融合AI技術與核心業務場景&#xff0c;破解傳統系統“數據孤島流程僵化”雙重困局。針對集團跨產業、多業態特點&#xff0c;方案以SAP S/4HANA為數據底座&#…

【RK3568 驅動開發:實現一個最基礎的網絡設備】

RK3568 驅動開發&#xff1a;實現一個最基礎的網絡設備一、引言二、編寫網絡設備驅動代碼1. 核心數據結構與接口2. 核心功能實現3. 網絡命名空間管理4.源代碼三、編譯與驗證1.加載模塊2.驗證網絡四、注意事項一、引言 RK3568 作為一款高性能 ARM 架構處理器&#xff0c;廣泛應…

CAIDCP系列對話:AI 驅動安全

數字時代&#xff0c;AI浪潮翻涌&#xff0c;網絡安全攻防戰已悄然升級&#xff1a; 某工業控制系統遭AI驅動勒索攻擊&#xff1a;攻擊者借 AI 精準捕捉異常網絡掃描、遠程 PowerShell 痕跡&#xff0c;瞬間加密文件索要贖金&#xff1b; 另一邊&#xff0c;某大型科技公司用AI…

ARMv8 沒開mmu執行memset引起的非對齊訪問異常

最近在haps上驗證一個新的芯片&#xff0c;記錄一下memset訪問出錯的問題。在沒開mmu和cache的情況下&#xff0c;對全局變量指針進行memset清零操作&#xff0c;發現每次都會出現異常。最后發現是沒開mmu導致出現了數據非對齊訪問導致報錯。排查EC區域發現是0x25&#xff0c;產…

基于LiveKit Go 實現騰訊云實時音視頻功能

詳細的生產部署建議&#xff0c;適用于 LiveKit Go 服務器 Web 客戶端 TURN/HTTPS。 1. 服務器準備 推薦使用云服務器&#xff08;如阿里云、騰訊云、AWS、Azure等&#xff09;&#xff0c;公網IP&#xff0c;帶寬建議≥10Mbps。系統推薦 Ubuntu 20.04/22.04 或 CentOS 7/8&…

三位一體:Ovis-U1如何以30億參數重構多模態AI格局?

1. 時代命題&#xff1a;多模態統一模型的破局之戰當GPT-4o以萬億級參數構建多模態帝國時&#xff0c;中國AI軍團正在書寫另一種答案。Ovis-U1用30億參數證明&#xff1a;參數量并非決定性因素&#xff0c;架構創新與訓練策略的化學反應&#xff0c;同樣能催生出改變游戲規則的…

圖像處理基礎:鏡像、縮放與矯正

在圖像處理中&#xff0c;鏡像、縮放和矯正操作是常見的圖像變換手段。這些操作可以幫助我們對圖像進行調整&#xff0c;以滿足不同的需求。本文將詳細介紹這三種操作的原理和實現方法&#xff0c;并通過代碼示例展示它們的實際應用。一、圖片鏡像旋轉1.1 什么是鏡像旋轉&#…

「Java案例」猜數游戲

案例實現 猜數字游戲 設計一個三位數的猜數游戲,三位數隨機生成。程序提示用戶輸入一個三位的數字,依照以下的規則決定贏取多少獎金:1) 如果用戶輸入的數字和隨機數字完全一致,輸出:“恭喜恭喜!完全猜對了!獲得三個贊!”2) 如果用戶輸入的數字覆蓋了隨機生成的所有數…

創客匠人解析創始人 IP 內卷:知識變現時代的生存邏輯與破局路徑

當知識付費行業進入 “存量競爭” 階段&#xff0c;創始人 IP 的 “內卷” 已非選擇而是必然。創客匠人在服務數萬知識創業者的實踐中發現&#xff0c;那些實現逆勢增長的案例&#xff0c;其核心差異往往在于創始人是否具備 “從幕后走到臺前” 的決心與能力 —— 這種內卷并非…

250705-Debian12-sudo apt update加速+配置RDP遠程桌面環境+設置FRP服務為開機啟動項

A. 實現sudo apt update加速 在 Debian 12 上運行 sudo apt update 很慢的常見原因包括&#xff1a; &#x1f50d; 一、常見原因分析 使用了國外的軟件源 默認 Debian 安裝源多數是國際服務器&#xff0c;國內訪問會非常慢。 DNS 解析慢或失敗 軟件源地址解析時間長&#xf…

數學視頻動畫引擎Python庫 -- Manim Voiceover 語音服務 Speech Services

文中內容僅限技術學習與代碼實踐參考&#xff0c;市場存在不確定性&#xff0c;技術分析需謹慎驗證&#xff0c;不構成任何投資建議。 Manim Voiceover 是一個為 Manim 打造的專注于語音旁白的插件&#xff1a; 直接在 Python 中添加語音旁白&#xff1a; 無需使用視頻編輯器&…

C++11 forward_list 從基礎到精通:原理、實踐與性能優化

文章目錄一、為什么需要 forward_list&#xff1f;二、基礎篇&#xff1a;forward_list 的核心特性與接口2.1 數據結構與迭代器2.2 常用接口速覽2.3 基礎操作示例&#xff1a;從初始化到遍歷2.3.1 初始化與遍歷2.3.2 插入與刪除&#xff1a;before_begin 的關鍵作用三、進階篇&…