Android Compose News App Navigation Animation, WebView, Floating Button, Bottom Navigation

Android Compose News App (6) Navigation Animation, WebView, Floating Button, Bottom Navigation

foreword

  The navigation of the page is completed in the previous article, and there will be more new Compose usages in this article, let's take a look.

text

  Some applications have some fancy operations that will make people's eyes shine. Most of the fancy operations are animations, so animations can also be used as Compose navigation. Let's use them below:

1. Navigation animation

① Add dependencies

  The navigation animation requires a dependency library. Add the following code to the dependencies{} closure of the app's build.gradle:

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

The accompanist_version here has been defined in the previous article, accompanist_version = '0.24.4-alpha'.

② use

Before using it, let's take a look at the places to be changed, as shown in the following figure:

The picture is the code written in the previous article. If you want to animate the navigation, you need to change it. After the replacement, it looks like the following picture:

The corresponding package names are these three:

import com.google.accompanist.navigation.animation.AnimatedNavHost
import com.google.accompanist.navigation.animation.composable
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
copy

The animation is divided into four modes

enterTransition : The animation to enter the current page. exitTransition: The animation to exit the current page. popEnterTransition: The animation of the current page reappearing after another page pops up. popExitTransition: The animation when the current page is hidden after being popped out of the stack.

These animations can be set directly in NavHost, let's set them up:

Let's run it:

You can see that the current page has an animation effect when entering the details page, and the animation effect is also the same when returning to the previous page. The two are the same. Let's try other animations.

The expansion and contraction animation is used here, and then we add an animation time to the animation, which is 500 milliseconds. Let's run it to see the effect:

Let's try another sliding animation.

Run it:

These animation effects have to be tried a lot before they can. Just find one that you like, the effect of this sliding is good, not so fancy but also can improve the user's experience.

Second, the use of WebView

   Those who have done conventional application development are definitely not unfamiliar with WebView, and even some apps with most H5 pages rely on WebView to operate, so how to use WebView in Compose? This is a question worth exploring, and we combine it with the actual situation of the current App.

① Navigation passes URL parameters

   There are two pages in the current App, the epidemic news page and the risk area details page, then we need to write another WebView loading page, which allows us to load the Url. Under the pages package, create a new WebViewPage.kt file with the following code:

@Composable
fun WebViewPage(navController: NavHostController, title: String, url: String){
    Scaffold(
        topBar = {
            //top app bar
            TopAppBar(
                title = {
                    Text(
                        text = title,
                        modifier = Modifier.fillMaxWidth(),
                        color = MaterialTheme.colors.onSecondary,
                        overflow = TextOverflow.Ellipsis, //beyond omission
                        maxLines = 1 //single line display
                    )
                },
                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
            })
    }
}
copy

This function has three parameters, navController, title, url. Focus on the use of WebView. There is currently no direct use of WebView in Compose, because our WebView is still Android's native WebView and has not been encapsulated by Compose. If you want to use native Android controls in Compose, you need to pass AndroidView. to load.

Then we add a WEB_VIEW_PAGE to PageConstant, as shown in the following figure:

Next, we add a composable to the HomeActivity to set the WebView page, as shown in the following figure:

Then it is to set the place to click to jump, as shown in the following figure:

There is a url in new in the list data here, so we pass the title and url at a few points, and add the code shown in the following figure to the EpidemicNewsListPage.

Remember to add clickable, let's run it and see if we can jump over.

It's really unpredictable. I didn't expect an error to be reported. The reason for the error is the problem of the url. If we pass the Url as a parameter, we need to do a processing on the url, as shown in the following figure:

Let's run it again:

Loading is complete.

② Configure WebView

We can also detect the progress of Url loading.

Add the following code to the WebViewPage function:

		val mWebViewClient = object : WebViewClient() {
            override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                super.onPageStarted(view, url, favicon)
                Log.d("webView", "loading starts")
            }
            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                Log.d("webViewT", "Loading completed")
            }
        }
        val mWebViewChromeClient = object : WebChromeClient() {
            override fun onProgressChanged(view: WebView?, newProgress: Int) {
                Log.d("webView", "load: $newProgress")
                super.onProgressChanged(view, newProgress)
            }
        }
copy

Then modify the content in the AndroidView, as shown below:

The final position is shown below:

Run it:

Hmm, OK.

Three, FloatingActionButton use

  Floating buttons are also very common in daily development. Let's add a floating button to our EpidemicNewsListPage. Because the page uses Scaffold, you can add floating buttons directly through Scaffold.

While adding the floating button, I cleared the excess content in the TopAppBar, let's run it:

Toast pops up when clicked, and is displayed in the lower right corner of the page by default.

