如何是Jetpack Compose构建漂亮的应用程序

这篇具有很好参考价值的文章主要介绍了如何是Jetpack Compose构建漂亮的应用程序。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

如何是Jetpack Compose构建漂亮的应用程序

如何是Jetpack Compose构建漂亮的应用程序

Jetpack compose 是在 Android 上构建 UI 的未来。

如果您完全不熟悉 android 并且不知道 Jetpack Compose 是什么——它基本上是一种构建本机用户界面的新方法。
Jetpack compose官方站点

https://developer.android.com/jetpack/compose

在本文中,您将了解如何使用 Jetpack Compose 遵循最佳实践进行 UI 开发。

我们正在建设什么
我们将构建一个显示 Apple Music 专辑列表的应用程序。让我们调用应用程序MyMusic。

从我的github 存储库中,您将学习如何:

https://github.com/ibrajix/MyMusic

  1. 使用推荐的方法(启动 API)构建启动画面

https://developer.android.com/guide/topics/ui/splash-screen

  1. 使用各种 UI 可组合项,例如行、列、惰性列、动画 API
  2. 将 MVVM 模式与 Jetpack Compose 结合使用(使用可观察对象和状态持有者,如 StateFlow)
  3. 使用Room 数据库从 JSON 文件保存本地数据
  4. 在应用程序上实现搜索功能
  5. 使用这个很棒的库实现带有过渡动画的简单导航

https://github.com/raamcosta/compose-destinations

  1. 如何使用这个很棒的库有效地显示 gif 等图像

https://github.com/skydoves/Landscapist

为了降低复杂性,本文重点介绍 UI。

SpashScreen

启动画面是在您的应用程序内容加载之前显示的内容。这是向用户展示您的品牌形象或徽标的一种方式。

如何是Jetpack Compose构建漂亮的应用程序

可悲的是,没有办法专门用 compose 来实现当前的 splash API。我们仍然需要一些 xml 代码

  • values/themes.xml下。添加启动画面主题
    代码中注释了每个属性的作用
<!--Parent Theme-->
<style name="Theme.MyMusic" parent="android:Theme.Material.Light.NoActionBar">
   ......
</style>

<!--Splash Screen Theme-->
<style name="Theme.MyMusic.SplashScreen" parent="Theme.SplashScreen">
   <!--splash screen background-->
   <item name="windowSplashScreenBackground">@color/splash_screen_background_color</item>

   <!--splash screen drawable-->
   <item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>

   <!--post splash screen - displayed after splash screen-->
   <item name="postSplashScreenTheme">@style/Theme.MyMusic</item>
</style>
  • 确保将主题包含在AndroidManifest.xml root 标记中
android:theme="@style/Theme.MyMusic.SplashScreen"

在您的 Launcher Activity 中安装主题,它应该是您的MainActivity.kt

class MainActivity : ComponentActivity()
  .........
super.onCreate(savedInstanceState)
  ......
installSplashScreen()
  • 运行该应用程序,您的初始屏幕应该可以正常工作。

StartSceen

如何是Jetpack Compose构建漂亮的应用程序

