commit
8532d190e8
|
|
@ -3,6 +3,6 @@
|
|||
/local.properties
|
||||
/.idea
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
**/build
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
buildscript {
|
||||
ext.kotlin_version = '1.3.11'
|
||||
ext.kotlin_version = '1.3.50'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
android {
|
||||
compileSdkVersion versions.compileSdk
|
||||
|
|
@ -21,14 +22,19 @@ dependencies {
|
|||
|
||||
api 'androidx.multidex:multidex:2.0.1'
|
||||
|
||||
api 'net.danlew:android.joda:2.9.9.4'
|
||||
api 'net.danlew:android.joda:2.10.2'
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
implementation "androidx.appcompat:appcompat:$versions.appcompat"
|
||||
|
||||
implementation "androidx.fragment:fragment:$versions.fragment"
|
||||
implementation "androidx.fragment:fragment-ktx:$versions.fragment"
|
||||
|
||||
implementation "com.jakewharton:butterknife:$versions.butterknife"
|
||||
kapt "com.jakewharton:butterknife-compiler:$versions.butterknife"
|
||||
|
||||
implementation("com.crashlytics.sdk.android:crashlytics:$versions.crashlytics@aar") {
|
||||
transitive = true
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,12 +21,16 @@ package ru.touchin.roboswag.components.navigation
|
|||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.MenuItem
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import ru.touchin.roboswag.core.log.Lc
|
||||
import ru.touchin.roboswag.components.navigation.fragments.BaseFragment
|
||||
import ru.touchin.roboswag.components.navigation.viewcontrollers.EmptyState
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Created by Gavriil Sitnikov on 07/03/2016.
|
||||
|
|
@ -150,9 +154,27 @@ open class FragmentNavigation(
|
|||
fragmentClass: Class<out Fragment>,
|
||||
args: Bundle? = null,
|
||||
addToStack: Boolean = true,
|
||||
backStackName: String? = null,
|
||||
transactionSetup: ((FragmentTransaction) -> Unit)? = null
|
||||
) {
|
||||
addToStack(fragmentClass, null, 0, addToStack, args, null, transactionSetup)
|
||||
addToStack(fragmentClass, null, 0, addToStack, args, backStackName, transactionSetup)
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes [Fragment] on top of stack with specific target fragment, arguments and transaction setup.
|
||||
*
|
||||
* @param fragmentClass KClass of [Fragment] to instantiate;
|
||||
* @param state State of instantiated [Fragment];
|
||||
* @param transactionSetup Function to setup transaction before commit. It is useful to specify transition animations or additional info.
|
||||
*/
|
||||
fun <T: Parcelable> push(
|
||||
fragmentClass: KClass<out BaseFragment<*, out T>>,
|
||||
state: T? = null,
|
||||
addToStack: Boolean = true,
|
||||
backStackName: String? = null,
|
||||
transactionSetup: ((FragmentTransaction) -> Unit)? = null
|
||||
) {
|
||||
push(fragmentClass.java, BaseFragment.args(state ?: EmptyState), addToStack, backStackName, transactionSetup)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -181,6 +203,24 @@ open class FragmentNavigation(
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes [Fragment] on top of stack with specific target fragment, arguments and transaction setup.
|
||||
*
|
||||
* @param fragmentClass KClass of [Fragment] to instantiate;
|
||||
* @param targetFragment Target fragment to be set as [Fragment.getTargetFragment] of instantiated [Fragment];
|
||||
* @param state State of instantiated [Fragment];
|
||||
* @param transactionSetup Function to setup transaction before commit. It is useful to specify transition animations or additional info.
|
||||
*/
|
||||
fun <T: Parcelable> pushForResult(
|
||||
fragmentClass: KClass<out BaseFragment<*, out T>>,
|
||||
targetFragment: Fragment,
|
||||
targetRequestCode: Int,
|
||||
state: T? = null,
|
||||
transactionSetup: ((FragmentTransaction) -> Unit)? = null
|
||||
) {
|
||||
pushForResult(fragmentClass.java, targetFragment, targetRequestCode, BaseFragment.args(state ?: EmptyState), transactionSetup)
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes [Fragment] on top of stack with specific transaction setup, arguments
|
||||
* and with [.TOP_FRAGMENT_TAG_MARK] tag used for simple up/back navigation.
|
||||
|
|
@ -215,6 +255,22 @@ open class FragmentNavigation(
|
|||
setAsTop(fragmentClass, args, false, transactionSetup)
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops all [Fragment]s and places new initial [Fragment] on top of stack with specific transaction setup and arguments.
|
||||
*
|
||||
* @param fragmentClass Class of [Fragment] to instantiate;
|
||||
* @param state State of instantiated [Fragment];
|
||||
* @param transactionSetup Function to setup transaction before commit. It is useful to specify transition animations or additional info.
|
||||
*/
|
||||
fun <T: Parcelable> setInitial(
|
||||
fragmentClass: KClass<out BaseFragment<*, out T>>,
|
||||
state: T? = null,
|
||||
transactionSetup: ((FragmentTransaction) -> Unit)? = null
|
||||
) {
|
||||
beforeSetInitialActions()
|
||||
setAsTop(fragmentClass.java, BaseFragment.args(state ?: EmptyState), false, transactionSetup)
|
||||
}
|
||||
|
||||
/**
|
||||
* Method calls every time before initial [Fragment] will be placed.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
package ru.touchin.roboswag.components.navigation.fragments
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.view.View
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import butterknife.ButterKnife
|
||||
import butterknife.Unbinder
|
||||
import ru.touchin.roboswag.components.navigation.BuildConfig
|
||||
import ru.touchin.roboswag.components.navigation.viewcontrollers.LifecycleLoggingObserver
|
||||
|
||||
open class BaseFragment<TActivity : FragmentActivity, TState : Parcelable>(@LayoutRes layoutRes: Int) : Fragment(layoutRes) {
|
||||
|
||||
companion object {
|
||||
private const val BASE_FRAGMENT_STATE_EXTRA = "BASE_FRAGMENT_STATE_EXTRA"
|
||||
|
||||
fun args(state: Parcelable?): Bundle = Bundle().also { it.putParcelable(BASE_FRAGMENT_STATE_EXTRA, state) }
|
||||
|
||||
// This method used to check unique state of each fragment.
|
||||
// If two fragments share same class for state, you should not pass state instance of current fragment to the one you transition to
|
||||
private fun <T : Parcelable> reserialize(parcelable: T): T {
|
||||
var parcel = Parcel.obtain()
|
||||
parcel.writeParcelable(parcelable, 0)
|
||||
val serializableBytes = parcel.marshall()
|
||||
parcel.recycle()
|
||||
parcel = Parcel.obtain()
|
||||
parcel.unmarshall(serializableBytes, 0, serializableBytes.size)
|
||||
parcel.setDataPosition(0)
|
||||
val result = parcel.readParcelable<T>(Thread.currentThread().contextClassLoader) ?: throw IllegalStateException("It must not be null")
|
||||
parcel.recycle()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
protected val view: View
|
||||
@JvmName("requireViewKtx") get() = requireView()
|
||||
|
||||
protected val activity: TActivity
|
||||
@JvmName("requireActivityKtx") get() = requireActivity() as TActivity
|
||||
|
||||
protected val context: Context
|
||||
@JvmName("requireContextKtx") get() = requireContext()
|
||||
|
||||
protected lateinit var state: TState
|
||||
private set
|
||||
|
||||
private lateinit var butterKnifeUnbinder: Unbinder
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setHasOptionsMenu(true)
|
||||
|
||||
state = savedInstanceState?.getParcelable<TState>(BASE_FRAGMENT_STATE_EXTRA)
|
||||
?: arguments?.getParcelable(BASE_FRAGMENT_STATE_EXTRA)
|
||||
?: throw IllegalStateException("Fragment state can't be null")
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
state = reserialize(state)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
lifecycle.addObserver(LifecycleLoggingObserver())
|
||||
butterKnifeUnbinder = ButterKnife.bind(this, view)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
butterKnifeUnbinder.unbind()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putParcelable(BASE_FRAGMENT_STATE_EXTRA, state)
|
||||
}
|
||||
|
||||
fun <T : View> findViewById(@IdRes id: Int): T = view.findViewById(id)
|
||||
|
||||
@ColorInt
|
||||
fun getColor(@ColorRes resId: Int): Int = ContextCompat.getColor(requireContext(), resId)
|
||||
|
||||
fun getColorStateList(@ColorRes resId: Int): ColorStateList? = ContextCompat.getColorStateList(context, resId)
|
||||
|
||||
fun getDrawable(@DrawableRes resId: Int): Drawable? = ContextCompat.getDrawable(context, resId)
|
||||
|
||||
}
|
||||
|
|
@ -171,7 +171,7 @@ open class ViewControllerFragment<TActivity : FragmentActivity, TState : Parcela
|
|||
viewController?.onCreateOptionsMenu(menu, inflater)
|
||||
}
|
||||
|
||||
override fun onPrepareOptionsMenu(menu: Menu?) {
|
||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||
viewController?.onPrepareOptionsMenu(menu)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue