Android---Jetpack Compose学习002

Compose 布局。Compose 布局的目标:1)实现高性能;2)让开发者能够轻松编写自定义布局;3)在 Compose 中,通过避免多次测量布局子级可实现高性能。如果需要进行多次测量,Compose 具有一个特殊系统,即固有特性测量。

标准布局组件

\bullet 使用 Column 可将多个像垂直地放置在屏幕上;

\bullet 使用 Row 可将多个项水平地放置在屏幕上;

\bullet 使用 Box 可将一个元素放在另一个元素上。类似于 FrameLayout 布局。

修饰符

修饰符的作用类似于xml 布局中的布局参数。借助修饰符,可以修饰或扩充可组合项。我们可以使用修饰符来执行以下操作:

\bullet 更改可组合项的大小、布局、行为和外观;

\bullet 添加信息,如无障碍标签;

\bullet 处理用户输入;

\bullet 添加高级互动,如使元素可点击、可滚动、可拖动或可缩放。

示例:通过标准布局组件修饰符实现如下布局效果

1. 新建一个 PhotoGrapherCard.kt 文件,进行布局

import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp

/**
 * @Author HL
 * @Date 2023/12/26 20:21
 * @Version 1.0
 */
@Composable
fun PhotographerCard(modifier: Modifier = Modifier){
    // TODO 水平放置,从左到右
    Row(
        modifier = Modifier
            .clip(RoundedCornerShape(4.dp)) // 设置圆角
            .background(color = MaterialTheme.colors.surface) // surface 是白色
            .clickable(onClick = {})
            .padding(all = 16.dp) // 设置点击时,水波纹效果

    ) {

        Surface (
            modifier = Modifier.size(50.dp),//设置图片大小
            shape = CircleShape, // 设置圆形形状
            // onSurface 是黑色
            color = MaterialTheme.colors.onSurface.copy(alpha = 0.2f) // 设置颜色。copy()把这个颜色复杂过来,然后设置一个透明度
        ) {
            Image(
                painter = painterResource(id = R.drawable.beauty), // 设置图片加载位置
                contentDescription = null
            )
        }

        // TODO 垂直放置,从上到下
        Column (
            modifier = Modifier
                .padding(start = 8.dp) // 左边设置填充 8dp
                .align(Alignment.CenterVertically) // 让文字垂直居中
        ) {
            Text(
                text = "Alfred Sisley",
                fontWeight = FontWeight.Bold // 设置字体,bold: 粗体
            )
            //LocalContentAlpha provides ContentAlpha.medium == LocalContentAlpha.provides(ContentAlpha.medium)
            // provides 是一个被 infix 修饰的函数。可以省略链式调用的“." 以及一对圆括号"()"
            // 隐式传参
            CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
                Text(
                    text = "3 minutes ago",
                    style = MaterialTheme.typography.body2 // 设置字体
                )
            }

        }
    }
}

2. 在 MainActivity.kt 里调用 PhotoGrapherCard

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            JetpackComposeLayoutsTheme {
                PhotographerCard()
            }
        }
    }
}

修饰符的顺序

由于每个函数都会对上一个函数返回的 Modifier 进行更改,因此顺序会影响最终结果。

Slots API

Material 组件大量使用槽位 API,这是 Compose 引入的一种模式,它在可组合项之上带来一层自定义设置。这种方法使组件变得更灵活,因为它们接受 可以自行配置的子元素,而不必公开子元素的每个配置参数。槽位会在界面中留出空白区域,让开发者按照自己的意愿来填充。

TopAppBar

scaffold

Scaffold 可以让我们实现具有基本 Material Design 布局结构的界面。Scaffold 可以为最常见的顶级 Material 组件(如 TopAppBar、BottomAppBar、FloatingActionButton 和 Drawer)提供槽位。通过使用 Scaffold,可轻松确保这些组件得到适当放置且正确地协同工作

示例:

创建 LayoutStudy.kt,完成布局

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

/**
 * @Author HL
 * @Date 2023/12/26 21:15
 * @Version 1.0
 */
@Composable
fun LayoutStudy(){
    Scaffold (
        // topBar 布局顶部
        topBar = {
            TopAppBar(
                // 设置标题
                title = {
                    Text(text = "LayoutStudy")
                },
                // 设置图标
                actions = {
                    IconButton(onClick = {}) {
                        Icon(imageVector = Icons.Filled.Favorite, contentDescription = null)
                    }
                }
            )
        }
    ) { innerPadding ->
        // 布局 body 部分
        BodyContent(Modifier.padding(innerPadding))
    }
}

@Composable
fun BodyContent(modifier : Modifier = Modifier){
    Column(modifier = Modifier.padding(8.dp)) {
        Text(text = "Hi there!")
        Text(text = "Thanks for going through the LayoutStudy")
    }
}

在 MainActivity.kt 里调用

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            JetpackComposeLayoutsTheme {
                //PhotographerCard()
                LayoutStudy()
            }
        }
    }
}

使用列表

如果我们知道用例不需要任何滚动,可以使用简单的 Column 或 Row。如果需要显示大量列表项(或长度未知的列表),可以使用 LazyColumnLazyRow

示例:设置一个可滚动的列表。可以通过 LayColumn 实现上下滚动的列表。

1. Lists.kt

@Composable
fun ScrollingList(){
    val listSize = 100
    val scrollState = rememberLazyListState()
    val coroutineScope = rememberCoroutineScope()
    // 放一个包含2个按钮的顶部布局,再放一个 List,从上到下
    Column() {
        //TODO 放两个按钮,从左到右
        Row {
            // 第一个按钮
            Button(
                modifier = Modifier.weight(1f), // 设置权重
                onClick = {
                    //Kotlin 携程
                    coroutineScope.launch {
                        // 滚到最顶部
                        scrollState.animateScrollToItem(0)
                    }

                }
            ) {
                Text(text = "Scroll to the top")
            }
            // 第二个按钮
            Button(
                modifier = Modifier.weight(1f),
                onClick = {
                    coroutineScope.launch {
                        // 滚动最底部
                        scrollState.animateScrollToItem(listSize - 1)
                    }
                }
            ) {
                Text(text = "Scroll to the end")
            }
        }

        //TODO 放列表项
        LazyColumn(state = scrollState){
           items(listSize){
               // 列表项
               ImageListItem(index = it)
           }
        }
    }
}

@Composable
fun ImageListItem(index : Int){
    Row(
        verticalAlignment = Alignment.CenterVertically
    ) {
        Image(
            painter = painterResource(id = R.drawable.beauty),
            contentDescription = null,
            modifier = Modifier.size(40.dp)
        )
        Spacer(modifier = Modifier.width(10.dp))
        Text(text = "Item $index", style = MaterialTheme.typography.subtitle1)
    }
}

2. MainActivity.kt

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            JetpackComposeLayoutsTheme {
                
                ScrollingList()
            }
        }
    }
}

自定义布局

在 Compose 中,界面元素由可组合函数表示,此类函数在被调用后会发出一部分界面,这部分界面随后会被添加到呈现在屏幕上的界面树中。每个界面元素都有一个父元素,还可能有多个子元素。此外,每个元素在其父元素中都有一个位置,指定为(x, y)位置;也都有一个尺寸,指定为 width 和 height。

使用布局修饰符

你可以使用 layout 修饰符修改元素的测量和布局方式。Layout 是一个 lambda;它的参数包括你可以测量的元素(以 measurable 的形式传递)以及该组合项的传入约束条件(以 constraints 的形式传递)。

示例:我们有如下一个需求:有一个文本 “Hi threr!”,它有一个 firstbaseline(图中红框),正常情况下,firstbaseline 是到图中 1 处的距离。现在的需求是 firstbaseline 是和父元素的距离,也就是下图中 2 处的距离。