创建一个新的composable,命名为StartScreen(代码路径 ui/screens/start/StartScreen.kt

@RootNavGraph(start = true)
@Destination(style = StartScreenTransitionAnimation::class)
@Composable
fun StartScreen(
    modifier: Modifier = Modifier,
    navigator: DestinationsNavigator
) {

   ..//we'll build the layout above here

}

@RootNavGraph - 这是我们导航库中的一个注释,表示这是我们导航图的起始屏幕。

@Destination - 也是来自我们导航库的注释,表示这个组合式是一个可以让用户往返导航的目的地。我们还包括了一个过渡动画的样式属性(请查看animations/StartScreenTransition.kt)。

@Modifier - 是传递给组合式的参数,用于装饰组合式(例如,大小、背景等)。

@Navigator - 帮助我们从一个目的地或屏幕导航到另一个。

  • 正如您从上面的图2中可以看到的那样,卡片被放置在肯伊·威斯特(Kanye West)的图像上方。
  • 因此,我们将使用一个Box。
  • Box是一个UI可组合,可以让您将项目放置在其他项目之上。

请在上面的{…}之间放置以下可组合:

Box(
    modifier = modifier
        .fillMaxSize()
){
.......
}
  • modifier 说明该 Box 应填充整个屏幕的大小。
  • 现在,在 Box 内部,我们放置我们的卡尼·韦斯特图片,这是一个 GIF(使用我们的图像加载库)。
Box(
    modifier = modifier
        .fillMaxSize()
){

    GlideImage(
        imageModel = R.drawable.kanye
    ) 
    ........
}
  • 接下来,我们需要创建一个放置在 Kanye 图片上方的卡片。我们可以使用 Card 组合来实现。
Box(
        modifier = modifier
            .fillMaxSize()
    ){

        GlideImage(
            imageModel = R.drawable.kanye
        )

        Card(modifier = modifier
            .fillMaxWidth(0.8F)
            .align(Alignment.BottomCenter)
            .padding(bottom = 50.dp),
            shape = RoundedCornerShape(50.dp),
            backgroundColor = MaterialTheme.colors.secondary
        ) {

          ...........

        }

}
  • 我们指定卡片应该在屏幕底部居中,宽度恰好占据屏幕的 80%,并有 50dp 的 padding。
  • 我们还指定了卡片应该有圆角,半径为 50dp,并具有辅助背景色。
  • 从上图2中可以看出,红色箭头表示物品是从上到下(纵向)排列的。

如何是Jetpack Compose构建漂亮的应用程序

  • Column是一个UI组件,可将其子项垂直排列在一起。
Box(
        modifier = modifier
            .fillMaxSize()
    ){

        GlideImage(
            imageModel = R.drawable.kanye
        )

        Card(modifier = modifier
            .fillMaxWidth(0.8F)
            .align(Alignment.BottomCenter)
            .padding(bottom = 50.dp),
            shape = RoundedCornerShape(50.dp),
            backgroundColor = MaterialTheme.colors.secondary
        ) {

            Column(
                modifier = modifier
                    .padding(bottom = 20.dp),
                verticalArrangement = Arrangement.SpaceEvenly,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                ...........
            }
            
       }
}
  • 这些修饰符和属性都是很容易理解的。
  • 我们确保在此列中放置的所有项目从上到下(垂直)均匀分布。
  • 同时,确保项目从左到右(水平)居中。
  • 现在,我们将在列中添加其他 UI 组合件——文本和按钮。
    开始界面的完整代码如下:
//StartScreen.kt
@RootNavGraph(start = true)
@Destination(style = StartScreenTransitionAnimation::class)
@Composable
fun StartScreen(
    modifier: Modifier = Modifier,
    navigator: DestinationsNavigator
) {

    Box(
        modifier = modifier
            .fillMaxSize()
    ){

        GlideImage(
            imageModel = R.drawable.kanye
        )

        Card(modifier = modifier
            .fillMaxWidth(0.8F)
            .align(Alignment.BottomCenter)
            .padding(bottom = 50.dp),
            shape = RoundedCornerShape(50.dp),
            backgroundColor = MaterialTheme.colors.secondary
        ) {

            Column(
                modifier = modifier
                    .padding(bottom = 20.dp),
                verticalArrangement = Arrangement.SpaceEvenly,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {

                Text(
                    modifier = modifier
                        .padding(30.dp),
                    text = stringResource(id = R.string.explore_your_world_of_music),
                    style = MaterialTheme.typography.h1,
                    textAlign = TextAlign.Center,
                    color = MaterialTheme.colors.onSecondary
                )

                Text(
                    modifier = modifier
                        .padding(horizontal = 30.dp),
                    text = stringResource(id = R.string.see_trending_songs_from_favs),
                    style = MaterialTheme.typography.caption,
                    textAlign = TextAlign.Center,
                    fontSize = 14.sp,
                    color = MaterialTheme.colors.onSecondary
                )

                Button(
                    modifier = modifier
                        .fillMaxWidth(0.6f)
                        .height(80.dp)
                        .padding(top = 8.dp)
                        .align(Alignment.CenterHorizontally)
                        .padding(8.dp),
                    shape = RoundedCornerShape(50.dp),
                    onClick = {
                        navigator.popBackStack()
                        navigator.navigate(HomeScreenDestination)
                    }
                ) {

                    Text(
                        text = stringResource(id =R.string.get_started),
                        style = MaterialTheme.typography.h3
                    )
                    
                }
            }
        }
    }
}
  • 请注意,我们在按钮点击时使用 onClick lambda 参数导航到 HomeScreenDestination
  • 请确保您已经创建了 HomeScreen composable,请检查 ui/screens/home/HomeScreen
    它应该带有 @Destination 注解。在成功构建后,这将自动为您创建 HomeScreenDestination 文件。

Home Screen

如何是Jetpack Compose构建漂亮的应用程序

  • 您必须已经创建了HomeScreen可组合项(检查ui/screens/home/HomeScreen.kt
  • 主屏幕基本上由从上到下排列的项目组成——垂直(如上面的黑色箭头所示)
@Destination(style = StartScreenTransitionAnimation::class)
@Composable
fun HomeScreen(
    navigator: DestinationsNavigator,
    albumDatabaseViewModel: AlbumDatabaseViewModel = hiltViewModel()
){
//--> Home screen layout here
}

个人而言,我喜欢干净、可重复使用的代码。所以,我不会将整个主屏幕项目放在此组合中。我们将创建另一个名为 HomeScreenItems.kt 的组合,并将其放在我们的 HomeScreen 中。

//HomeScreen.kt
@Destination(style = StartScreenTransitionAnimation::class)
@Composable
fun HomeScreen(
    navigator: DestinationsNavigator,
    albumDatabaseViewModel: AlbumDatabaseViewModel = hiltViewModel()
){

.............// Check full code for other variables

    HomeScreenItems(navigator = navigator, albums = albums.value,
        onCardClicked = {
        shouldOpenAlbumDetails = true
        albumUrl = it
    },
        onPopularAlbumClicked = {
           shouldOpenTrendingAlbums = true
        }
    )

}

这是我们的HomeScreenItems.kt文件

//HomeScreenItems.kt
@Composable
fun HomeScreenItems(
    modifier: Modifier = Modifier,
    navigator: DestinationsNavigator,
    albums: List<Album>,
    albumDatabaseViewModel: AlbumDatabaseViewModel = hiltViewModel(),
    onCardClicked: (String) -> Unit,
    onPopularAlbumClicked: () -> Unit
) {

    ........

}
  • 该可组合接受许多参数。
    我将强调一下之前没有解释过的参数:

  • albums - 来自Room数据库实体/表的专辑列表

  • albumDatabaseViewModel - 数据源的viewModel

  • onCardClicked - 当卡片被点击时调用的Lambda函数

  • onPopularAlbumClicked - 当点击热门专辑时调用的Lambda函数

  • 由于我们希望我们的主屏幕可以滚动,并且随着我们滚动逐渐加载项目,因此我们将使用LazyColumn作为根布局。

  • LazyColumn是一个垂直滚动的可组合列表,仅组合和布局当前可见的项目。

//HomeScreenItems.kt
@Composable
fun HomeScreenItems(
    modifier: Modifier = Modifier,
    navigator: DestinationsNavigator,
    albums: List<Album>,
    albumDatabaseViewModel: AlbumDatabaseViewModel = hiltViewModel(),
    onCardClicked: (String) -> Unit,
    onPopularAlbumClicked: () -> Unit
) {

    LazyColumn(
        modifier = modifier
            .fillMaxSize()
            .background(MaterialTheme.colors.bgHome)
            .padding(20.dp)
    ){
    
       .........
     
    }

}
  • 因此,我们想在 LazyColumn 中放置什么?非动态内容(单个静态项)和动态内容(变化的项)。
  • 从图3中,您会发现蓝色框和绿色框中的项目是非动态内容。它们不会改变。
  • 因此,我们将使用单个项目 lambda 函数来显示这些项。
  • 每个部分都有一个用于显示 UserHomeSection()SearchSection()PopularAlbumSection() 的组合体。
//HomeScreenItems.kt 
LazyColumn(
        modifier = modifier
            .fillMaxSize()
            .background(MaterialTheme.colors.bgHome)
            .padding(20.dp)
    ){

        /**
         * Non-Dynamic Items
         */

        item {

            //first section
            UserHomeSection()

            //search home screen
            SearchSection(
                searchTextFieldValue = "",
                onSearchTextFieldValueChange = {  },
                onSearchTextFieldClicked = { navigator.navigate(SearchScreenDestination) },
                searchFieldPlaceHolder = R.string.search_albums,
                searchEnabled = false,
                showKeyboardOnStart = false
            )

            //popular item section
            PopularAlbumSection(
                cardTextTitle = R.string.popular,
                cardTextItem = R.string.top_trending_albums,
                cardImage = R.drawable.ic_character,
                onPopularAlbumCardClicked = {
                    //popular album clicked, go to apple music
                    onPopularAlbumClicked()
                }
            )

        }

      item{

          Text(
              modifier = modifier
                  .fillMaxWidth()
                  .padding(top = 12.dp),
                style = MaterialTheme.typography.h2,
                fontSize = 18.sp,
                color = MaterialTheme.colors.onSecondary,
                text = stringResource(id = R.string.all_albums)
            )

        }

       .................


     }

}
  • 这样做是为了分离关注点,并且主要是为了可重用性(例如,我可以在应用程序的其他位置使用SearchSection可组合部件,而无需复制SearchSection可组合部件中的整个代码)
  • 实际上,我在SearchScreen中使用了相同的可组合部件。
  • 请注意,在图3中,第一个框标记为蓝色。这只是表示项目从左到右(水平)放置。因此,我们需要使用名为Row的可组合部件。
  • Row用于在屏幕上水平放置项目。
  • 现在,对于我们从Room数据库获取的动态项目,我们将使用称为items的lambda函数来显示它们。
    我们完整的HomeScreenItems.kt如下:
//HomeScreenItems.kt
@Composable
fun HomeScreenItems(
    modifier: Modifier = Modifier,
    navigator: DestinationsNavigator,
    albums: List<Album>,
    albumDatabaseViewModel: AlbumDatabaseViewModel = hiltViewModel(),
    onCardClicked: (String) -> Unit,
    onPopularAlbumClicked: () -> Unit
) {

    LazyColumn(
        modifier = modifier
            .fillMaxSize()
            .background(MaterialTheme.colors.bgHome)
            .padding(20.dp)
    ){

        /**
         * Non-Dynamic Items
         */

        item {

            //first section
            UserHomeSection()

            //search home screen
            SearchSection(
                searchTextFieldValue = "",
                onSearchTextFieldValueChange = {  },
                onSearchTextFieldClicked = { navigator.navigate(SearchScreenDestination) },
                searchFieldPlaceHolder = R.string.search_albums,
                searchEnabled = false,
                showKeyboardOnStart = false
            )

            //popular item section
            PopularAlbumSection(
                cardTextTitle = R.string.popular,
                cardTextItem = R.string.top_trending_albums,
                cardImage = R.drawable.ic_character,
                onPopularAlbumCardClicked = {
                    //popular album clicked, go to apple music
                    onPopularAlbumClicked()
                }
            )

        }

        /**
         * Dynamic Items
         */

        item{

            Text(
                modifier = modifier
                    .fillMaxWidth()
                    .padding(top = 12.dp),
                style = MaterialTheme.typography.h2,
                fontSize = 18.sp,
                color = MaterialTheme.colors.onSecondary,
                text = stringResource(id = R.string.all_albums)
            )

        }


        items(items = albums){ album->

            AlbumCard(
                album = album,
                onClickCard = { albumUrl->
                  //card clicked, go to details screen
                    onCardClicked(albumUrl)
                },
                onClickLike = { isLiked, albumId->
                    albumDatabaseViewModel.doUpdateAlbumLikedStatus(!isLiked, albumId)
                }
            )

        }

    }

}

我创建了一个名为AlbumCard的可重复使用的可组合项,我们可以将其用作显示所有动态项目的模型。
确保检查完整代码以正确理解其工作原理。

我希望我已经能够解释基本 UI 如何与 Jetpack Compose 一起工作。有关 UI 的更多信息,请查看官方文档

github代码网址

https://github.com/ibrajix/MyMusic

参考

https://ibrajix.medium.com/how-i-built-this-nice-looking-app-using-jetpack-compose-3974db7eb9e文章来源地址https://www.toymoban.com/news/detail-436638.html

到了这里,关于如何是Jetpack Compose构建漂亮的应用程序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 解释 RESTful API,以及如何使用它构建 web 应用程序

             RESTful API stands for Representational State Transfer Application Programming Interface. It is a set of principles and guidelines for building web services that provide data in a standard format, typically JSON or XML. RESTful API emphasizes on uniformity, scalability, reliability, performance, and flexibility. It operates on HTTP and follo

    2024年02月14日
    浏览(66)
  • 解释 RESTful API,以及如何使用它构建 web 应用程序。

    RESTful API是一种利用HTTP协议进行通信的Web API设计风格,它采用了一组统一且可缓存的操作,包括GET、POST、PUT、DELETE等,通过URL来定位资源,以及使用JSON、XML等格式来传输数据,以实现系统之间的数据交互和资源共享。 使用RESTful API构建Web应用程序,首先需要设计API的URL、

    2024年02月11日
    浏览(66)
  • 什么是RESTful API,以及如何它使用构建 web 应用程序(InsCode AI 创作助手)

    RESTful API 是一种基于 REST(Representational State Transfer,表征状态转移) 架构风格的 API,它使用 HTTP 协议的方法(GET,POST,PUT,DELETE)来实现资源的创建、读取、更新和删除。通过这种方式,API 可以更加简单和灵活,使得不同编程语言之间的交互更加容易。 使用 RESTful API 构建

    2024年02月09日
    浏览(64)
  • Nest的基本概念,以及如何使用Nest CLI来构建一个简单的Web应用程序

    Nest是一个用于构建高效、可扩展的Node.js服务器端应用程序的框架。它是基于Express.js构建的,并且提供了多种新特性和抽象层,可以让开发者更加轻松地构建复杂的应用程序。 本文将介绍Nest的基本概念,以及如何使用Nest CLI来构建一个简单的Web应用程序。 模块 在Nest中,模块

    2024年02月02日
    浏览(110)
  • idea使用docker-compose发布应用程序

    idea要想使用docker-compose,不能使用ssh创建idea Docker,而需要使用socket创建idea Docker。 socket docker是不安全的,任何人都可以访问你的docker,所以只能测试环境使用,请勿在正式环境使用socket docker。 云服务器安全组开放2375端口,如果不是云服务器则自己修改防火墙规则开放237

    2024年02月02日
    浏览(37)
  • Flutter中的Web应用程序开发:构建现代Web应用程序

    作者:禅与计算机程序设计艺术 作为人工智能专家,程序员和软件架构师,CTO,我今天将为大家分享有关 Flutter 中 Web 应用程序开发的见解。在这篇文章中,我们将深入探讨 Flutter Web 应用程序的开发过程、技术原理以及最佳实践。 引言 随着移动设备的普及,Web 应用程序在全

    2024年02月12日
    浏览(74)
  • 【Serverless Web 应用程序】构建流程

    【1】选择构建 Serverless Web 应用程序,程序架构如下所示: 【2】开发流程 【2.1】静态 Web 托管与持续部署: 所有的静态网页内容(HTML、CSS、JavaScript、图 像)和其他文件将由 AWS Amplify 控制台管理。用户将使用 AWS Amplify 控制 台公开的公共网站 URL 访问 Web。不需要额外运行

    2024年02月03日
    浏览(56)
  • 使用Docker构建分布式应用程序

    作者:禅与计算机程序设计艺术 Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux或Windows机器上,也可以实现虚拟化。 传统的应用分为三层结构:应用运行环境、应用逻辑和资源管理,Doc

    2024年02月08日
    浏览(74)
  • 基于aws构建一个web应用程序

    经验帖以及个人总结。 一. 在创建EC2主机前,可先行创建密匙以及安全组。 关于安全组: 1. 入站规则(别人访问你做的一些限制) :开放ssh 端口。是为了可以进行linux相关的连接。                                                                      开放http端口。

    2024年02月08日
    浏览(44)
  • vite + electron 构建前端桌面应用程序

    npm yarn 选择是否继续 项目名称 选择框架 选择项目语言 项目构建成功,根据提示进入项目目录,安装依赖 electron 官网:https://www.electronjs.org/zh/docs/latest/ vite-plugin-electron :https://github.com/electron-vite/vite-plugin-electron 安装依赖(electron 安装比较慢,耐心等待即可) 编写 Electron 入

    2024年02月06日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包