What if you want to change the location?

① Modify the default display position

Only two parameters, the default is End.

Of course, the above is in Scaffold, what if you want to display it in another place? Then just use Column and then use Box to do the stacking as you wrote the regular layout before. Here we still change it to End.

floatingActionButtonPosition = FabPosition.End
copy

Here the epidemic details page has been written, you will see a floating button on the current page, then this button is used to return to the main page, the App does not have a main page yet, let's build the main page.

4. Construction of App main page

Create a new HomePage.kt file under the pages package with the following code:

@Composable
fun HomePage(navController: NavHostController) {
    Scaffold(
        topBar = {
            //top app bar
            TopAppBar(
                title = {
                    Text(
                        text = stringResource(id = R.string.app_name),
                        modifier = Modifier.fillMaxWidth(),
                        color = MaterialTheme.colors.onSecondary,
                        overflow = TextOverflow.Ellipsis, //beyond omission
                        maxLines = 1, //single line display
                        textAlign = TextAlign.Center
                    )
                }
            )
        }
    ) {

    }
}
copy

Then add one in PageConstant

const val HOME_PAGE = "homePage"
copy

Go back to HomeActivity.

Change the first startup page to HomePage, and then run it as shown below.

Here we will navigate the page.

① Sealed

First, we add the following dependencies to the dependencies{} closure of the app's build.gradle:

	//icon library
    implementation "androidx.compose.material:material-icons-extended:$compose_version"
copy

Sync Now, this is an icon library that we will use later.

Next, build a sealed class and create a new BottomItemScreen under the utils package. The code is as follows:

/**
 * Define route name, bottom title and icon
 */
sealed class BottomItemScreen(val route: String, val title: String, val icon: ImageVector){
    object HOME: BottomItemScreen(HOME_ITEM,"front page", Icons.Default.Home)
    object STAR: BottomItemScreen(COLLECTION_ITEM,"collect", Icons.Default.Favorite)
}
copy

② Build the bottom navigation Item

Create a new BottomBarView.kt under the ui package, and the code inside is as follows:

@Composable
fun BottomBarView(navController: NavController) {
    val navItem = listOf(
        BottomItemScreen.HOME,
        BottomItemScreen.STAR
    )
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    //current route
    val currentRoute = navBackStackEntry?.destination?.route
    BottomAppBar {
        navItem.forEach { 
            BottomNavigationItem(
                label = { Text(text = it.title) },//set item tag
                icon = { Icon(imageVector = it.icon, contentDescription = it.title)},//Set item icon
                selectedContentColor = Color.White,//color when selected
                unselectedContentColor = colorResource(id = R.color.gray),//color when unchecked
                selected = currentRoute == it.route,//Assign when selected
                onClick = {
                    //When clicking, according to the different items selected, assign value first, then navigate the route, save the state after navigation,
                    navController.navigate(it.route){
                        popUpTo(navController.graph.findStartDestination().id){
                            saveState = true
                        }
                        launchSingleTop = true
                        restoreState = true
                    }
                }
            )
        }
    }
}
copy

This composable function is to build the ItemView for the bottom navigation, and then we define the descriptions of the two subpages in the main page in the PageConstant

	const val HOME_ITEM = "home"

    const val COLLECTION_ITEM = "collection"
copy

Let's go back to HomePage.kt. The modified code in the main page is as follows:

③ Load the bottom navigation Item

@Composable
fun HomePage() {
    val navController = rememberAnimatedNavController()
    Scaffold(
        topBar = {
            //top app bar
            TopAppBar(
                title = {
                    Text(
                        text = stringResource(id = R.string.app_name),
                        modifier = Modifier.fillMaxWidth(),
                        color = MaterialTheme.colors.onSecondary,
                        overflow = TextOverflow.Ellipsis, //beyond omission
                        maxLines = 1, //single line display
                        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()
            }
        }
    }
}
copy

The key code here is marked as follows:

The main thing is to add a bottomBar in Scaffold, and then set AnimatedNavHost, which is similar to the previous content.

④ Display navigation

So now we need to create two new items, and create a new Home Item.kt under the pages package

@Composable
fun HomeItem() {
    Text(text = "Home")
}
copy

Create a new CollectionItem.kt

@Composable
fun CollectionItem() {
    Text(text = "Collection")
}
copy

Now that you have everything you need, let's run it:

The next article will add a drawer, and then add an entry for epidemic news in the drawer.

5. Source code

If you think the code is helpful to you, please Fork or Star it~ GitHub: GoodNews CSDN: GoodNews_6.rar

Posted by felipe_lopes on Tue, 03 May 2022 15:54:17 +0300