FirstBaselineToTop.kt
// firstBaselineToTop 为 Modifier 的扩展函数
fun Modifier.firstBaselineToTop(firstBaselineToTop : Dp) = this.then(// this.then() 的 放回值就是一个 Modifier

    // TODO 用 layout 修饰符来修改元素的测量和布局位置
    // measurable 测量元素;constraints 约束条件
    layout { measurable, constraints ->
        // 测量元素
        val placeable = measurable.measure(constraints)
        // 测量之后,获取元素的基线值,即 firsrBaseline 到元素顶部的值
        val firstBaseline = placeable[FirstBaseline]
        // 元素左上角新的 Y 坐标值 = 新基线值 - 旧基线值;firstBaselineToTop 方法传进来的值
        // roundToPx() 转为像素
        val Y = firstBaselineToTop.roundToPx() - firstBaseline

        // 设置元素的宽和高。元素的高是指,元素底部到父容器顶部的位置
        val height = placeable.height + Y
        layout(placeable.width, height){
            //设置元素的新位置
            placeable.placeRelative(0, Y)
        }
    }
)
@Composable
fun TextWithPaddingToBaseline(){
    JetpackComposeLayoutsTheme {

        // 这里我们要 firstBaselineToTop 设置值为 baseline 到 父容器顶部为 24dp,
        // TODO 这个值由我们自己设定
        Text(text = "Hi There!",
            Modifier
                    // 指定 firstBaselineToTop 的值
                .firstBaselineToTop(24.dp) // 这里需要返回一个 Modifier 才能继续下面的链式调用
                .background(Color.Red))
    }
}

firstBaselineToTop

右边的布局中, firstBaselineToTop 值是到父容器顶部的距离,是我们上面代码中设定的 24dp, 然后 measure 可以帮我们测出 Text 的基线高度(firstBaseline),那么 Text 左上角黑点的位置坐标为(0, firstBaselineToTop - firstBaseline)

MyOwnColumn

完成如下布局,模仿 Column 布局,给了4个文本,一列4行的方式排列。 

示例代码:

@Composable
fun MyOwnColumn(
    modifier: Modifier = Modifier,
    content : @Composable ()-> Unit){
    // 有多个元素,所以用 Layout()
    Layout(
        modifier = modifier,
        content = content){ measurables, constraints ->
        // 测量多个元素
        val placeables = measurables.map { measurable ->
            measurable.measure(constraints)
        }
        var positionY = 0
        // 元素布局的大小,设置为父容器的最大高度和宽度
        layout(constraints.maxWidth, constraints.maxHeight){
            placeables.forEach { placeable ->
                //placeable 就是我们测量的每一个子容器
                placeable.placeRelative(x = 0, y = positionY)
                // positionY 更新高度,第一个元素的顶部到父容器顶部的距离为0;
                // 第二个元素顶部到父容器顶部的距离为 第一个元素的高度
                // 第三个元素顶部到父容器顶部的距离为 第一个元素的高度 + 第二个元的的高度
                positionY += placeable.height
            }
        }
    }
}

@Composable
fun MyOwnColumnSample(){
    JetpackComposeLayoutsTheme() {
        MyOwnColumn {
            Text(text = "MyOwnColumn")
            Text(text = "places items")
            Text(text = "vertically.")
            Text(text = "We've done it by hand!")
        }
    }
}

StaggeredGrid

通过 StaggeredGrid 自定义如下布局

StaggeredGrid.kt

// 话题列表
val topics = listOf(
    "Arts & Crafts",
    "Beauty",
    "Books",
    "Business",
    "Comics",
    "Culinary",
    "Design",
    "Fashion",
    "Film",
    "History",
    "maths"
)

@Composable
fun StaggeredGrid(
    modifier: Modifier = Modifier,
    rows : Int = 3, //指定元素最终传进来,显示多少行。默认3行
    content : @Composable () -> Unit
){

    Layout(
        modifier = modifier,
        content = content
    ){ measurables, constraints ->
        // rowWidths 用于保存每行的宽度值
        val rowWidths = IntArray(rows){ 0 }
        // rowHeights 用于保存每行的高度值
        val rowHeights = IntArray(rows){ 0 }

        // 测量元素,带索引
        val placeables = measurables.mapIndexed{index, measurable ->
            // 得到每一个元素
            val placeable = measurable.measure(constraints)
            // 计算当前元素该去到数组的那个位置,row = 0, 1, 2
            var row = index % rows
            // 每一行的宽度由每一个元素的宽度累加
            rowWidths[row] += placeable.width
            // 每一行的高度由每一行中最高的元素代表
            rowHeights[row] = max(rowHeights[row], placeable.height)
            placeable
        }
        // 计算表格的宽度,即为 rowWidth 中最宽的那一行
        // 计算表格的高度,即为 rowHeight 中元素之和。也就是rows列之和
        val gridWidth = rowWidths.maxOrNull() ?: constraints.minWidth
        val gridHeight = rowHeights.sumOf { it } // rowHeights 里所有元素相加

        // 设置每一行的 Y 坐标,每一行中的每一个元素的 Y 坐标是一样的
        val rowY = IntArray(rows){ 0 }
        // 第一列元素的 Y 坐标都0,第i行(i > 0)元素的 Y 坐标为前面 i - 1 行的高度之和
        for(i in 1 until rows){
            rowY[i] = rowY[i - 1] + rowHeights[i - 1]
        }
        // TODO 设置表格的宽高
        layout(gridWidth, gridHeight){
            //TODO 布局每一个元素,那么就要计算每一个元素的(x, y)坐标
            // 上面我们已经计算了每个元素的 Y坐标,TODO 这里还需计算每个元素的 X 坐标
            val rowX = IntArray(rows){ 0 }
            // 遍历每一个元素
            placeables.forEachIndexed{ index, placeable ->
                val row = index % rows
                // 每一列的第一个元素的 X 值都是0,所以直接先放置,然后再修改 rowX[row]
                placeable.placeRelative(
                    x = rowX[row],
                    y = rowY[row]
                )

                // 修改 rowX[row]位置的值,为同一列中下一个元素计算 X 值,即前面元素的 宽度之和
                rowX[row] += placeable.width
            }
        }
    }

}

// TODO 每一个条目
@Composable
fun Chip(
    modifier: Modifier = Modifier,
    text : String
){
    // 一个卡片,圆角。里面包含一个 Row,第一列是 Box,第二列是 Text
    Card (
        modifier = modifier,
        border = BorderStroke(color = Color.Black, width = Dp.Hairline),// 设置边框线,Hairline默认1dp
        shape = RoundedCornerShape(8.dp) // 设置4个圆角
    ) {
        Row(
            modifier = Modifier.padding(start = 8.dp, top = 4.dp, end = 8.dp, bottom = 4.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Box(
                modifier = Modifier
                    .size(16.dp, 16.dp)
                    .background(color = MaterialTheme.colors.secondary)
            )
            Spacer(modifier = Modifier.width(8.dp))
            Text(text = text)
        }
    }
}

@Composable
fun StaggeredGridBodyContent(){
    Row(
        modifier = Modifier
            .background(color = Color.LightGray)
            .padding(16.dp)
            .horizontalScroll(rememberScrollState()), // 可以水平滚动
        content = {
            StaggeredGrid(modifier = Modifier) {
                // 放元素
                for(topic in topics){
                   Chip(modifier = Modifier.padding(8.dp), text = topic)
                }
            }
        }
    )
}

Activity.kt

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            JetpackComposeLayoutsTheme {
                //PhotographerCard()
                //LayoutStudy()
                //SampleList()
                //LazyList()
                //ScrollingList()
                //TextWithPaddingToBaseline()
                //MyOwnColumnSample()
                //StaggeredGrid()
                StaggeredGridBodyContent()
            }
        }
    }
}

约束布局

在实现对齐要求比较复杂的较大布局时,ConstraintLayout 很有用。 

引用

引用是使用 createRefs() 或 createRefFor() 创建的,ConstraintLayout 中的每个可组合项都需要有与之关联的引用。

约束条件

 约束条件是使用 constrainAs() 修饰符提供的,该修饰符将引用作为参数,可让你在主体 lambda 中指定其约束条件。

约束条件是使用 linkTo() 或其它有用的方法指定的。parent 是一个现有的引用,可用于指定对 ConstraintLayout 可组合项本身的约束条件。

案例1:用 ConstraintLayout 布局出如下效果。

1. 导入 ConstraintLayout 的依赖

implementation 'androidx.constraintlayout:constraintlayout-compose:1.0.0-alpha08'

2. ConstraintLayout.kt

