
0 为什么要有布局和传统XML一样若不使用具体的布局所有控件将堆叠在一起无法呈现所想的视图效果。例如下面在界面中声明了两个文本控件但却未用布局包裹就会导致两个控件重叠。Preview Composable fun ArtistCard() { Text(Alfred Sisley) Text(3 minutes ago) }一 垂直布局 Column被Column布局包裹的控件将会垂直排列就像传统XML中的LinearLayout将orientation设置为了vertical。如下用Column对控件进行包裹便实现了垂直布局。Preview Composable fun ArtistCardColumn() { Column { Text(Alfred Sisley) Text(3 minutes ago) } }二 水平布局 Row被Row布局包裹的控件将会水平排列就像传统XML中的LinearLayout将orientation设置为了horizontal。Preview Composable fun ArtistCardColumn() { Row { Text(Alfred Sisley) Text(3 minutes ago) } }三 堆叠排列布局Box从Box这个单词来理解这个布局的特性Box即“箱子”箱子中存放的物品都是堆叠或排列起来的所以我将其称为堆叠排列布局。Box布局的使用比较复杂需要通过属性参数才能 实现对子控件的布局排列。下面简单介绍下Box的两个常用属性。contentAlignment这个属性主要用于设置Box中子控件的位置如上下左右中。ModifierModifier是Compose中各个控件最常用到的修饰属性几乎可以为每个控件设置Modifier属性。它可以设置如同传统xml中的matchParent、padding、width、height、background等一样的效果且可以链式调用简化了传统xml的很多代码。Preview Composable fun BoxTest() { Box( modifier Modifier .size(300.dp) .background(Color.Cyan), contentAlignment Alignment.BottomStart ) { Image(painter painterResource(R.drawable.ic_launcher_background), ) Icon(painter painterResource(R.drawable.ic_launcher_foreground), ) } }实际应用我们可以利用Box布局来实现一个类似于网易云黑胶唱片的效果效果展示黑胶唱片旋转效果演示代码class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { HelloWorldComposeTheme { Surface { VinylRecordView() } } } } } // 歌曲数据类 data class Song( val name: String, val artist: String, val coverRes: Int, RawRes val rawRes: Int ) //当前播放歌曲 val curSong Song(我害怕, 薛之谦, R.drawable.demo_music1, R.raw.demo_music1) //黑胶唱片效果实现 Preview Composable fun VinylRecordView() { var diskRotation by remember { mutableFloatStateOf(0f) } val rotationSpeed 0.042f // 每帧递增度数可调速度 val isPlaying remember { mutableStateOf(true) } // 动画黑胶旋转 LaunchedEffect(isPlaying.value) { while (isPlaying.value) { diskRotation rotationSpeed * 16 // 16是大致每帧毫秒 if (diskRotation 360f) diskRotation - 360f delay(16) } // 这里不处理归零保持在当前角度暂停状态 } Box( modifier Modifier .fillMaxWidth() .fillMaxHeight() .aspectRatio(1f)//裁切为正方形 .graphicsLayer(rotationZ diskRotation),//设置旋转动画 contentAlignment Alignment.Center ) { //黑胶 Box( modifier Modifier .clip(CircleShape) .background(Color.Black, CircleShape) .fillMaxSize(0.7f) .align(Alignment.Center) ) { Image( painter painterResource(id R.drawable.ic_disc), contentDescription null, modifier Modifier .fillMaxSize() .clip(CircleShape) ) } // 封面 Box( modifier Modifier .clip(CircleShape) .background(Color.White, CircleShape) .fillMaxSize(0.5f) .align(Alignment.Center) ) { Image( painter painterResource(id curSong.coverRes), contentDescription null, modifier Modifier .fillMaxSize() .clip(CircleShape) ) } } }四 其余布局除了上述所提及的基础布局外Compose还提供了很多其他的布局。如BoxWithConstraints对应xml中的ConstraintLayoutLazyVerticalGrid对应xml中的GridLayout布局等等。还有Compose提供了许多开箱即用的布局例如ModalNavigationDrawer、TopAppBar等只需要再进行具体的元素填充即可完成所需要的界面。