带有CoordinatorLayout的Android NavHostFragment

时间:2018-07-14 10:35:11

标签: android navigation navigationcontroller

我想在我的应用中实现新的Android导航组件。众所周知,默认情况下,基本上用于承载片段(NavHostFragment)的片段使用FrameLayout。但是,不幸的是,FrameLayout对窗口插入一无所知,因为它是在Android 4.4之前开发的。因此,我想知道如何创建自己的NavHostFragment,它将使用CoordinatorLayout作为根元素在视图层次结构中传递窗口插图。

1 个答案:

答案 0 :(得分:0)

要用CoordinatorLayout替换FrameLayout,可以创建自定义NavHostFrament并覆盖onCreateView方法。

在NavHostFragment内部

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    FrameLayout frameLayout = new FrameLayout(inflater.getContext());
    // When added via XML, this has no effect (since this FrameLayout is given the ID
    // automatically), but this ensures that the View exists as part of this Fragment's View
    // hierarchy in cases where the NavHostFragment is added programmatically as is required
    // for child fragment transactions
    frameLayout.setId(getId());
    return frameLayout;
}

如您所见,FrameLayout是通过编程方式创建的,其ID在返回之前已设置。

CustomNavHostFragment

class CustomNavHostFragment : NavHostFragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        // change it to CoordinatorLayout
        val view = CoordinatorLayout(inflater.context)
        view.id = id
        return view
    }
}

但是,您无需将NavHostFragment的默认FrameLayout替换为CoordinatorLayout。根据伊恩·莱克(Ian Lake)的answer,您还可以实现ViewCompat.setOnApplyWindowInsetsListener()来拦截对窗口插图的调用并进行必要的调整。

coordinatorLayout?.let {
    ViewCompat.setOnApplyWindowInsetsListener(it) { v, insets ->
        ViewCompat.onApplyWindowInsets(
            v, insets.replaceSystemWindowInsets(
                insets.systemWindowInsetLeft, 0,
                insets.systemWindowInsetRight, insets.systemWindowInsetBottom
            )
        )
        insets // return original insets to pass them down in view hierarchy or remove this line if you want to pass modified insets down the stream.
        // or
        // insets.consumeSystemWindowInsets()
    }
}