Android Compose 新闻App(六)导航动画、WebView、浮动按钮、底部导航

前言正文一、导航动画① 添加依赖② 使用

二、WebView使用① 导航传递URL参数② 配置WebView

三、FloatingActionButton使用① 修改默认显示位置

四、App主页面构建① 密封类② 构建底部导航Item③ 装载底部导航Item④ 显示导航

五、源码

前言

  在上篇文章中完成了页面的导航,而在本篇文章中将会有更多新的Compose用法,一起来看看吧。

正文

  一些应用有一些花里花哨的操作就会让人眼前一亮,大部分花里胡哨的操作就是动画,那么作为Compose的导航也是可以使用动画的,下面我们来使用一下:

一、导航动画

① 添加依赖

  导航动画是需要一个依赖库的,在app的build.gradle的dependencies{}闭包中中增加如下代码:

//Navigation动画

implementation "com.google.accompanist:accompanist-navigation-animation:$accompanist_version"

这里的accompanist_version在之前的文章中已经定义好了,accompanist_version = ‘0.24.4-alpha’。

② 使用

使用之前我们先来看一下要更改的地方,如下图所示: 图中是上一篇文章中所写的代码,如果要使导航有动画效果,则需要换一下。换了之后如下图所示:

对应的包名就是这三个:

import com.google.accompanist.navigation.animation.AnimatedNavHost

import com.google.accompanist.navigation.animation.composable

import com.google.accompanist.navigation.animation.rememberAnimatedNavController

这里动画分为四种模式 enterTransition :进入当前页面的动画。 exitTransition:退出当前页面的动画。 popEnterTransition:当前页面在另一个页面弹出后重新出现的动画。 popExitTransition:当前页面弹出栈后隐藏时的动画。

这些动画可以直接设置在NavHost中,下面我们设置一下: 下面我们运行一下: 可以看到当前页面进入到详情页面有动画效果,而返回之前的页面时也是这个动画效果,两者一样,我们再试试其他的动画。 这里用的是展开和收缩动画,然后我们在动画中增加一个动画时间,都是500毫秒,下面我们运行一下看看效果: 下面我们再尝试一个滑动动画。 运行一下:

这些动画效果要多去尝试,才可以的。找一个自己觉得喜欢的就行了,这个滑动的效果就不错,不是那么花里胡哨同样又能提高用户的体验。

二、WebView使用

  做过常规应用开发的对WebView肯定不陌生,甚至有的H5页面居多的App,全靠WebView来操作,那么在Compose中怎么去使用WebView呢?这是一个值得去探究的问题,我们结合到当前App的实际情况来看。

① 导航传递URL参数

  当前的App中有两个页面,疫情新闻页面和风险区详情页面,那么我们需要再写一个WebView的加载页面,可以让我们去加载Url。在pages包下,新建一个WebViewPage.kt文件,里面的代码如下:

@Composable

fun WebViewPage(navController: NavHostController, title: String, url: String){

Scaffold(

topBar = {

//顶部应用栏

TopAppBar(

title = {

Text(

text = title,

modifier = Modifier.fillMaxWidth(),

color = MaterialTheme.colors.onSecondary,

overflow = TextOverflow.Ellipsis, //超出省略

maxLines = 1 //单行显示

)

},

navigationIcon = {

IconButton(onClick = { navController.popBackStack() }) {

Icon(

imageVector = Icons.Filled.ArrowBack,

contentDescription = "ArrowBack"

)

}

},

elevation = 4.dp

)

}

) {

AndroidView(factory = { context ->

val webView = WebView(context)

webView.settings.javaScriptEnabled = true

webView.settings.javaScriptCanOpenWindowsAutomatically = true

webView.settings.domStorageEnabled = true

webView.settings.loadsImagesAutomatically = true

webView.settings.mediaPlaybackRequiresUserGesture = false

webView.webViewClient = WebViewClient()

webView.loadUrl(url)

webView

})

}

}

此函数参数有三个,navController,title,url。着重讲一下WebView的使用,Compose中目前并没有WebView的直接使用,因为我们的WebView还是Android的原生WebView,没有经过Compose的封装,而如果要在Compose中使用原生的Android控件,则就需要通过AndroidView来加载。

然后我们在PageConstant中增加一个WEB_VIEW_PAGE,如下图所示:

下面我们在HomeActivity中添加一个composable用来设置WebView页面,如下图所示: 然后是设置点击跳转的地方,如下图中所示: 这里的列表数据中的new中是有url的,因此我们几点将title和url传递过去,在EpidemicNewsListPage中添加如下图所示的代码。 记得clickable要添加,下面我们运行一下,看能不能跳转过去。 真是世事难料啊,没想到会报错,报错的原因就是url的问题,如果我们将Url作为参数传递,那么需要对url做一个处理,如下图所示: 下面我们再运行一次:

加载就完成了。

② 配置WebView

我们同样可以检测Url加载的进度。

在WebViewPage函数中添加如下代码:

val mWebViewClient = object : WebViewClient() {

override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {

super.onPageStarted(view, url, favicon)

Log.d("webView", "加载开始")

}

override fun onPageFinished(view: WebView?, url: String?) {

super.onPageFinished(view, url)

Log.d("webViewT", "加载完成")

}

}

val mWebViewChromeClient = object : WebChromeClient() {

override fun onProgressChanged(view: WebView?, newProgress: Int) {

Log.d("webView", "加载:$newProgress")

super.onProgressChanged(view, newProgress)

}

}

然后再修改一下AndroidView中的内容,如下图所示: 最终位置如下图所示: 运行一下: 嗯,OK。

