Skip to content

Instantly share code, notes, and snippets.

@fornewid
Created April 27, 2019 15:58
Show Gist options
  • Save fornewid/286d4feeeda4a0858f294de833fb3d93 to your computer and use it in GitHub Desktop.
Save fornewid/286d4feeeda4a0858f294de833fb3d93 to your computer and use it in GitHub Desktop.
package soup.gdg.navigation.sample.navigation
import android.content.Context
import android.os.Bundle
import android.util.AttributeSet
import android.util.Log
import androidx.annotation.CallSuper
import androidx.annotation.IdRes
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.navigation.NavDestination
import androidx.navigation.NavOptions
import androidx.navigation.Navigator
import androidx.navigation.NavigatorProvider
import androidx.navigation.fragment.FragmentNavigator
import androidx.navigation.fragment.R
@Navigator.Name("dialog_fragment")
class DialogFragmentNavigator(
private val context: Context,
private val fragmentManager: FragmentManager
) : Navigator<DialogFragmentNavigator.Destination>() {
companion object {
private const val TAG = "DialogFragmentNavigator"
}
override fun navigate(
destination: Destination,
args: Bundle?,
navOptions: NavOptions?,
navigatorExtras: Extras?
): NavDestination? {
if (fragmentManager.isStateSaved) {
Log.i(TAG, "Ignoring navigate() call: FragmentManager has already saved its state")
return null
}
var className = destination.getClassName()
if (className[0] == '.') {
className = context.packageName + className
}
val frag = instantiateDialogFragment(context, fragmentManager, className)
frag.arguments = args
@IdRes val destId = destination.id
frag.setTargetFragment(
fragmentManager.primaryNavigationFragment,
destId /* requestCode */
)
frag.show(fragmentManager, "dialog-$destId")
return null
}
private fun instantiateDialogFragment(
context: Context,
fragmentManager: FragmentManager,
className: String
): DialogFragment {
return fragmentManager.fragmentFactory.instantiate(context.classLoader, className)
as DialogFragment
}
override fun createDestination(): Destination {
return Destination(this)
}
override fun popBackStack(): Boolean {
return true
}
@NavDestination.ClassType(Fragment::class)
class Destination : NavDestination {
private var className: String? = null
constructor(navigatorProvider: NavigatorProvider) :
super(navigatorProvider.getNavigator(FragmentNavigator::class.java))
constructor(fragmentNavigator: Navigator<out Destination>) :
super(fragmentNavigator)
@CallSuper
override fun onInflate(context: Context, attrs: AttributeSet) {
super.onInflate(context, attrs)
val a = context.resources.obtainAttributes(attrs, R.styleable.FragmentNavigator)
val className = a.getString(R.styleable.FragmentNavigator_android_name)
if (className != null) {
setClassName(className)
}
a.recycle()
}
fun setClassName(className: String): Destination {
this.className = className
return this
}
fun getClassName(): String {
return className ?: throw IllegalStateException("Fragment class was not set")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment