2

I want to implement new Android Navigation component in my app. As I know, the fragment that is basically used to host fragments (NavHostFragment), uses by default FrameLayout. But, unfortunately, FrameLayout doesn't know anythhing about window insets because it was developed way before Android 4.4. So I want to know how can I create my own NavHostFragment which will use CoordinatorLayout as root element to pass window insets downside in view hierarchy.

Kiryl Tkach
  • 3,118
  • 5
  • 20
  • 36

1 Answers1

0

To replace FrameLayout with CoordinatorLayout you can create custom NavHostFrament and override onCreateView method.

inside of 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;
}

As you can see, FrameLayout is created programmatically and it's id gets set before returning it.

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
    }
}

However, you don't need to replace NavHostFragment's default FrameLayout to CoordinatorLayout. According to Ian Lake's answer you can also implement ViewCompat.setOnApplyWindowInsetsListener() to intercept the calls for window insets and make necessary adjustments.

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()
    }
}
Marat
  • 6,142
  • 6
  • 39
  • 67