Jetpack Compose

未来Android开发的趋势,就是Compose声明式UI。声明式UI是大势所趋,告别传统的xml方式,你会看到在Compose中有flutter的影子。

本文可以连贯去看,带你做成一个小项目

一,使用

下载安装最新版本AndroidStudio,创建项目会有Compose选项。
![在这里插入图片描述](https://img-blog.csdnimg.cn/0f42f3e4b7e3419f8f0995ee3c206e12.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5py95pyo5oiQ5omN,size_16,color_FFFFFF,t_70,g_se,x_1

二,废话不多开始撸代码

1,创建实体类TestBean

data class TestBean(val title:String,val content:String)

2,显示页面代码

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyComposeTheme {
                TestItem(bean = TestBean("Jackson", "去哪里"))
            }
        }
    }
}

@Composable
fun TestItem(bean: TestBean) {
    Row(modifier = Modifier.padding(8.dp)) {
        Image(
            painter = painterResource(id = R.drawable.ic_launcher_background),
            contentDescription = null,
            modifier = Modifier
                .size(50.dp)
                .clip(CircleShape)
        )
        Spacer(modifier = Modifier.width(10.dp))
        Column() {
            Text(
                text = bean.title,
                color = MaterialTheme.colors.secondaryVariant
            )
            Spacer(modifier = Modifier.width(10.dp))
            Text(
                text = bean.content,
                style = MaterialTheme.typography.body1,
                modifier = Modifier.padding(5.dp),
                maxLines = 1
            )
        }
    }
}

3,运行效果
在这里插入图片描述

  • setCotent:view显示入口,相当于xml布局方式setContentView()
  • MyComposeTheme :项目主题样式
  • @Composable:表示是用Compose方式写的view组件
  • Row,Column,Image,Text:这些都是view组件,没啥可说的
  • Modifier:使用view组件离不开的类,可以设置view样式等等

三,实现一个静态列表

1,创建静态数据类ListData

object ListData {
    val listData = listOf(
        TestBean("Jackson", "I love you"),
        TestBean("Jackson", "How are you How are you How are you How are you How are you"),
        TestBean("Jackson", "What are you doing"),
        TestBean("Jackson", "What's your name"),
        TestBean("Jackson", "I love you"),
        TestBean("Jackson", "I love you"),
        TestBean("Jackson", "How are you"),
        TestBean("Jackson", "What are you doing"),
        TestBean("Jackson", "What's your name"),
        TestBean("Jackson", "I love you")
    )
}

2,创建列表

@Composable
fun TestListCompose(list: List<TestBean>) {
    LazyColumn() {
        items(list) { bean ->
            TestItem(bean)
        }
    }
}

3,显示列表

 setContent {
     MyComposeTheme {
        TestListCompose(ListData.listData)
    }
 }

4,运行效果
在这里插入图片描述
可以发现很简单就实现了一个列表,只需要一行代码LazyColumn就可以实现列表加载,省去了传统的adapter方式。

四,轻松实现页面导航(Navigation)

implementation "androidx.navigation:navigation-compose:$nav_version"

1,创建NavController

//rememberNavController() 方法来创建 NavController
val navController = rememberNavController()

2,创建创建 NavHost实现跳转

每个 NavController 都必须与一个 NavHost 可组合项相关联。NavHost 将 NavController 与导航图相关联,后者用于指定您应能够在其间进行导航的可组合项目的地。

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyComposeTheme {
                Surface(color = MaterialTheme.colors.background) {
                    NavHostDemo()
                }
            }
        }
    }
}
@Composable
fun NavHostDemo() {
    val navController = rememberNavController()
    NavHost(navController = navController, startDestination = "one") {
        //"one":用于导航的路由路径
        composable("one") { PageOne(navController) }
        //two:路由路径,name:参数名称
        composable("two/{name}") { backStackEntry ->
            PageTwo(navController, backStackEntry.arguments?.getString("name"))
        }
    }
}
//页面一
@Composable
fun PageOne(navController: NavController) {
    //跳转到页面二,传递参数hello
    Button(onClick = { navController.navigate("two/hello") }) {
        Text(text = "跳转")
    }
}
//页面二 接收参数name
@Composable
fun PageTwo(navController: NavController, name: String?) {
    Button(onClick = { navController.popBackStack() }) {
        Text(text = "$name")
    }
}

五,BottomNavigation的使用

在这里插入图片描述1,用于存放底部Item数据

data class BottomItem(val label: String, val selectItemRes: Int, val unSelectItemRes: Int)
companion object {
        val mBottomTabItems =
            listOf(
                BottomItem("首页", R.drawable.ic_home_pressed, R.drawable.ic_home),
                BottomItem("发现", R.drawable.ic_find_pressed, R.drawable.ic_find),
                BottomItem("学习", R.drawable.ic_study_pressed, R.drawable.ic_study),
                BottomItem("我的", R.drawable.ic_user_pressed, R.drawable.ic_user)
            )
    }

2,简单封装BottomNavigation

@Composable
fun BottomBarWidget(
    navController: NavController,
    selectedPosition: Int,
    bottomItems: List<BottomItem>,
    onItemSelected: (position: Int) -> Unit
) {
    BottomNavigation() {
        bottomItems.forEachIndexed { index, item ->
            BottomNavigationItem(
                selected = selectedPosition == index,
                onClick = {
                    onItemSelected.invoke(index)
                    navController.navigate(item.label)
                },
                icon = {
                    Image(
                        painter = painterResource(id = if (selectedPosition == index) item.selectItemRes else item.unSelectItemRes),
                        contentDescription = item.label,
                        modifier = Modifier.size(25.dp),
                        contentScale = ContentScale.Inside
                    )
                },
                label = {
                    Text(
                        text = item.label,
                        color = if (selectedPosition == index) Color(0xFFF25822) else Color(0xFF999999)
                    )
                },
            )
        }
    }
}

3,创建NavHost

@Composable
fun NavPageDemo(navController: NavController) {
    NavHost(
        navController = navController as NavHostController,
        startDestination = "首页"
    ) {
        composable("首页") {
            //首页
            PageHome()
        }
        composable("发现") {
            //发现
            PageFind()
        }
        composable("学习") {
            //学习
            PageStudy()
        }
        composable("我的") {
            //个人中心
            PageUser()
        }
    }

4,编写页面

@Composable
fun PageHome() {
    Surface(color = Color(0xFFE04F4F)) {
        Row(
            modifier = Modifier
                .fillMaxHeight()
                .fillMaxWidth(),
            horizontalArrangement = Arrangement.Center,//设置水平居中对齐
            verticalAlignment = Alignment.CenterVertically//设置垂直居中对齐
        ) {
            Text(
                text = "首页",
                color = Color.White
            )
        }

    }
}
//其他页面相同 省略...

5,使用

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyComposeTheme {
                Surface(color = MaterialTheme.colors.background) {
                    val navController = rememberNavController()
                    var bottomSelectedState by remember { mutableStateOf(0) }
                 
                    Scaffold(
                        bottomBar = {
                            BottomBarWidget(navController, bottomSelectedState, mBottomTabItems) {
                                bottomSelectedState = it
                            }
                        }
                    ) {
                        NavPageDemo(navController)
                    }
                }
            }
        }
    }

六,Pager的使用

  implementation "com.google.accompanist:accompanist-pager:0.24.2-alpha"
  implementation "com.google.accompanist:accompanist-pager-indicators:0.24.2-alpha"
  • HorizontalPager:水平滑动
  • VerticalPager:垂直滑动

1,HorizontalPager使用

改造PageHome代码如下,编写BannerView

@ExperimentalPagerApi
@Composable
fun PageHome() {
    Surface {
        BannerView()
    }
}
@ExperimentalPagerApi
@Composable
fun BannerView() {
    val pagerState = rememberPagerState()
    Box(
    ) {
        HorizontalPager(
            count = 10,
            modifier = Modifier.height(150.dp),
            state = pagerState
        ) { page ->
            Text(
                text = "Page: $page",
                modifier = Modifier
                    .fillMaxWidth()
                    .fillMaxHeight()
                    .background(
                        if (page % 2 == 0) Color(0xFF34BFD1) else Color(0xFFF25822)
                    )
            )
        }
        // 水平指示器
        HorizontalPagerIndicator(
            pagerState = pagerState,
            modifier = Modifier
                .align(Alignment.BottomCenter)
                .padding(16.dp),
        )
    }
}

2,看效果

在这里插入图片描述

七,TabRow和Pager的结合

1,继续改造PageHome代码

@ExperimentalPagerApi
@Composable
fun PageHome() {
    Surface {
        TabRowHome()
    }
}
@ExperimentalPagerApi
@Composable
fun TabRowHome() {
    val pages = listOf(
        "首页", "新闻", "资讯", "精品"
    )
    val tabPageState = rememberPagerState(0)
    Column() {
        TabRow(
            selectedTabIndex = tabPageState.currentPage,
            indicator = { tabPositions ->
                TabRowDefaults.Indicator(
                    Modifier.pagerTabIndicatorOffset(tabPageState, tabPositions),
                    color = Color(0xFFF25822)
                )
            },
        ) {
            pages.forEachIndexed { index, title ->
                Tab(
                    text = {
                        Text(text = title)
                    },
                    selected = tabPageState.currentPage == index, //是否选中
                    onClick = { //点击事件
                        CoroutineScope(Dispatchers.Main).launch {
                            tabPageState.scrollToPage(index)
                        }
                    },
                    selectedContentColor = Color(0xFFF25822),  //选中的颜色
                    unselectedContentColor = Color(0xFF999999), //未选中的颜色
                )
            }
        }
        HorizontalPager(
            count = pages.size,
            state = tabPageState,
            reverseLayout = false,
            itemSpacing = 2.dp
        ) { page ->
            if (page == 0) {
                BannerView()
            } else {
                Column(modifier = Modifier.fillMaxSize()) {
                    Text(
                        text = "Page: $page",
                        modifier = Modifier.fillMaxWidth()
                    )
                }
            }
        }
    }
}

2,效果图

在这里插入图片描述

八,ConstraintLayout的使用

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

1,继续改造PagerHome,在BannerView下方继续添如下View

@Composable
fun IconView(){
    ConstraintLayout(modifier = Modifier.fillMaxWidth()) {
        val (box1, box2, box3,box4) = createRefs()
        createHorizontalChain(box1, box2, box3,box4)

        Box(modifier = Modifier
            .clip(CircleShape)
            .size(50.dp)
            .background(Color.Red)
            .constrainAs(box1) {})
        Box(modifier = Modifier
            .clip(CircleShape)
            .size(50.dp)
            .background(Color.Yellow)
            .constrainAs(box2) {})
        Box(modifier = Modifier
            .clip(CircleShape)
            .size(50.dp)
            .background(Color.Blue)
            .constrainAs(box3) {})
        Box(modifier = Modifier
            .clip(CircleShape)
            .size(50.dp)
            .background(Color.Green)
            .constrainAs(box4) {})
    }
}

2,效果图
在这里插入图片描述

九,网格布局

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun GridView() {

    LazyVerticalGrid(cells = GridCells.Fixed(3)) {
        items(6) {
            Card(
                backgroundColor = Color(0xFF252525),
                modifier = Modifier.size(80.dp).padding(10.dp)
            ){}
        }
    }
}

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值