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

Android Compose 切换按钮深度剖析:从源码到实践(六)

Android Compose 切换按钮深度剖析:从源码到实践

一、引言

在现代 Android 应用开发中,用户交互体验至关重要。切换按钮(Toggle Button)作为一种常见的交互组件,允许用户在两种状态之间进行切换,例如开 / 关、选中 / 未选中等。Android Compose 作为 Google 推出的声明式 UI 工具包,为开发者提供了便捷的方式来创建和定制切换按钮。本文将深入 Android Compose 框架的切换按钮模块,从源码级别进行详细分析,帮助开发者更好地理解和运用切换按钮,提升应用的交互体验。

二、Android Compose 基础回顾

2.1 Compose 简介

Android Compose 是用于构建 Android UI 的现代工具包,它采用声明式编程范式,与传统的基于视图的 UI 系统相比,代码更加简洁、易于维护。通过使用可组合函数(Composable Functions),开发者可以描述 UI 的外观和行为,Compose 会自动处理布局和状态管理。

2.2 核心概念

2.2.1 可组合函数(@Composable)

可组合函数是 Compose 的核心概念,使用 @Composable 注解标记的函数可以用来构建 UI。这些函数可以调用其他可组合函数,从而构建出复杂的 UI 界面。

kotlin

import androidx.compose.runtime.Composable
import androidx.compose.material.Text// 简单的可组合函数,显示文本
@Composable
fun SimpleText() {Text(text = "Hello, Compose!")
}
2.2.2 状态管理

Compose 提供了强大的状态管理机制,通过 mutableStateOf 函数可以创建可变状态。当状态发生变化时,Compose 会自动重新组合受影响的 UI 部分。

kotlin

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.material.Text@Composable
fun StatefulText() {// 创建可变状态,初始值为 "Hello"var text by mutableStateOf("Hello")// 显示文本Text(text = text)// 模拟状态变化text = "World"
}

三、切换按钮概述

3.1 切换按钮的作用

切换按钮在 Android 应用中广泛应用,用于让用户在两种状态之间进行快速切换。常见的使用场景包括开关功能、选择模式等。

3.2 Android Compose 中的切换按钮组件

在 Android Compose 中,主要有以下几种切换按钮组件:

  • Switch:经典的开关样式切换按钮。
  • Checkbox:复选框样式的切换按钮。
  • RadioButton:单选框样式的切换按钮。

3.3 简单示例

以下是一个简单的 Switch 组件示例:

kotlin

import androidx.compose.material.Switch
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable@Composable
fun SimpleSwitch() {// 创建可变状态,用于记录开关状态var isChecked by mutableStateOf(false)Switch(checked = isChecked,onCheckedChange = { isChecked = it })
}

四、Switch 组件源码分析

4.1 Switch 组件定义

Switch 组件的定义位于 androidx.compose.material 包中,以下是简化后的源码:

kotlin

@Composable
fun Switch(checked: Boolean, // 当前开关状态onCheckedChange: (Boolean) -> Unit, // 状态改变时的回调函数modifier: Modifier = Modifier, // 修饰符,用于修改组件的外观和行为enabled: Boolean = true, // 组件是否可用colors: SwitchColors = SwitchDefaults.colors() // 开关的颜色设置
) {// 使用 Clickable 修饰符处理点击事件val interactionSource = remember { MutableInteractionSource() }val semanticsProperties = {SemanticsProperties.CheckableState provides CheckableState(checked)SemanticsProperties.ToggleableState provides ToggleableState(checked)SemanticsProperties.OnClickLabel provides if (checked) "Turn off" else "Turn on"}Box(modifier = modifier.clickable(interactionSource = interactionSource,indication = rememberRipple(bounded = false),enabled = enabled,onClick = { onCheckedChange(!checked) }).semantics(mergeDescendants = true, properties = semanticsProperties).then(Modifier.size(SwitchDefaults.SwitchWidth, SwitchDefaults.SwitchHeight))) {// 绘制开关轨道val trackColor = colors.trackColor(enabled = enabled, checked = checked).valueCanvas(modifier = Modifier.fillMaxSize().padding(SwitchDefaults.TrackPadding)) {drawRoundRect(color = trackColor,cornerRadius = SwitchDefaults.TrackCornerRadius)}// 绘制开关拇指val thumbColor = colors.thumbColor(enabled = enabled, checked = checked).valueval thumbOffset = animateFloatAsState(targetValue = if (checked) SwitchDefaults.ThumbCheckedOffset else SwitchDefaults.ThumbUncheckedOffset,animationSpec = tween(durationMillis = SwitchDefaults.AnimationDuration))Canvas(modifier = Modifier.size(SwitchDefaults.ThumbSize).offset(x = thumbOffset.value).align(Alignment.CenterStart)) {drawCircle(color = thumbColor,radius = SwitchDefaults.ThumbRadius)}}
}

4.2 点击事件处理

Switch 组件使用 Clickable 修饰符处理点击事件。当用户点击开关时,会调用 onCheckedChange 回调函数,将新的开关状态传递给该函数。

kotlin

modifier.clickable(interactionSource = interactionSource,indication = rememberRipple(bounded = false),enabled = enabled,onClick = { onCheckedChange(!checked) }
)