@Composable
fun ConstraintLayoutContent(){
    // TODO 需要在 build.gradle 中引入依赖
    ConstraintLayout {
        //TODO 1. 通过 createRefs 创建引用,ConstraintLayout 中的每个元素都需要关联一个引用
        val (button, text) = createRefs()

        Button(
            onClick = { /*TODO*/ },
            //TODO 2.使用 Modifier.constrainAs 来提供约束,引用作为它的第一个参数
            // 在 lambda 表达式中指定约束规则
            modifier = Modifier.constrainAs(button){
                // TODO 3.约束条件是使用 linkTo(), parent.top表示在父容器顶部,有一个外边距 margin
                top.linkTo(parent.top, margin = 16.dp)
            }
        ) {
            Text(text = "Button")
        }
        
        Text(text = "Text", modifier = Modifier.constrainAs(text) {
            // 约束条件是使用 linkTo(), button.bottom表示位于button 的底部,有一个外边距 margin
            top.linkTo(button.bottom, margin = 16.dp)
            // 在 ConstraintLayout 中水平居中
            centerHorizontallyTo(parent)
        })
    }
}

 案例2:

@Composable
fun ConstraintLayoutContent2(){
    ConstraintLayout {
        val (button1, button2, text) = createRefs()

        Button(
            onClick = {},
            modifier = Modifier.constrainAs(button1){
                top.linkTo(parent.top, margin = 16.dp)
            }
        ) {
            Text(text = "Button1")
        }
        Text(text = "Text", modifier = Modifier.constrainAs(text) {
            // 约束条件是使用 linkTo(), button.bottom表示位于button 的底部,有一个外边距 margin
            top.linkTo(button1.bottom, margin = 16.dp)
            //TODO 在 text 的中间位置位于 boton1 的 end 位置
            centerAround(button1.end)
        })

        // 将 button1 和 text 组合起来,建立一个屏障
        val barrier = createEndBarrier(button1, text)
        Button(
            onClick = {  },
            modifier = Modifier.constrainAs(button2){
                //TODO top: 给顶部设置约束,start: 给左边设置约束
                top.linkTo(parent.top, margin = 16.dp)
                start.linkTo(barrier)
            }
        ) {
            Text(text = "Button1")
        }
    }
}

解耦 API

在某些情况下,最好将约束条件与应用它们的布局分离开来。例如,我们可能会希望根据屏幕配置来更改约束条件,或在两个约束条件集之间添加动画效果。

\bullet 将 ConstraintSet 作为参数传递给 ConstraintLayout。

\bullet 使用 layoutId 修饰符将在 ConstraintSet 中创建的引用分配给可组合项。

如下代码所示:我们系统代码中 margin 是根据屏幕旋转时,动态设置的值,这种就不好弄了。

我们可以通过解耦的方式,将 Button 和 Text 组件之间的约束关系在外部定义,然后传入到 ConstraintLayout 中。而 margin 作为一个其它约束,就作为参数传递。如下代码所示

@Composable
fun DecoupledConstraintLayout2(){
    // 打包
    BoxWithConstraints {
        // maxWidth 和 maxHeight 是 BoxWithConstraints 中的属性
        val constrains = if(maxWidth < maxHeight){
            //TODO 返回的是一个 ConstraintSet
            DecoupledConstraints(16.dp) // 竖屏情况下
        }else{
            DecoupledConstraints(64.dp)// 横屏情况下
        }
        ConstraintLayout (constrains) {
            Button(
                onClick = { },
                modifier = Modifier.layoutId("button")
            ) {
                Text(text = "Button")
            }

            Text(text = "Text", modifier = Modifier.layoutId("text"))
        }
    }
}

// TODO 将Button 和 Text 的约束抽离到外部,
private fun DecoupledConstraints(margin : Dp) : ConstraintSet{
    return ConstraintSet{
        val button = createRefFor("button")
        val text = createRefFor("text")

        constrain(button){
            top.linkTo(parent.top, margin)
        }
        constrain(text){
            top.linkTo(button.bottom, margin)
        }
    }
}

Intrinsics

\bullet Compose 只测量子元素一次,测量两次会引发运行时异常。但是,有时在测量子元素之前,我们需要一些有关子元素的信息。