三、FloatingActionButton使用

  浮动按钮在日常开发中,也是很常见的,下面在我们的EpidemicNewsListPage中添加一个浮动按钮。 因为页面使用了Scaffold,因此可以直接通过Scaffold去添加浮动按钮。 添加浮动按钮的同时,我把TopAppBar中多余的内容清除掉了,下面我们运行一下: 点击时弹出Toast,默认显示在页面的右下角。

那如果要改位置呢?

① 修改默认显示位置

就两个参数,默认就是End。 当然了,上面说的是在Scaffold,如果你要换一个地方显示呢?那就按照之前写常规布局那样,用Column然后使用Box做层叠就好了。这里我们还是改成End。

floatingActionButtonPosition = FabPosition.End

这里疫情详情页面已经是写完了,你会看到当前页面中有一个浮动按钮,那么这个按钮就是用来返回主页面的,App现在还没有主页面的,下面我们来构建主页面。

四、App主页面构建

在pages包下新建一个HomePage.kt文件,里面的代码如下:

@Composable

fun HomePage(navController: NavHostController) {

Scaffold(

topBar = {

//顶部应用栏

TopAppBar(

title = {

Text(

text = stringResource(id = R.string.app_name),

modifier = Modifier.fillMaxWidth(),

color = MaterialTheme.colors.onSecondary,

overflow = TextOverflow.Ellipsis, //超出省略

maxLines = 1, //单行显示

textAlign = TextAlign.Center

)

}

)

}

) {

}

}

然后在PageConstant中增加一个

const val HOME_PAGE = "homePage"

再回到HomeActivity中。 将第一个启动的页面改成HomePage,再运行之后如下图所示。

在这里我们将进行页面的导航。

① 密封类

首先我们在app的build.gradle的dependencies{}闭包中添加如下依赖:

//图标库

implementation "androidx.compose.material:material-icons-extended:$compose_version"

Sync Now,这是一个图标库,后面我们将用到它。

下面构建一个密封类,在utils包下新建一个BottomItemScreen,代码如下:

/**

* 定义路线名称,底部标题和图标

*/

sealed class BottomItemScreen(val route: String, val title: String, val icon: ImageVector){

object HOME: BottomItemScreen(HOME_ITEM,"首页", Icons.Default.Home)

object STAR: BottomItemScreen(COLLECTION_ITEM,"收藏", Icons.Default.Favorite)

}

② 构建底部导航Item

在ui包下新建一个BottomBarView.kt,里面的代码如下:

@Composable

fun BottomBarView(navController: NavController) {

val navItem = listOf(

BottomItemScreen.HOME,

BottomItemScreen.STAR

)

val navBackStackEntry by navController.currentBackStackEntryAsState()

//当前路线

val currentRoute = navBackStackEntry?.destination?.route

BottomAppBar {

navItem.forEach {

BottomNavigationItem(

label = { Text(text = it.title) },//设置item标签

icon = { Icon(imageVector = it.icon, contentDescription = it.title)},//设置item图标

selectedContentColor = Color.White,//选中时颜色

unselectedContentColor = colorResource(id = R.color.gray),//未选中时颜色

selected = currentRoute == it.route,//选中时赋值

onClick = {

//点击时根据,选中了不同items,则先赋值,在进行路线导航,导航后保存状态,

navController.navigate(it.route){

popUpTo(navController.graph.findStartDestination().id){

saveState = true

}

launchSingleTop = true

restoreState = true

}

}

)

}

}

}

这个可组合函数就是构建底部导航的ItemView,然后我们在PageConstant中定义主页中的两个子页面的描述

const val HOME_ITEM = "home"

const val COLLECTION_ITEM = "collection"

下面我们回到HomePage.kt中,主页面中修改代码如下:

③ 装载底部导航Item

@Composable

fun HomePage() {

val navController = rememberAnimatedNavController()

Scaffold(

topBar = {

//顶部应用栏

TopAppBar(

title = {

Text(

text = stringResource(id = R.string.app_name),

modifier = Modifier.fillMaxWidth(),

color = MaterialTheme.colors.onSecondary,

overflow = TextOverflow.Ellipsis, //超出省略

maxLines = 1, //单行显示

textAlign = TextAlign.Center

)

}

)

},

modifier = Modifier.fillMaxSize(),

bottomBar = {

BottomBarView(navController)

}

) {

AnimatedNavHost(

navController = navController,

startDestination = HOME_ITEM,

enterTransition = {

slideInHorizontally(

initialOffsetX = { fullWidth -> fullWidth },

animationSpec = tween(500)

)

},

exitTransition = {

slideOutHorizontally(

targetOffsetX = { fullWidth -> -fullWidth },

animationSpec = tween(500)

)

},

popEnterTransition = {

slideInHorizontally(

initialOffsetX = { fullWidth -> -fullWidth },

animationSpec = tween(500)

)

},

popExitTransition = {

slideOutHorizontally(

targetOffsetX = { fullWidth -> fullWidth },

animationSpec = tween(500)

)

}

) {

composable(HOME_ITEM) {

HomeItem()

}

composable(COLLECTION_ITEM) {

CollectionItem()

}

}

}

}

这里关键的代码如下图标注所示: 主要就是在Scaffold中增加了一个bottomBar,然后设置AnimatedNavHost,这和前面的内容相似。

④ 显示导航

那么现在我们还需要新建两个Item,在pages包下新建一个HomeItem.kt

@Composable

fun HomeItem() {

Text(text = "Home")

}

再新建一个CollectionItem.kt

@Composable

fun CollectionItem() {

Text(text = "Collection")

}

现在该有的就都有了,下面我们运行一下:

下一篇将会增加一个抽屉,然后在抽屉中增加疫情新闻的入口。

五、源码

如果你觉得代码对你有帮助的话,不妨Fork或者Star一下~ GitHub:GoodNews CSDN:GoodNews_6.rar

相关文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。