4.3 状态动画

在开关状态切换时,使用 animateFloatAsState 函数实现拇指的动画效果。通过设置不同的目标值(SwitchDefaults.ThumbCheckedOffset 和 SwitchDefaults.ThumbUncheckedOffset),并指定动画规格(tween),实现平滑的动画过渡。

kotlin

val thumbOffset = animateFloatAsState(targetValue = if (checked) SwitchDefaults.ThumbCheckedOffset else SwitchDefaults.ThumbUncheckedOffset,animationSpec = tween(durationMillis = SwitchDefaults.AnimationDuration)
)

4.4 颜色设置

Switch 组件使用 SwitchColors 来设置开关的颜色,包括轨道颜色和拇指颜色。可以通过 SwitchDefaults.colors() 方法获取默认的颜色设置,也可以自定义颜色。

kotlin

val trackColor = colors.trackColor(enabled = enabled, checked = checked).value
val thumbColor = colors.thumbColor(enabled = enabled, checked = checked).value

五、Checkbox 组件源码分析

5.1 Checkbox 组件定义

Checkbox 组件的定义如下:

kotlin

@Composable
fun Checkbox(checked: Boolean, // 当前复选框状态onCheckedChange: ((Boolean) -> Unit)?, // 状态改变时的回调函数modifier: Modifier = Modifier, // 修饰符enabled: Boolean = true, // 组件是否可用colors: CheckboxColors = CheckboxDefaults.colors() // 复选框的颜色设置
) {val interactionSource = remember { MutableInteractionSource() }val semanticsProperties = {SemanticsProperties.CheckableState provides CheckableState(checked)SemanticsProperties.ToggleableState provides ToggleableState(checked)SemanticsProperties.OnClickLabel provides if (checked) "Uncheck" else "Check"}Box(modifier = modifier.clickable(interactionSource = interactionSource,indication = rememberRipple(bounded = false),enabled = enabled && onCheckedChange != null,onClick = { onCheckedChange?.invoke(!checked) }).semantics(mergeDescendants = true, properties = semanticsProperties).then(Modifier.size(CheckboxDefaults.Size))) {// 绘制复选框背景val boxColor = colors.boxColor(enabled = enabled, checked = checked).valueCanvas(modifier = Modifier.fillMaxSize().padding(CheckboxDefaults.InnerPadding)) {drawRoundRect(color = boxColor,cornerRadius = CheckboxDefaults.CornerRadius)}// 绘制复选框选中标记if (checked) {val checkmarkColor = colors.checkmarkColor(enabled = enabled, checked = checked).valueCanvas(modifier = Modifier.fillMaxSize().padding(CheckboxDefaults.InnerPadding)) {drawPath(path = Path().apply {moveTo(size.width * 0.2f, size.height * 0.5f)lineTo(size.width * 0.4f, size.height * 0.7f)lineTo(size.width * 0.8f, size.height * 0.3f)},color = checkmarkColor,strokeWidth = CheckboxDefaults.CheckmarkStrokeWidth)}}}
}

5.2 点击事件处理

与 Switch 类似,Checkbox 也使用 Clickable 修饰符处理点击事件。当用户点击复选框时,会调用 onCheckedChange 回调函数。

kotlin

modifier.clickable(interactionSource = interactionSource,indication = rememberRipple(bounded = false),enabled = enabled && onCheckedChange != null,onClick = { onCheckedChange?.invoke(!checked) }
)

5.3 绘制逻辑

Checkbox 组件的绘制分为两部分:背景和选中标记。当复选框被选中时,会绘制选中标记;未选中时,只绘制背景。

kotlin

// 绘制背景
val boxColor = colors.boxColor(enabled = enabled, checked = checked).value
drawRoundRect(color = boxColor,cornerRadius = CheckboxDefaults.CornerRadius
)// 绘制选中标记
if (checked) {val checkmarkColor = colors.checkmarkColor(enabled = enabled, checked = checked).valuedrawPath(path = Path().apply {moveTo(size.width * 0.2f, size.height * 0.5f)lineTo(size.width * 0.4f, size.height * 0.7f)lineTo(size.width * 0.8f, size.height * 0.3f)},color = checkmarkColor,strokeWidth = CheckboxDefaults.CheckmarkStrokeWidth)
}

5.4 颜色设置

Checkbox 组件使用 CheckboxColors 来设置背景颜色和选中标记颜色。可以通过 CheckboxDefaults.colors() 方法获取默认的颜色设置,也可以自定义颜色。

kotlin

val boxColor = colors.boxColor(enabled = enabled, checked = checked).value
val checkmarkColor = colors.checkmarkColor(enabled = enabled, checked = checked).value

六、RadioButton 组件源码分析

6.1 RadioButton 组件定义

kotlin

@Composable
fun RadioButton(selected: Boolean, // 当前单选框是否选中onClick: (() -> Unit)?, // 点击事件回调函数modifier: Modifier = Modifier, // 修饰符enabled: Boolean = true, // 组件是否可用colors: RadioButtonColors = RadioButtonDefaults.colors() // 单选框的颜色设置
) {val interactionSource = remember { MutableInteractionSource() }val semanticsProperties = {SemanticsProperties.SelectableState provides SelectableState(selected)SemanticsProperties.OnClickLabel provides if (selected) "Unselect" else "Select"}Box(modifier = modifier.clickable(interactionSource = interactionSource,indication = rememberRipple(bounded = false),enabled = enabled && onClick != null,onClick = onClick).semantics(mergeDescendants = true, properties = semanticsProperties).then(Modifier.size(RadioButtonDefaults.Size))) {// 绘制单选框外圈val outerColor = colors.unselectedColor(enabled = enabled).valueCanvas(modifier = Modifier.fillMaxSize().padding(RadioButtonDefaults.OuterPadding)) {drawCircle(color = outerColor,radius = RadioButtonDefaults.OuterRadius)}// 绘制单选框内圈if (selected) {val innerColor = colors.selectedColor(enabled = enabled).valueCanvas(modifier = Modifier.fillMaxSize().padding(RadioButtonDefaults.InnerPadding)) {drawCircle(color = innerColor,radius = RadioButtonDefaults.InnerRadius)}}}
}

6.2 点击事件处理

RadioButton 同样使用 Clickable 修饰符处理点击事件。当用户点击单选框时,会调用 onClick 回调函数。

kotlin

modifier.clickable(interactionSource = interactionSource,indication = rememberRipple(bounded = false),enabled = enabled && onClick != null,onClick = onClick
)

6.3 绘制逻辑

RadioButton 组件的绘制分为外圈和内圈。当单选框被选中时,会绘制内圈;未选中时,只绘制外圈。

kotlin

// 绘制外圈
val outerColor = colors.unselectedColor(enabled = enabled).value
drawCircle(color = outerColor,radius = RadioButtonDefaults.OuterRadius
)// 绘制内圈
if (selected) {val innerColor = colors.selectedColor(enabled = enabled).valuedrawCircle(color = innerColor,radius = RadioButtonDefaults.InnerRadius)
}

6.4 颜色设置

RadioButton 组件使用 RadioButtonColors 来设置外圈和内圈的颜色。可以通过 RadioButtonDefaults.colors() 方法获取默认的颜色设置,也可以自定义颜色。

kotlin

val outerColor = colors.unselectedColor(enabled = enabled).value
val innerColor = colors.selectedColor(enabled = enabled).value

七、切换按钮的样式定制

7.1 自定义颜色

可以通过自定义 SwitchColorsCheckboxColors 和 RadioButtonColors 来改变切换按钮的颜色。

7.1.1 自定义 Switch 颜色

kotlin

import androidx.compose.material.Switch
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.material.SwitchDefaults@Composable
fun CustomColorSwitch() {var isChecked by mutableStateOf(false)Switch(checked = isChecked,onCheckedChange = { isChecked = it },colors = SwitchDefaults.colors(checkedThumbColor = Color.Red,checkedTrackColor = Color.Blue,uncheckedThumbColor = Color.Green,uncheckedTrackColor = Color.Yellow))
}
7.1.2 自定义 Checkbox 颜色

kotlin

import androidx.compose.material.Checkbox
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.material.CheckboxDefaults@Composable
fun CustomColorCheckbox() {var isChecked by mutableStateOf(false)Checkbox(checked = isChecked,onCheckedChange = { isChecked = it },colors = CheckboxDefaults.colors(checkedColor = Color.Red,uncheckedColor = Color.Blue,checkmarkColor = Color.Green))
}
7.1.3 自定义 RadioButton 颜色

kotlin

import androidx.compose.material.RadioButton
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.material.RadioButtonDefaults@Composable
fun CustomColorRadioButton() {var isSelected by mutableStateOf(false)RadioButton(selected = isSelected,onClick = { isSelected = !isSelected },colors = RadioButtonDefaults.colors(selectedColor = Color.Red,unselectedColor = Color.Blue))
}

7.2 自定义大小

可以使用 Modifier.size 修饰符来改变切换按钮的大小。

7.2.1 自定义 Switch 大小

kotlin

import androidx.compose.material.Switch
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp@Composable
fun CustomSizeSwitch() {var isChecked by mutableStateOf(false)Switch(checked = isChecked,onCheckedChange = { isChecked = it },modifier = Modifier.size(50.dp, 25.dp))
}
7.2.2 自定义 Checkbox 大小

kotlin

import androidx.compose.material.Checkbox
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp@Composable
fun CustomSizeCheckbox() {var isChecked by mutableStateOf(false)Checkbox(checked = isChecked,onCheckedChange = { isChecked = it },modifier = Modifier.size(30.dp))
}
7.2.3 自定义 RadioButton 大小

kotlin

import androidx.compose.material.RadioButton
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp@Composable
fun CustomSizeRadioButton() {var isSelected by mutableStateOf(false)RadioButton(selected = isSelected,onClick = { isSelected = !isSelected },modifier = Modifier.size(30.dp))
}

7.3 自定义形状

虽然切换按钮默认是圆形或矩形,但可以通过自定义绘制逻辑来改变其形状。以下是一个自定义形状的 Switch 示例:

kotlin

import androidx.compose.material.Switch
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirectionclass CustomSwitchShape : Shape {override fun createOutline(size: Size,layoutDirection: LayoutDirection,density: Density): Outline {// 自定义形状逻辑,这里简单返回一个矩形return Outline.Rectangle(androidx.compose.ui.geometry.Rect(0f, 0f, size.width, size.height))}
}@Composable
fun CustomShapeSwitch() {var isChecked by mutableStateOf(false)Switch(checked = isChecked,onCheckedChange = { isChecked = it },modifier = Modifier.clip(CustomSwitchShape()))
}

八、切换按钮的交互处理

8.1 点击事件处理

如前面源码分析所述,切换按钮通过 Clickable 修饰符处理点击事件。可以在 onCheckedChange 或 onClick 回调函数中处理点击逻辑。

kotlin

import androidx.compose.material.Switch
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable
import android.widget.Toast
import androidx.compose.ui.platform.LocalContext@Composable
fun ClickableSwitch() {val context = LocalContext.currentvar isChecked by mutableStateOf(false)Switch(checked = isChecked,onCheckedChange = {isChecked = itToast.makeText(context, "Switch state changed: $it", Toast.LENGTH_SHORT).show()})
}

8.2 状态管理

切换按钮的状态通常使用 mutableStateOf 来管理。当状态发生变化时,Compose 会自动重新组合 UI。

kotlin

import androidx.compose.material.Checkbox
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable@Composable
fun StateManagedCheckbox() {var isChecked by mutableStateOf(false)Checkbox(checked = isChecked,onCheckedChange = { isChecked = it })
}

8.3 分组管理(RadioButton)

RadioButton 通常用于分组选择,同一组的 RadioButton 只能有一个被选中。可以通过状态管理来实现分组功能。

kotlin

import androidx.compose.material.RadioButton
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable
import androidx.compose.foundation.layout.Column@Composable
fun RadioButtonGroup() {val options = listOf("Option 1", "Option 2", "Option 3")var selectedOption by mutableStateOf(options[0])Column {options.forEach { option ->RadioButton(selected = option == selectedOption,onClick = { selectedOption = option })}}
}

九、切换按钮的性能优化

9.1 避免不必要的重新组合

可以使用 remember 函数缓存计算结果,避免每次重新组合时都进行重复计算。

kotlin

import androidx.compose.material.Switch
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember@Composable
fun OptimizedSwitch() {var isChecked by mutableStateOf(false)val colors = remember {SwitchDefaults.colors(checkedThumbColor = Color.Red,checkedTrackColor = Color.Blue,uncheckedThumbColor = Color.Green,uncheckedTrackColor = Color.Yellow)}Switch(checked = isChecked,onCheckedChange = { isChecked = it },colors = colors)
}

9.2 减少组件嵌套

过多的组件嵌套会增加布局的复杂度,影响性能。可以尽量减少不必要的组件嵌套。

kotlin

// 不推荐的写法,嵌套过多
@Composable
fun NestedSwitch() {Box {Switch(checked = false,onCheckedChange = {})}
}// 推荐的写法,减少嵌套
@Composable
fun OptimizedNestedSwitch() {Switch(checked = false,onCheckedChange = {})
}

十、切换按钮的异常处理

10.1 空指针异常

在使用切换按钮时,要确保 onCheckedChange 或 onClick 回调函数不为空。

kotlin

// 错误示例,传入 null 作为 onCheckedChange 参数
// Switch(
//     checked = false,
//     onCheckedChange = null
// )// 正确示例,传入有效的 onCheckedChange 回调函数
Switch(checked = false,onCheckedChange = { /* 处理状态变化 */ }
)

10.2 状态不一致问题

在多线程或复杂状态管理场景下,可能会出现状态不一致的问题。可以使用 mutableStateOf 结合 LaunchedEffect 来确保状态更新的一致性。

kotlin

import androidx.compose.material.Switch
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import kotlinx.coroutines.delay@Composable
fun ConsistentStateSwitch() {var isChecked by mutableStateOf(false)LaunchedEffect(isChecked) {// 模拟异步操作delay(1000)// 更新状态isChecked = !isChecked}Switch(checked = isChecked,onCheckedChange = { isChecked = it })
}

十一、切换按钮的扩展和定制

11.1 自定义切换按钮组件

可以通过组合现有的组件来创建自定义的切换按钮组件。以下是一个带有文本标签的 Switch 组件示例:

kotlin

import androidx.compose.material.Switch
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable
import androidx.compose.foundation.layout.Row
import androidx.compose.material.Text@Composable
fun LabeledSwitch(label: String) {var isChecked by mutableStateOf(false)Row {Switch(checked = isChecked,onCheckedChange = { isChecked = it })Text(text = label)}
}

11.2 自定义交互效果

可以通过自定义 Indication 来实现自定义的交互效果。以下是一个带有自定义涟漪效果的 Checkbox 示例:

kotlin

import androidx.compose.material.Checkbox
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.unit.IntSize
import kotlinx.coroutines.launch@Composable
fun CustomIndicationCheckbox() {var isChecked by mutableStateOf(false)var layoutCoordinates: LayoutCoordinates? = nullCheckbox(checked = isChecked,onCheckedChange = { isChecked = it },modifier = Modifier.onGloballyPositioned { layoutCoordinates = it }.pointerInput(Unit) {detectTapGestures(onPress = { offset ->val size = layoutCoordinates?.size ?: IntSize.Zerolaunch {// 模拟自定义涟漪效果for (i in 0..100) {val alpha = 1f - i / 100f// 绘制自定义涟漪drawCustomRipple(alpha, offset, size)kotlinx.coroutines.delay(10)}}})})
}fun DrawScope.drawCustomRipple(alpha: Float, center: Offset, size: IntSize) {drawCircle(color = Color.Red.copy(alpha = alpha),radius = size.maxDimension.toFloat(),center = center)
}

十二、总结与展望

12.1 总结

通过对 Android Compose 框架中切换按钮(SwitchCheckboxRadioButton)的源码分析,我们深入了解了它们的实现原理、交互处理、样式定制和性能优化等方面的知识。切换按钮作为常见的交互组件,在 Android 应用中起着重要的作用。借助 Compose 的声明式编程范式和强大的状态管理机制,开发者可以轻松创建和定制切换按钮,提升应用的交互体验。

相关文章:

Android Compose 切换按钮深度剖析:从源码到实践(六)

Android Compose 切换按钮深度剖析:从源码到实践 一、引言 在现代 Android 应用开发中,用户交互体验至关重要。切换按钮(Toggle Button)作为一种常见的交互组件,允许用户在两种状态之间进行切换,例如开 /…...

挖矿病毒应急响应处置手册

挖矿病毒应急响应处置手册 文章目录 挖矿病毒应急响应处置手册0x00 概述0x01 了解基本情况1.1 如何发现1.1.1 异常外联1.1.2 主机异常1.2 事件的时间节点1.3 临时处置情况1.4 网络拓扑情况0x02 判断是否属于挖矿2.1 属于挖矿2.1.1 根据告警和流量信息初步判断挖矿类型2.1.2 win…...

VSCode - 查看 PDF 文件

VSCode 原生并不支持 查看 PDF 文件,需要额外安装插件。 这里我使用 vscode-pdf,效果还不错,有需要的可以搜索安装。 效果: 2025-03-18(二)...

vue3:八、登录界面实现-忘记密码

该文章实现登录界面的忘记密码功能,点击忘记密码文本,打开dialog对话框 一、页面效果 加入忘记密码,在记住密码的同一行中,实现flex-between 二、对话框实现 1、新建组件页面 2、引入dialog组件到组件页面 参考路径 Dialog 对…...

Python Django入门(创建其他网页)

在本章中,你将学习如何使用 Django(http://djangoproject.com/ )来开发一个名为“学习笔记”(Learning Log)的项目,这是一个在线日志系统,让你能够记录所学习的有关特定主题的知识。 我们将为这…...

Windows安装MySQL5.7.26教程图解

Windows安装MySQL5.7.26教程图解 零、准备工作 下载MySQL软件包 ①、官网下载:程序员 常用 软件汇总 - 超人那个超~ - 博客园 ②、百度云下载:链接:百度网盘 请输入提取码 提取码:chao 一、彻底删除MySQL 从电脑里卸载旧的MYSQL数据库服务时,首先先在WINDOWS服务里…...

FreGS: 3D Gaussian Splatting with Progressive Frequency Regularization论文学习记录

3. 提出的方法 我们提出了FreGS,一种具有渐进频率正则化的新型3D高斯溅射方法,它是首个从频率角度缓解3D高斯溅射过度重建问题的方法。图2展示了FreGS的概览。第3.1节简要介绍了原始的3D高斯溅射方法(3D-GS),包括高斯…...

汽车行业敏捷开发实践:基于Atlassian工具链的全流程解决方案(Jira、Confluence、Jira Service Management等)

直播回顾 在数字化浪潮席卷全球的今天,各行各业都在积极寻求转型与突破,汽车行业也不例外。 近日,在“Atlassian助力企业破局:数字化协作与全球市场拓展”的线上直播活动中,龙智资深顾问张晓乐深入探讨了汽车行业数字…...

遇到一个奇怪问题,页面请求不到后端

背景 页面有两个请求,第一个接口获取令牌,第二个接口根据令牌去获取数据, 突然发现获取数据接口校验令牌的时候一直报错 而且报错的时候服务器没有获取令牌请求 而且发现偶尔是正常的,正常的发现服务器ip和异常的不一样,同事定位可能是域名解析问题 解决 最后定位是腾讯cdn解…...

【C++】:C++11详解 —— 线程库

目录 线程库(thread) 线程对象的构造函数 构造函数的用法示例 参数传递的关键细节 构造函数的异常行为 线程对象的使用 互斥量库(mutex) 互斥量类型 锁管理类(RAII 封装) 条件变量(…...

招聘面试季--一文顿悟,Java中字节流和字符流的区别及使用场景上的差异

‌一、核心区别‌ ‌特性‌‌字节流‌‌字符流‌‌数据单位‌以字节(8-bit)为单位处理数据(如0xA1)以字符(16-bit Unicode)为单位处理数据(如A, 你)‌基类‌InputStream / OutputSt…...

在 ARM 嵌入式 Linux 下使用 C/C++ 实现 MQTT

在 ARM 嵌入式 Linux 下使用 C/C 实现 MQTT 通信是一个常见的需求,尤其是在资源受限的环境中。以下是一个详细的教程,使用 Eclipse Paho C Client 库来实现 MQTT 客户端。 1. 安装 Eclipse Paho C Client 库 Eclipse Paho C Client 是一个轻量级的 MQTT…...

C++20 中 `constexpr` 的强大扩展:算法、工具与复数库的变革

文章目录 一、constexpr 在 <algorithm> 中的应用1. 编译时排序2. 编译时查找 二、constexpr 在 <utility> 中的应用1. 编译时交换2. 编译时条件交换 三、constexpr 在 <complex> 中的应用1. 编译时复数运算 四、总结 C20 对 constexpr 的增强是其最引人注目…...

C++ 介绍STL底层一些数据结构

c 标准模板库中&#xff0c;set和map的底层实现通常基于红黑树&#xff0c;然们都是平衡二叉搜索树(Balanceed Binary Serach Tree&#xff09;的一种,这种结构保证了 插入&#xff0c;删除&#xff0c;查找的时间复杂度为O(log n)比普通二叉搜索树更高效。 set set<T>…...

算法2--两数相加

题目描述 解题思路 题目说的很详细了&#xff0c;也就是把每个数倒序写成链表进行输入&#xff0c;然后让你计算两个倒序数组的和&#xff0c;要保证跟预期的结果一样。 首先应该考虑的是两个数组的长度问题&#xff0c;对于链表的每一位进行加法运算&#xff0c;如果两个列表…...

Docker搭建Testlink教程

1.拉取镜像 打开终端输入命令&#xff1a; #拉取mariadb镜像 docker pull bitnami/mariadb #拉取testlink镜像 docker pull bitnami/testlink-archived 执行结果&#xff1a; 2.运行容器 打开终端输入命令&#xff1a; #创建容器网络 docker network create testlink #查…...

安卓7.0以上App抓包

安卓7.0以上App抓包 导出BurpSuite证书 设置本机IP的8080端口监听 证书转换 将这个der证书下载到kali上&#xff0c;并使用以下命令进行证书转换 openssl x509 -inform der -in cacert.der -out burp.pem openssl x509 -inform PEM -subject_hash_old -in burp.pem转换成功…...

CCBCISCN复盘

AWDP – ccfrum 自己搭了一下环境, 复现一下这道题目, 之前比赛的时候完全没想到这个漏洞要怎么打, 修也不知道要怎么修, 就仅仅是对用户名的账号和密码进行了一下过滤, 完全没起到作用, 唉, 实在太菜 如果想要尝试复现的话可以尝试拉取这个镜像, 我打完之后就直接把这个容器给…...

【C++】八大常见的设计模式的实现与实践指南

目录 创建型模式 单例模式工厂方法模式抽象工厂模式 结构型模式 适配器模式装饰者模式代理模式 行为型模式 观察者模式策略模式命令模式 高级主题 现代C特性影响模式性能对比典型应用案例 设计模式分类 一、创建型模式 1. 单例模式&#xff08;Singleton&#xff09; 现代…...

OpenEMMA: 基于多模态大语言模型的端到端开源自动驾驶框架

OpenEMMA: 基于多模态大语言模型的端到端开源自动驾驶框架 创新点 OpenEMMA 将前置摄像头图像和车辆历史文本状态作为输入。驾驶任务被构建为视觉问答&#xff08;VQA&#xff09;问题&#xff0c;利用思维链推理来指导模型生成关键物体的详细描述、行为洞察和元驾驶决策。这…...

kali,NTFS,用户管理,文件共享,本地安全策略,计算机基础

kali更新源 vim /etc/apt/sources.list 优质源 中科大Kali镜像源​deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contribdeb-src http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib​阿里云Kali镜像源​deb http://mirrors.aliyun.com…...

零基础上手Python数据分析 (7):Python 面向对象编程初步

写在前面 回顾一下,我们已经学习了 Python 的基本语法、数据类型、常用数据结构和文件操作、异常处理等。 到目前为止,我们主要采用的是 面向过程 (Procedural Programming) 的编程方式,即按照步骤一步一步地编写代码,解决问题。 这种方式对于简单的任务已经足够,但当程序…...

基于深度学习的皮肤癌智能检测与语音提示系统【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...

脚本一键式启动Nginx、Mysql、Redis

此脚本包含拉取镜像、数据卷挂载、容器启动三大部分&#xff0c;可一键式安装三大环境 新建一个depoy.sh文件在服务器上&#xff0c;然后复制以下内容。 给脚本文件添加执行权限 chmod x depoy.sh # 文件的当前目录下 如果需要修改数据库MYSQL密码和Reids密码 MYSQL_ROO…...

蓝桥杯备赛-DFS-有奖问答

问题描述 小蓝正在参与一个现场问答的节目。活动中一共有 3030 道题目, 每题只有答对和答错两种情况, 每答对一题得 1010 分&#xff0c;答错一题分数归零。 小蓝可以在任意时刻结束答题并获得目前分数对应的奖项&#xff0c;之后不能再答任何题目。最高奖项需要 100100 分, …...

[AI速读]CHISEL vs. SystemVerilog:用RISC-V核心对比两种硬件设计语言

在硬件设计领域,选择合适的语言对开发效率、维护成本和最终性能都至关重要。最近,一项研究对比了两种硬件描述语言——CHISEL(基于Scala的嵌入式语言)和传统的SystemVerilog,它们分别实现了同一款RISC-V核心(SweRV-EL2)。以下是关键发现和结论。 为什么选择CHISEL? CHI…...

PHP PSR(PHP Standards Recommendations)介绍

PHP PSR&#xff08;PHP Standards Recommendations&#xff09;是 PHP 社区制定的一系列标准化规范&#xff0c;旨在统一 PHP 代码的编写方式、接口设计和开发实践&#xff0c;以提高代码的可读性、可维护性和互操作性。以下是核心 PSR 标准的解读和具体使用方法&#xff1a; …...

字节跳动实习生主导开发强化学习算法,助力大语言模型性能突破

目录 禹棋赢的背景与成就 主要成就 DAPO算法的技术细节 算法优势 禹棋赢的研究历程 关键时间节点 字节跳动的“Top Seed人才计划” 计划特点 小编总结 在大模型时代&#xff0c;经验不再是唯一的衡量标准&#xff0c;好奇心、执行力和对新技术的敏锐洞察力成为推动技术…...

Java并发编程面试题:锁(17题)

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…...

各类神经网络学习:(四)RNN 循环神经网络(下集),pytorch 版的 RNN 代码编写

上一篇下一篇RNN&#xff08;中集&#xff09;待编写 代码详解 pytorch 官网主要有两个可调用的模块&#xff0c;分别是 nn.RNNCell 和 nn.RNN &#xff0c;下面会进行详细讲解。 RNN 的同步多对多、多对一、一对多等等结构都是由这两个模块实现的&#xff0c;只需要将对输入…...

【python】OpenCV—Hand Landmarks Detection

文章目录 1、功能描述2、代码实现3、效果展示4、完整代码5、涉及到的库函数6、参考 更多有趣的代码示例&#xff0c;可参考【Programming】 1、功能描述 基于 opencv-python 和 mediapipe 实现手部关键点的检测&#xff08;无法检测出手&#xff0c;不过可以根据关键点的信息外…...

C++和标准库速成(十)——类型别名、类型定义、类型推断和标准库简介

目录 1. 类型别名2. 类型定义(不建议)3. 类型推断3.1 auto3.1.1 auto&3.1.2 auto*3.1.3 拷贝列表初始化和直接列表初始化 3.2 decltype 4. 标准库简介参考 1. 类型别名 类型别名为现有的类型声明提供新名称。可以将类型别名视为用于为现有类型声明引入同义词而无须创建新类…...

Java JMX 未授权访问漏洞分析与修复指南

#作者&#xff1a;张桐瑞 文章目录 一、漏洞背景二、漏洞描述三、漏洞影响四、修复方案1. 禁用远程JMX访问&#xff1a;2. 配置JMX访问权限&#xff1a; 一、漏洞背景 Java管理扩展&#xff08;Java Management Extensions&#xff0c;简称JMX&#xff09;是Java平台的管理和…...

挂谷问题与挂谷猜想:从平面转针到高维拓扑

挂谷问题与挂谷猜想&#xff1a;从平面转针到高维拓扑 目录 挂谷问题的起源数学定义与基本性质研究进展挂谷集合与挂谷猜想王虹与Joshua Zahl的突破意义与影响 挂谷问题的起源 1917年&#xff0c;日本数学家挂谷宗一(かけや そういち Soichi Kakeya&#xff0c;1886-1947)提…...

区块链 智能合约安全 | 整型溢出漏洞

目录&#xff1a; 核心概念 溢出类型 上溢 原理 案例 下溢 原理 案例 练习 漏洞修复 使用 SafeMath 库&#xff08;旧版本&#xff09; 升级 Solidity 版本&#xff08;≥0.8.0&#xff09; 地址&#xff1a;zkanzz 整型溢出漏洞&#xff08;Integer Overflow/Underflow Vulne…...

C# HTTP 文件上传、下载服务器

程序需要管理员权限&#xff0c;vs需要管理员打开 首次运行需要执行以下命令注册URL&#xff08;管理员命令行&#xff09; netsh advfirewall firewall add rule name"FileShare" dirin actionallow protocolTCP localport8000 ipconfig | findstr "IPv4&quo…...

IDEA导入jar包后提示无法解析jar包中的类,比如无法解析符号 ‘log4j‘

IDEA导入jar包后提示无法解析jar包中的类 问题描述解决方法 问题描述 IDEA导入jar包的Maven坐标后&#xff0c;使用jar中的类比如log4j&#xff0c;仍然提示比如无法解析符号 log4j。 解决方法 在添加了依赖和配置文件后&#xff0c;确保刷新你的IDE项目和任何缓存&#xff…...

C++前缀和

个人主页&#xff1a;[PingdiGuo_guo] 收录专栏&#xff1a;[C干货专栏] 大家好&#xff0c;今天我们来了解一下C的一个重要概念&#xff1a;前缀和 目录 1.什么是前缀和 2.前缀和的用法 1.前缀和的定义 2.预处理前缀和数组 3.查询区间和 4.数组中某个区间的和是否为特定…...

kafka压缩

最近有幸公司参与kafka消息压缩&#xff0c;背景是日志消息量比较大。kafka版本2.4.1 一、确认压缩算法 根据场景不同选择不同。如果是带宽敏感患者推荐高压缩比的zstd&#xff0c;如果是cpu敏感患者推荐lz4 lz4和zstd底层都使用的是lz77算法&#xff0c;具体实现逻辑不同&am…...

C 语 言 --- 扫 雷 游 戏(初 阶 版)

C 语 言 --- 扫 雷 游 戏 初 阶 版 代 码 全 貌 与 功 能 介 绍扫雷游戏的功能说明游 戏 效 果 展 示游 戏 代 码 详 解game.htest.cgame.c 总结 &#x1f4bb;作 者 简 介&#xff1a;曾 与 你 一 样 迷 茫&#xff0c;现 以 经 验 助 你 入 门 C 语 言 &#x1f4a1;个 人 主…...

黑鲨外设2025春季新品发布会:全球首款“冷暖双控”鼠标亮相!

据可靠消息称&#xff0c;电竞外设领域的创新引领者——黑鲨外设&#xff0c;正式官宣将于2025年3月28日17:00召开主题为“究极体验&#xff0c;竞在其中”春季新品发布会。据悉&#xff0c;此次新品发布会将于黑鲨游戏外设和黑鲨游戏手机官方平台同步直播&#xff0c;&#xf…...

SpringBoot-MVC配置类与 Controller 的扫描

文章目录 前言一、自动配置类位置二、自动配置类解析2.1 WebMvcAutoConfiguration2.1.1 EnableWebMvcConfiguration 2.2 DispatcherServletAutoConfiguration 三、RequestMapping 的扫描过程3.1 RequestMappingHandlerMapping#afterPropertiesSet3.2 RequestMappingHandlerMapp…...

Nexus L2 L3基本配置

接口基本配置 N7K上所有端口默认处于shutdown状态; N5K上所有端口默认处于no shutdown状态(所有端口都是switchport) 默认所有接口都是三层route模式, 只有当线卡不支持三层的时候, 接口才会处于二层switchport模式 show run all | in “system default” 创建SVI口需要提前打…...

asp.net 4.5在医院自助系统中使用DeepSeek帮助医生分析患者报告

环境&#xff1a; asp.net 4.5Visual Studio 2015本地已经部署deepseek-r1:1.5b 涉及技术 ASP.NET MVC框架用于构建Web应用程序。使用HttpWebRequest和HttpWebResponse进行HTTP请求和响应处理。JSON序列化和反序列化用于构造和解析数据。SSE&#xff08;服务器发送事件&#xf…...

LCCI ESG 中英联合认证国际分析师适合的岗位

LCCI ESG中英联合认证国际分析师领域热门岗位大揭秘&#xff01;&#x1f30d; 大家好&#xff01;今天我们来探讨LCCI ESG中英联合认证国际分析师领域的热门岗位&#xff0c;看看是否有适合你的选择。 1️⃣ LCCI ESG中英联合认证国际分析师报告专员&#xff1a;主要负责编制…...

AGI成立的条件

AGI&#xff08;通用人工智能&#xff09;的成立需满足多项核心条件&#xff0c;这些条件既涵盖技术能力层面的突破&#xff0c;也涉及伦理与认知维度的考量。 一、通用性与多任务处理能力 跨领域泛化能力 AGI需具备类似人类的通用性&#xff0c;能够灵活切换不同领域&#xf…...

论文阅读:2023 EMNLP SeqXGPT: Sentence-level AI-generated text detection

总目录 大模型安全相关研究&#xff1a;https://blog.csdn.net/WhiffeYF/article/details/142132328 SeqXGPT: Sentence-level AI-generated text detection https://aclanthology.org/2023.emnlp-main.73/ https://github.com/Jihuai-wpy/SeqXGPT https://www.doubao.com/…...

解决python配置文件类configparser.ConfigParser,插入、读取数据,自动转为小写的问题

配置类 [Section1] Key_AAA Value[Section2] AnotherKey Value默认情况下&#xff0c;ConfigParser会将ini配置文件中的KEY&#xff0c;转为小写。 重载后配置类&#xff1a; 继承类从configparser.ConfigParser改为configparser.RawConfigParser重载方法optionxform&#…...

超图神经网络的详细解析与python示例

扩展传统集合关系至超边结构&#xff0c;处理高阶交互问题。 有关人工智能的数学基础之逻辑、集合论和模糊理论&#xff1a;看我文章人工智能的数学基础之逻辑、集合论和模糊理论-CSDN博客 一、超图神经网络概述 超图神经网络&#xff08;Hypergraph Neural Network&#xff0…...

机器视觉中图像的腐蚀和膨胀是什么意思?它能用来做什么?

​腐蚀&#xff08;Erosion&#xff09;​和膨胀&#xff08;Dilation&#xff09;​是两种基本的形态学操作&#xff0c;通常用于二值图像&#xff08;黑白图像&#xff09;的处理。它们是形态学图像处理的基础&#xff0c;广泛应用于图像分割、边缘检测、噪声去除等任务。 1…...