MIT License

项目介绍

furkanaskin/TrickyNavigationSample 是一个托管在 GitHub 上的开源项目,主要使用 Kotlin 编写,采用 MIT License 许可证,目前获得 151 个 Star、27 次 Fork。

仓库全名
furkanaskin/TrickyNavigationSample
开源许可证
MIT License
Star 数
151
Fork 数
27
未关闭 Issue
1

README 摘要

TrickyNavigationSample This repository contains some tricks about Android Navigation Component. 3rd party libraries not used. Outputs Default Bottom Behaviour | Tricky Bottom Behaviour :-------------------------:|:-------------------------:| Android Navigation Component default behavior hasn't got bottom navigation back stack. If you wanna add back stack to your bottomNavigationMenu it's easy and simple. Just add…

完整内容见 GitHub 原始 README 或本页 。

常见问题

TrickyNavigationSample 用什么语言开发?

主要使用 Kotlin 编写,采用 MIT License 许可证,目前有 151 个 Star。

TrickyNavigationSample 可以免费商用吗?

仓库采用 MIT License 许可证,可免费使用与修改,商业使用请遵守许可证条款(例如保留版权声明与许可声明)。

如何获取 TrickyNavigationSample 的源码?

可以直接克隆仓库:git clone https://github.com/furkanaskin/TrickyNavigationSample.git,默认分支为 master;安装与运行步骤见仓库 README。

TrickyNavigationSample 最近还在维护吗?

仓库最近一次更新为 2021年7月18日,当前有 1 个未关闭 Issue;Star 数为 151,可作为社区活跃度的参考。

关于

This repository contains some tricks about Android Navigation Component. 3rd party libraries not used.

描述取自 GitHub 官方 API,中文内容由 GitRead 中文社区 编辑团队整理。

语言占比

Kotlin

README

TrickyNavigationSample

This repository contains some tricks about Android Navigation Component. 3rd party libraries not used.

Outputs

Default Bottom Behaviour Tricky Bottom Behaviour

Android Navigation Component default behavior hasn’t got bottom navigation back stack. If you wanna add back stack to your bottomNavigationMenu it’s easy and simple. Just add:

android:menuCategory="secondary"

to your all menu items.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/homeFragment"
        android:icon="@drawable/ic_home"
        android:menuCategory="secondary"
        android:title="Home" />

    <item
        android:id="@+id/searchFragment"
        android:icon="@drawable/ic_search"
        android:menuCategory="secondary"
        android:title="Search" />

    <item
        android:id="@+id/gamesFragment"
        android:icon="@drawable/ic_games"
        android:menuCategory="secondary"
        android:title="Games" />

    <item
        android:id="@+id/notificationsFragment"
        android:icon="@drawable/ic_notifications"
        android:menuCategory="secondary"
        android:title="Notifications" />
</menu>
menuCategory=“secondary” Tricky “secondary”

With adding secondary to your items you gonna have backstack but if you want a stack like in Instagram or Youtube make the following changes:

First of all we need an extension for our navController.

fun NavController.popBackStackAllInstances(destination: Int, inclusive: Boolean): Boolean {
    var popped: Boolean
    while (true) {
        popped = popBackStack(destination, inclusive)
        if (!popped) {
            break
        }
    }
    return popped
}

Then extend your bottom tab fragments from BaseBottomTabFragment, don’t forget to use utils functions when you try to navigate from tab starter fragments.

BaseBottomTabFragment has onBackPressedDispatcher for handling back press. Also it has isNavigated boolean, because if it’s trying to navigate in same tab we don’t need to addCallback.

open class BaseBottomTabFragment : Fragment() {
    var isNavigated = false

    fun navigateWithAction(action: NavDirections) {
        isNavigated = true
        findNavController().navigate(action)
    }

    fun navigate(resId: Int) {
        isNavigated = true
        findNavController().navigate(resId)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        if (!isNavigated)
            requireActivity().onBackPressedDispatcher.addCallback(this) {
                val navController = findNavController()
                if (navController.currentBackStackEntry?.destination?.id != null) {
                    findNavController().popBackStackAllInstances(
                        navController.currentBackStackEntry?.destination?.id!!,
                        true
                    )
                } else
                    navController.popBackStack()
            }
    }
}

With this trick we have a back stack like Instagram and Youtube but we forgot something. As you know if you setup your toolbar with navController, your back press behaviour works with navController and onBackPressedDispatcher just affects your activiy’s back press. If you wanna get the same bottom behavior with your toolbar navigate button. Add to following code to your activity:

binding.toolbar.setNavigationOnClickListener {
    when (navController.currentDestination?.id) {
        R.id.searchFragment, R.id.gamesFragment, R.id.notificationsFragment -> {
            if (onBackPressedDispatcher.hasEnabledCallbacks())
                onBackPressedDispatcher.onBackPressed()
            else
                navController.navigateUp()
        }
        else -> navController.navigateUp()
    }
 }

Dynamic Label :-------------------------:

As you know, if you setup your toolbar with navController, your toolbar titles handling from navController. Navcontroller uses your fragment labels as title. For making this dynamically we need to use Android Navigation Component - SafeArgs

Define your argument as string in nav_graph

<fragment
    android:id="@+id/dynamicTitleFragment"
    android:name="com.faskn.trickynavigationsample.fragments.DynamicTitleFragment"
    android:label="{title}"
    tools:layout="@layout/fragment_dynamic_title" >
    <argument
        android:name="title"
        app:argType="string"
        android:defaultValue="Title" />
</fragment>

don’t forget to use your argument as label

android:label="{title}"

and then pass data between destinations

binding.buttonDynamicTitleNavigate.setOnClickListener {
    navigateWithAction(
        SearchFragmentDirections.actionSearchFragmentToDynamicTitleFragment(
            binding.editTextTitle.text.toString()
        )
    )
 }
Default Replace Tricky Replace

As you know, if you call findNavController().navigate() it replaces your current fragment with other and when you call back press maybe your state is not saved. The easiest solution is passing id to your all views. It works with ScrollView, Recyclerview, etc…

But the best solution is Event.kt or EventObserver.kt

Tricky Add :-------------------------:

With Android Navigation Component you can’t add any fragment to your container. But you just wanna add 3-4 fragment to your navController you can use this solution.

Navigation Component 2.1.0 supports <dialog> tag in navigation graph.

This trick uses BottomSheetDialogFragment as fullscreen and with isDraggable = false attribute. It works like add. But adding too many screens can cause performance issues. Be careful.

评论

暂无评论