Android Compose 新闻App导航动画WebView浮动按钮底部导航

Posted 初学者-Study

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Compose 新闻App导航动画WebView浮动按钮底部导航相关的知识,希望对你有一定的参考价值。

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

前言

  在上篇文章中完成了页面的导航,而在本篇文章中将会有更多新的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

以上是关于Android Compose 新闻App导航动画WebView浮动按钮底部导航的主要内容,如果未能解决你的问题,请参考以下文章

Android Compose 新闻AppRoom复杂数据AlertDialog弹窗页面导航

Android Compose 新闻App抽屉布局动态权限拍照返回

Android Compose 新闻App抽屉布局动态权限拍照返回

Android Compose 新闻App抽屉布局动态权限拍照返回

Android Compose 新闻App网络框架搭建

Android Compose 新闻App网络数据Compose UI显示加载Room和DataStore使用