\bullet Intrinsics 允许你在实际测量之前查询子项。1)(min|max)intrinsicWidth:鉴于此高度,你可以正确绘制内容的最小/最大宽度是多少。2)(min|max)intrinsicHeight:鉴于此宽度,你可以正确绘制内容的最小/最大高度是多少。

示例:如下布局。要在中间做一个分割线,它的高度与左右文本的高度一致

@Composable
fun TwoTexts(modifier: Modifier = Modifier){
    // 将 Row 的高度限制为文本的高度,通过 Intrinsic 在测量之前来获取文本的高度信息
    Row (modifier = Modifier.height(IntrinsicSize.Min)) {
        Text(
            text = "Hi",
            modifier = Modifier
                .padding(start = 4.dp)
                .weight(1f)
                .wrapContentWidth(Alignment.Start)
        )

        // 两个文本中间的线
        Divider(
            color = Color.Black,
            modifier = Modifier
                .fillMaxHeight() //fillMaxHeight()获取父容器最大高度
                .width(1.dp))

        Text(
            text = "There",
            modifier = Modifier
                .padding(start = 4.dp)
                .weight(1f)
                .wrapContentWidth(Alignment.End)
        )
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数字孪生:构建未来智慧社区的关键技术

随着科技的快速发展&#xff0c;数字孪生技术作为构建未来智慧社区的关键技术&#xff0c;正逐渐受到广泛关注。数字孪生技术能够实现物理世界与数字世界的交互映射&#xff0c;为智慧社区的建设提供强有力的支持。本文将探讨数字孪生技术在构建未来智慧社区中的作用和意义&…

JavaIO读取C101.txt文件

一、split分割带空格的字符串&#xff08;四种方法及其区别&#xff09; 参考&#xff1a;https://blog.csdn.net/yezonghui/article/details/106455940 String str "a b c d";String[] arr1 str.split(" "); //仅分割一个空格 String[] arr2 str…

yo!这里是Linux线程保姆级入门介绍

目录 前言 Linux线程基础 线程概念 底层示意图 线程vs进程 Linux线程控制 创建线程 线程ID 线程终止 线程等待 线程分离 Linux线程互斥 背景概念 互斥量mutex 1.相关接口 2.实现原理 可重入vs线程安全 死锁 Linux线程同步 条件变量 生产者消费者模型 基于…

MySQL-索引(INDEX)

文章目录 1. 索引概述及优劣势2. 索引结构和不同引擎对索引的支持情况2.1 Btree2.2 Hash索引 3. 索引分类4. 索引语法5. 索引在什么情况下会失效&#xff1f;5.1 最左前缀法则5.2 范围查询5.3 索引列运算5.4 头部模糊查询5.5 OR连接条件5.6 字符串不加引号5.7 数据分布影响 6. …

【开源】SpringBoot框架开发考研专业课程管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 考研高校模块2.3 高校教师管理模块2.4 考研专业模块2.5 考研政策模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 考研高校表3.2.2 高校教师表3.2.3 考研专业表3.2.4 考研政策表 四、系统展示五、核…

跳表详解和实现|深挖Redis底层数据结构

文章目录 跳表前言项目代码仓库认识跳表跳表的实现思路跳表性能分析对比平衡树&#xff08;avl和红黑树&#xff09;和哈希表使用手册成员变量成员函数构造析构迭代器sizeclearemptyoperatorfindinserterase 跳表细节实现节点定义跳表结构定义构造、析构、拷贝构造和赋值重载si…

hummingbird,一个便于将模型部署到边缘设备的Python库!

前言 随着人工智能和机器学习的快速发展&#xff0c;将训练好的模型部署到生产环境中成为了一个重要的任务。而边缘计算设备&#xff0c;如智能手机、嵌入式系统和物联网设备&#xff0c;也需要能够运行机器学习模型以进行实时推理。Python Hummingbird 是一个强大的工具&…

Linux Terminator工具: 保存窗口布局 执行默认启动指令

How do I get Terminator to start up with my custom layout? - Ask Ubuntu

新春快乐(烟花、春联)【附源码】

新春快乐 一&#xff1a; C语言 -- 烟花二&#xff1a;Python -- 春联三&#xff1a;Python -- 烟花四&#xff1a;HTML -- 烟花 一&#xff1a; C语言 – 烟花 运行效果&#xff1a; #include <graphics.h> #include <math.h> #include <time.h> #include…

JSP原理简述

JSP动态网页技术&#xff0c;可以定义html&#xff0c;css&#xff0c;js等静态内容&#xff0c;还可以定义java代码等动态内容。 注意导入坐标时&#xff0c;JSP的scope标签是provided&#xff0c;和servlet一样&#xff0c;否则会报错。 JSP本质上就是一个Servlet&#xff0c…

C++11:移动构造函数【写法+调用时机】【C++返回vector为什么不报错】

文章目录 what is 移动构造函数&#xff1f;移动构造函数的实现的例子when 移动构造函数&#xff1f;在C98之前&#xff0c;没有移动构造函数&#xff0c;是怎么做的呢&#xff1f;后记 what is 移动构造函数&#xff1f; 构造函数string(string&& str)类似于复制构造…

单片机项目调试中的技巧和常见问题解决

单片机是嵌入式系统中的重要组成部分&#xff0c;在各种电子设备中发挥着重要的作用。在单片机项目开发过程中&#xff0c;调试是至关重要的一环&#xff0c;同时也会遇到一些常见问题。本文将介绍一些单片机项目调试的技巧以及常见问题的解决方法&#xff0c;希望能够对单片机…

leetcode——滑动窗口题目汇总

本章总结一下滑动窗口的解题思路&#xff1a; 在字符串中使用双指针 left 和 right 围成的一个左闭右开的区域作为一个窗口。不断将 right 向右滑动&#xff0c;直到窗口中的字符串符合条件。此时将 left 向右滑动&#xff0c;直到窗口中的字符串不符合条件&#xff0c;期间需…

H12-821_73

73.某台路由器Router LSA如图所示&#xff0c;下列说法中错误的是&#xff1f; A.本路由器的Router ID为10.0.12.1 B.本路由器为DR C.本路由器已建立邻接关系 D.本路由器支持外部路由引入 答案&#xff1a;B 注释&#xff1a; LSA中的链路信息Link ID&#xff0c;Data&#xf…

MFC实现遍历系统进程

今天我们来枚举系统中的进程和结束系统中进程。 认识几个API 1&#xff09;CreateToolhelp32Snapshot 用于创建系统快照 HANDLE WINAPI CreateToolhelp32Snapshot( __in DWORD dwFlags, //指定快照中包含的系统内容__in DWORD th32P…

C++初阶:适合新手的手撕vector(模拟实现vector)

上次讲了常用的接口&#xff1a;C初阶&#xff1a;容器&#xff08;Containers&#xff09;vector常用接口详解 今天就来进行模拟实现啦 文章目录 1.基本结构与文件规划2.空参构造函数&#xff08;constructor)4.基本函数&#xff08;size(),capacity(),resize(),reserve())4.增…

基于JavaWeb的网上订餐项目

点击以下链接获取源码&#xff1a; https://download.csdn.net/download/qq_64505944/88825723?spm1001.2014.3001.5503 Java项目-16 浏览商品&#xff0c;会员登录&#xff0c;添加购物车&#xff0c;进行配送等功能 文件代码功能介绍 1.Src下的java文件存放的我们后端的…

Python算法题集_两两交换链表中的节点

Python算法题集_两两交换链表中的节点 题24&#xff1a;两两交换链表中的节点1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【四节点法】2) 改进版一【列表操作】3) 改进版二【三指针法】4) 改进版三【递归大法】 4. 最优算法 本文为Python算法…

Python 小白的 Leetcode Daily Challenge 刷题计划 - 20240209(除夕)

368. Largest Divisible Subset 难度&#xff1a;Medium 动态规划 方案还原 Yesterdays Daily Challenge can be reduced to the problem of shortest path in an unweighted graph while todays daily challenge can be reduced to the problem of longest path in an unwe…

ubuntu20.04 安装mysql(8.x)

安装mysql命令 sudo apt-get install mysql-server安装完毕后&#xff0c;立即初始化密码 sudo mysql -u root # 初次进入终端无需密码ALTER USER rootlocalhost IDENTIFIED WITH caching_sha2_password BY yourpasswd; # 设置本地root密码设置mysql远程登录 设置远程登录账…