diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index 4fbbde07..00000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-FragNav
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index b833761f..f4f9eb19 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,9 +2,9 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/java/com/ncapdevi/sample/activities/BottomTabsActivity.kt b/app/src/main/java/com/ncapdevi/sample/activities/BottomTabsActivity.kt
index 01326d98..1d2e81fc 100644
--- a/app/src/main/java/com/ncapdevi/sample/activities/BottomTabsActivity.kt
+++ b/app/src/main/java/com/ncapdevi/sample/activities/BottomTabsActivity.kt
@@ -10,39 +10,45 @@ import com.ncapdevi.fragnav.FragNavLogger
import com.ncapdevi.fragnav.FragNavSwitchController
import com.ncapdevi.fragnav.FragNavTransactionOptions
import com.ncapdevi.fragnav.tabhistory.FragNavTabHistoryController
+import com.ncapdevi.fragnav.tabhistory.UniqueTabHistoryStrategy
import com.ncapdevi.sample.R
import com.ncapdevi.sample.fragments.*
import com.roughike.bottombar.BottomBar
class BottomTabsActivity : AppCompatActivity(), BaseFragment.FragmentNavigation, FragNavController.TransactionListener, FragNavController.RootFragmentListener {
+ override val numberOfRootFragments: Int = 5
- private var fragNavController: FragNavController? = null
+ private val fragNavController: FragNavController = FragNavController(supportFragmentManager, R.id.container)
+
+ private lateinit var bottomBar: BottomBar
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(com.ncapdevi.sample.R.layout.activity_bottom_tabs)
- val bottomBar = findViewById(R.id.bottomBar)
-
- fragNavController = FragNavController.newBuilder(savedInstanceState,
- supportFragmentManager,
- R.id.container)
- .transactionListener(this)
- .rootFragmentListener(this, 5)
- .switchController(FragNavTabHistoryController.UNIQUE_TAB_HISTORY, object : FragNavSwitchController {
- override fun switchTab(index: Int, transactionOptions: FragNavTransactionOptions?) {
- bottomBar.selectTabAtPosition(index)
- }
- })
- .fragmentHideStrategy(FragNavController.DETACH_ON_NAVIGATE_HIDE_ON_SWITCH)
- .eager(true)
- .logger(object : FragNavLogger {
- override fun error(message: String, throwable: Throwable) {
- Log.e(TAG, message, throwable)
- }
- })
- .build()
+ bottomBar = findViewById(R.id.bottomBar)
+
+ fragNavController.apply {
+ transactionListener = this@BottomTabsActivity
+ rootFragmentListener = this@BottomTabsActivity
+ createEager = true
+ fragNavLogger = object : FragNavLogger {
+ override fun error(message: String, throwable: Throwable) {
+ Log.e(TAG, message, throwable)
+ }
+ }
+
+ fragmentHideStrategy = FragNavController.DETACH_ON_NAVIGATE_HIDE_ON_SWITCH
+
+ navigationStrategy = UniqueTabHistoryStrategy(object : FragNavSwitchController {
+ override fun switchTab(index: Int, transactionOptions: FragNavTransactionOptions?) {
+ bottomBar.selectTabAtPosition(index)
+ }
+ })
+ }
+
+ fragNavController.initialize(INDEX_NEARBY, savedInstanceState)
val initial = savedInstanceState == null
if (initial) {
@@ -50,41 +56,41 @@ class BottomTabsActivity : AppCompatActivity(), BaseFragment.FragmentNavigation,
}
- fragNavController?.executePendingTransactions()
+ fragNavController.executePendingTransactions()
bottomBar.setOnTabSelectListener({ tabId ->
when (tabId) {
- R.id.bb_menu_recents -> fragNavController?.switchTab(INDEX_RECENTS)
- R.id.bb_menu_favorites -> fragNavController?.switchTab(INDEX_FAVORITES)
- R.id.bb_menu_nearby -> fragNavController?.switchTab(INDEX_NEARBY)
- R.id.bb_menu_friends -> fragNavController?.switchTab(INDEX_FRIENDS)
- R.id.bb_menu_food -> fragNavController?.switchTab(INDEX_FOOD)
+ R.id.bb_menu_recents -> fragNavController.switchTab(INDEX_RECENTS)
+ R.id.bb_menu_favorites -> fragNavController.switchTab(INDEX_FAVORITES)
+ R.id.bb_menu_nearby -> fragNavController.switchTab(INDEX_NEARBY)
+ R.id.bb_menu_friends -> fragNavController.switchTab(INDEX_FRIENDS)
+ R.id.bb_menu_food -> fragNavController.switchTab(INDEX_FOOD)
}
}, initial)
- bottomBar.setOnTabReselectListener { fragNavController?.clearStack() }
+ bottomBar.setOnTabReselectListener { fragNavController.clearStack() }
}
override fun onBackPressed() {
- if (fragNavController?.popFragment()?.not() == true) {
+ if (fragNavController.popFragment().not()) {
super.onBackPressed()
}
}
override fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState)
- fragNavController?.onSaveInstanceState(outState!!)
+ fragNavController.onSaveInstanceState(outState!!)
}
override fun pushFragment(fragment: Fragment) {
- fragNavController?.pushFragment(fragment)
+ fragNavController.pushFragment(fragment)
}
override fun onTabTransaction(fragment: Fragment?, index: Int) {
// If we have a backstack, show the back button
- supportActionBar?.setDisplayHomeAsUpEnabled(fragNavController?.isRootFragment?.not() == true)
+ supportActionBar?.setDisplayHomeAsUpEnabled(fragNavController.isRootFragment.not())
}
@@ -92,7 +98,7 @@ class BottomTabsActivity : AppCompatActivity(), BaseFragment.FragmentNavigation,
override fun onFragmentTransaction(fragment: Fragment?, transactionType: FragNavController.TransactionType) {
//do fragmentty stuff. Maybe change title, I'm not going to tell you how to live your life
// If we have a backstack, show the back button
- supportActionBar?.setDisplayHomeAsUpEnabled(fragNavController?.isRootFragment?.not() == true)
+ supportActionBar?.setDisplayHomeAsUpEnabled(fragNavController.isRootFragment.not())
}
@@ -109,7 +115,7 @@ class BottomTabsActivity : AppCompatActivity(), BaseFragment.FragmentNavigation,
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
- android.R.id.home -> fragNavController?.popFragment()
+ android.R.id.home -> fragNavController.popFragment()
}
return true
}
diff --git a/app/src/main/java/com/ncapdevi/sample/activities/NavDrawerActivity.kt b/app/src/main/java/com/ncapdevi/sample/activities/NavDrawerActivity.kt
index a95d478b..d1fc5f4e 100644
--- a/app/src/main/java/com/ncapdevi/sample/activities/NavDrawerActivity.kt
+++ b/app/src/main/java/com/ncapdevi/sample/activities/NavDrawerActivity.kt
@@ -19,7 +19,7 @@ class NavDrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSe
//Better convention to properly name the indices what they are in your app
- private var fragNavController: FragNavController? = null
+ private var fragNavController: FragNavController = FragNavController(supportFragmentManager, R.id.container)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -51,10 +51,13 @@ class NavDrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSe
RecentsFragment.newInstance(0),
FavoritesFragment.newInstance(0))
- fragNavController = FragNavController.newBuilder(savedInstanceState, supportFragmentManager, R.id.container)
- .rootFragments(fragments)
- .defaultTransactionOptions(FragNavTransactionOptions.newBuilder().customAnimations(R.anim.slide_in_from_right, R.anim.slide_out_to_left, R.anim.slide_in_from_left, R.anim.slide_out_to_right).build())
- .build()
+ fragNavController.apply {
+ rootFragments = fragments
+ defaultTransactionOptions = FragNavTransactionOptions.newBuilder().customAnimations(R.anim.slide_in_from_right, R.anim.slide_out_to_left, R.anim.slide_in_from_left, R.anim.slide_out_to_right).build()
+ }
+
+ fragNavController.initialize(INDEX_RECENTS,savedInstanceState)
+
}
@@ -62,30 +65,30 @@ class NavDrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSe
val drawer = findViewById(R.id.drawer_layout)
when {
drawer.isDrawerOpen(GravityCompat.START) -> drawer.closeDrawer(GravityCompat.START)
- fragNavController?.isRootFragment?.not() == true -> fragNavController?.popFragment()
+ fragNavController.isRootFragment.not() -> fragNavController.popFragment()
else -> super.onBackPressed()
}
}
override fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState)
- fragNavController?.onSaveInstanceState(outState)
+ fragNavController.onSaveInstanceState(outState)
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
- R.id.bb_menu_recents -> fragNavController?.switchTab(INDEX_RECENTS)
- R.id.bb_menu_favorites -> fragNavController?.switchTab(INDEX_FAVORITES)
- R.id.bb_menu_nearby -> fragNavController?.switchTab(INDEX_NEARBY)
- R.id.bb_menu_friends -> fragNavController?.switchTab(INDEX_FRIENDS)
- R.id.bb_menu_food -> fragNavController?.switchTab(INDEX_FOOD)
- R.id.bb_menu_recents2 -> fragNavController?.switchTab(INDEX_RECENTS2)
- R.id.bb_menu_favorites2 -> fragNavController?.switchTab(INDEX_FAVORITES2)
- R.id.bb_menu_nearby2 -> fragNavController?.switchTab(INDEX_NEARBY2)
- R.id.bb_menu_friends2 -> fragNavController?.switchTab(INDEX_FRIENDS2)
- R.id.bb_menu_food2 -> fragNavController?.switchTab(INDEX_FOOD2)
- R.id.bb_menu_recents3 -> fragNavController?.switchTab(INDEX_RECENTS3)
- R.id.bb_menu_favorites3 -> fragNavController?.switchTab(INDEX_FAVORITES3)
+ R.id.bb_menu_recents -> fragNavController.switchTab(INDEX_RECENTS)
+ R.id.bb_menu_favorites -> fragNavController.switchTab(INDEX_FAVORITES)
+ R.id.bb_menu_nearby -> fragNavController.switchTab(INDEX_NEARBY)
+ R.id.bb_menu_friends -> fragNavController.switchTab(INDEX_FRIENDS)
+ R.id.bb_menu_food -> fragNavController.switchTab(INDEX_FOOD)
+ R.id.bb_menu_recents2 -> fragNavController.switchTab(INDEX_RECENTS2)
+ R.id.bb_menu_favorites2 -> fragNavController.switchTab(INDEX_FAVORITES2)
+ R.id.bb_menu_nearby2 -> fragNavController.switchTab(INDEX_NEARBY2)
+ R.id.bb_menu_friends2 -> fragNavController.switchTab(INDEX_FRIENDS2)
+ R.id.bb_menu_food2 -> fragNavController.switchTab(INDEX_FOOD2)
+ R.id.bb_menu_recents3 -> fragNavController.switchTab(INDEX_RECENTS3)
+ R.id.bb_menu_favorites3 -> fragNavController.switchTab(INDEX_FAVORITES3)
}
val drawer = findViewById(R.id.drawer_layout)
drawer.closeDrawer(GravityCompat.START)
@@ -93,6 +96,6 @@ class NavDrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSe
}
override fun pushFragment(fragment: Fragment) {
- fragNavController?.pushFragment(fragment)
+ fragNavController.pushFragment(fragment)
}
}
diff --git a/build.gradle b/build.gradle
index d91e878c..ef9eb27d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,12 +1,12 @@
buildscript {
- ext.kotlin_version = '1.2.21'
+ ext.kotlin_version = '1.2.40'
repositories {
jcenter()
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.0.1'
+ classpath 'com.android.tools.build:gradle:3.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
@@ -26,7 +26,7 @@ ext {
// App dependencies
junitVersion = '4.12'
- supportVersion = '27.0.2'
+ supportVersion = '27.1.1'
buildToolsVersion = '27.0.3'
minSdkVersion = 14
targetSdkVersion = 27
diff --git a/frag-nav/build.gradle b/frag-nav/build.gradle
index dc576fbf..ab304971 100644
--- a/frag-nav/build.gradle
+++ b/frag-nav/build.gradle
@@ -10,8 +10,8 @@ apply plugin: 'maven'
apply plugin: 'com.github.kt3k.coveralls'
ext {
- libraryVersionCode = 23
- libraryVersionName = '2.4.0'
+ libraryVersionCode = 24
+ libraryVersionName = '3.0.0-RC'
//Bintray and Maven
bintrayRepo = 'maven'
diff --git a/frag-nav/src/main/java/com/ncapdevi/fragnav/Builder.kt b/frag-nav/src/main/java/com/ncapdevi/fragnav/Builder.kt
deleted file mode 100644
index 5e093514..00000000
--- a/frag-nav/src/main/java/com/ncapdevi/fragnav/Builder.kt
+++ /dev/null
@@ -1,152 +0,0 @@
-package com.ncapdevi.fragnav
-
-import android.os.Bundle
-import android.support.v4.app.Fragment
-import android.support.v4.app.FragmentManager
-import com.ncapdevi.fragnav.tabhistory.*
-import com.ncapdevi.fragnav.tabhistory.FragNavTabHistoryController.Companion.UNIQUE_TAB_HISTORY
-import com.ncapdevi.fragnav.tabhistory.FragNavTabHistoryController.Companion.UNLIMITED_TAB_HISTORY
-
-class Builder(private val savedInstanceState: Bundle?, val fragmentManager: FragmentManager, val containerId: Int) {
- internal var rootFragmentListener: FragNavController.RootFragmentListener? = null
- internal var transactionListener: FragNavController.TransactionListener? = null
- internal var defaultTransactionOptions: FragNavTransactionOptions? = null
- internal var numberOfTabs = 0
- internal var rootFragments: List? = null
-
- @FragNavController.TabIndex
- internal var selectedTabIndex = FragNavController.TAB1
-
- @FragNavController.FragmentHideStrategy
- internal var fragmentHideStrategy = FragNavController.DETACH
-
- internal var createEager = false
-
- internal var navigationStrategy: NavigationStrategy = CurrentTabStrategy()
-
- internal var fragNavLogger: FragNavLogger? = null
-
- /**
- * @param selectedTabIndex The initial tab index to be used must be in range of rootFragments size
- */
- fun selectedTabIndex(@FragNavController.TabIndex selectedTabIndex: Int): Builder {
- this.selectedTabIndex = selectedTabIndex
- if (selectedTabIndex > numberOfTabs) {
- throw IndexOutOfBoundsException("Starting index cannot be larger than the number of stacks")
- }
- return this
- }
-
- /**
- * @param rootFragment A single root fragment. This library can still be helpful when managing a single stack of fragments
- */
- fun rootFragment(rootFragment: Fragment): Builder {
- return rootFragments(listOf(rootFragment))
- }
-
- /**
- * @param rootFragments a list of root fragments. root Fragments are the root fragments that exist on any tab structure. If only one fragment is sent in, fragnav will still manage
- * transactions
- */
- fun rootFragments(rootFragments: List): Builder {
- if (rootFragmentListener != null) {
- throw IllegalStateException("Root fragments and root fragment listener can not be set the same time")
- }
- this.rootFragments = rootFragments
- numberOfTabs = rootFragments.size
- if (numberOfTabs > FragNavController.MAX_NUM_TABS) {
- throw IllegalArgumentException("Number of root fragments cannot be greater than " + FragNavController.MAX_NUM_TABS)
- }
- return this
- }
-
- /**
- * @param transactionOptions The default transaction options to be used unless otherwise defined.
- */
- fun defaultTransactionOptions(transactionOptions: FragNavTransactionOptions): Builder {
- defaultTransactionOptions = transactionOptions
- return this
- }
-
- /**
- * @param rootFragmentListener a listener that allows for dynamically creating root fragments
- * @param numberOfTabs the number of tabs that will be switched between
- */
- fun rootFragmentListener(rootFragmentListener: FragNavController.RootFragmentListener, numberOfTabs: Int): Builder {
- if (rootFragments != null) {
- throw IllegalStateException("Root fragment listener and root fragments can not be set the same time")
- }
- this.rootFragmentListener = rootFragmentListener
- this.numberOfTabs = numberOfTabs
- if (this.numberOfTabs > FragNavController.MAX_NUM_TABS) {
- throw IllegalArgumentException("Number of tabs cannot be greater than " + FragNavController.MAX_NUM_TABS)
- }
- return this
- }
-
- /**
- * @param transactionListener A listener to be implemented (typically within the main activity) to fragment transactions (including tab switches)
- */
- fun transactionListener(transactionListener: FragNavController.TransactionListener): Builder {
- this.transactionListener = transactionListener
- return this
- }
-
- /**
- * @param popStrategy Switch between different approaches of handling tab history while popping fragments on current tab
- */
- @Deprecated(
- "UNIQUE_TAB_HISTORY and UNLIMITED_TAB_HISTORY require FragNavSwitchController",
- ReplaceWith("switchController(popStrategy, fragNavSwitchController)")
- )
- fun popStrategy(@FragNavTabHistoryController.PopStrategy popStrategy: Int): Builder {
- if (popStrategy != FragNavTabHistoryController.UNIQUE_TAB_HISTORY || popStrategy != FragNavTabHistoryController.UNLIMITED_TAB_HISTORY) {
- throw IllegalStateException("UNIQUE_TAB_HISTORY and UNLIMITED_TAB_HISTORY require FragNavSwitchController, please use `switchController` instead ")
- }
- this.navigationStrategy = CurrentTabStrategy()
- return this
- }
-
- /**
- * @param fragmentHideStrategy Switch between different approaches of hiding inactive and showing active fragments
- */
- fun fragmentHideStrategy(@FragNavController.FragmentHideStrategy fragmentHideStrategy: Int): Builder {
- this.fragmentHideStrategy = fragmentHideStrategy
- return this
- }
-
- /**
- * @param createEager Should initially create all tab's topmost fragment
- */
- fun eager(createEager: Boolean): Builder {
- this.createEager = createEager
- return this
- }
-
- /**
- * @param fragNavSwitchController Handles switch requests
- */
- fun switchController(@FragNavTabHistoryController.PopStrategy popStrategy: Int, fragNavSwitchController: FragNavSwitchController): Builder {
- this.navigationStrategy = when (popStrategy) {
- UNIQUE_TAB_HISTORY -> UniqueTabHistoryStrategy(fragNavSwitchController)
- UNLIMITED_TAB_HISTORY -> UnlimitedTabHistoryStrategy(fragNavSwitchController)
- else -> CurrentTabStrategy()
- }
- return this
- }
-
- /**
- * @param fragNavLogger Reports errors for the client
- */
- fun logger(fragNavLogger: FragNavLogger): Builder {
- this.fragNavLogger = fragNavLogger
- return this
- }
-
- fun build(): FragNavController {
- if (rootFragmentListener == null && rootFragments == null) {
- throw IndexOutOfBoundsException("Either a root fragment(s) needs to be set, or a fragment listener")
- }
- return FragNavController(this, savedInstanceState)
- }
-}
\ No newline at end of file
diff --git a/frag-nav/src/main/java/com/ncapdevi/fragnav/FragNavController.kt b/frag-nav/src/main/java/com/ncapdevi/fragnav/FragNavController.kt
index b5428b18..49da4a36 100644
--- a/frag-nav/src/main/java/com/ncapdevi/fragnav/FragNavController.kt
+++ b/frag-nav/src/main/java/com/ncapdevi/fragnav/FragNavController.kt
@@ -12,6 +12,8 @@ import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentTransaction
import com.ncapdevi.fragnav.tabhistory.*
+import com.ncapdevi.fragnav.tabhistory.FragNavTabHistoryController.Companion.UNIQUE_TAB_HISTORY
+import com.ncapdevi.fragnav.tabhistory.FragNavTabHistoryController.Companion.UNLIMITED_TAB_HISTORY
import org.json.JSONArray
import java.util.*
@@ -27,58 +29,58 @@ import java.util.*
*
* Originally Created March 2016
*/
-class FragNavController internal constructor(builder: Builder, savedInstanceState: Bundle?) {
-
- @IdRes
- private val containerId: Int = builder.containerId
- private val fragmentStacksTags: MutableList> = ArrayList(builder.numberOfTabs)
- private val rootFragments: MutableList = ArrayList(builder.numberOfTabs)
- private val fragmentManger: FragmentManager = builder.fragmentManager
- private val defaultTransactionOptions: FragNavTransactionOptions? = builder.defaultTransactionOptions
- private val navigationStrategy: NavigationStrategy = builder.navigationStrategy
- private val fragNavLogger: FragNavLogger? = builder.fragNavLogger
- private val rootFragmentListener: RootFragmentListener? = builder.rootFragmentListener
- private val transactionListener: TransactionListener? = builder.transactionListener
-
- private val fragmentHideStrategy = builder.fragmentHideStrategy
- private val createEager = builder.createEager
+class FragNavController constructor(private val fragmentManger: FragmentManager, @IdRes private val containerId: Int) {
+
+ //region Public properties
+ var rootFragments: List? = null
+ set(value) {
+ if (value != null) {
+ if (rootFragmentListener != null) {
+ throw IllegalStateException("Root fragments and root fragment listener can not be set the same time")
+ }
+
+ if (value.size > FragNavController.MAX_NUM_TABS) {
+ throw IllegalArgumentException("Number of root fragments cannot be greater than " + FragNavController.MAX_NUM_TABS)
+ }
+ }
+
+ field = value
+ }
+ var defaultTransactionOptions: FragNavTransactionOptions? = null
+ var fragNavLogger: FragNavLogger? = null
+ var rootFragmentListener: RootFragmentListener? = null
+
+ var transactionListener: TransactionListener? = null
+ var navigationStrategy: NavigationStrategy = CurrentTabStrategy()
+ set(value) {
+ field = value
+ fragNavTabHistoryController = when (value) {
+ is UniqueTabHistoryStrategy -> UniqueTabHistoryController(DefaultFragNavPopController(), value.fragNavSwitchController)
+ is UnlimitedTabHistoryStrategy -> UnlimitedTabHistoryController(DefaultFragNavPopController(), value.fragNavSwitchController)
+ else -> CurrentTabHistoryController(DefaultFragNavPopController())
+ }
+
+ }
+
+ var fragmentHideStrategy = FragNavController.DETACH
+ var createEager = false
@TabIndex
@get:CheckResult
@get:TabIndex
- var currentStackIndex: Int = builder.selectedTabIndex
+ var currentStackIndex: Int = FragNavController.TAB1
private set
+ //endregion
+
+ //region Private properties
+ private val fragmentStacksTags: MutableList> = ArrayList()
private var tagCount: Int = 0
private var mCurrentFrag: Fragment? = null
private var mCurrentDialogFrag: DialogFragment? = null
private var executingTransaction: Boolean = false
- private var fragNavTabHistoryController: FragNavTabHistoryController
-
- init {
- val fragNavPopController = DefaultFragNavPopController()
- fragNavTabHistoryController = when (navigationStrategy) {
- is UniqueTabHistoryStrategy -> UniqueTabHistoryController(fragNavPopController, navigationStrategy.fragNavSwitchController)
- is UnlimitedTabHistoryStrategy -> UnlimitedTabHistoryController(fragNavPopController, navigationStrategy.fragNavSwitchController)
- else -> CurrentTabHistoryController(fragNavPopController)
- }
-
- val initialRootFragments = builder.rootFragments
- if (initialRootFragments != null) {
- rootFragments.addAll(initialRootFragments)
- }
-
- //Attempt to restore from bundle, if not, initialize
- if (!restoreFromBundle(savedInstanceState)) {
- for (i in 0 until builder.numberOfTabs) {
- fragmentStacksTags.add(Stack())
- }
-
- initialize(currentStackIndex)
- } else {
- fragNavTabHistoryController.restoreFromBundle(savedInstanceState)
- }
- }
+ private var fragNavTabHistoryController: FragNavTabHistoryController = CurrentTabHistoryController(DefaultFragNavPopController())
+ //endregion
//region Public helper functions
@@ -167,46 +169,69 @@ class FragNavController internal constructor(builder: Builder, savedInstanceStat
*
* @param index the tab index to initialize to
*/
- fun initialize(@TabIndex index: Int) {
- currentStackIndex = index
- if (currentStackIndex > fragmentStacksTags.size) {
- throw IndexOutOfBoundsException("Starting index cannot be larger than the number of stacks")
- }
- fragNavTabHistoryController.switchTab(index)
- currentStackIndex = index
- clearFragmentManager()
- clearDialogFragment()
- if (index == NO_TAB) {
- return
+ fun initialize(@TabIndex index: Int = TAB1, savedInstanceState: Bundle? = null) {
+ if (rootFragmentListener == null && rootFragments == null) {
+ throw IndexOutOfBoundsException("Either a root fragment(s) needs to be set, or a fragment listener")
+ } else if (rootFragmentListener != null && rootFragments != null) {
+ throw java.lang.IllegalStateException("Shouldn't have both a rootFragmentListener and rootFragments set, this is clearly a mistsake")
}
- val ft = createTransactionWithOptions(defaultTransactionOptions, false)
+ val numberOfTabs: Int = rootFragmentListener?.numberOfRootFragments ?: rootFragments?.size ?: 0
- val lowerBound = if (createEager) 0 else index
- val upperBound = if (createEager) fragmentStacksTags.size else index + 1
- for (i in lowerBound until upperBound) {
- currentStackIndex = i
- val fragment = getRootFragment(i)
- val fragmentTag = generateTag(fragment)
- fragmentStacksTags[currentStackIndex].push(fragmentTag)
- ft.add(containerId, fragment, fragmentTag)
- if (i != index) {
- if (shouldDetachAttachOnSwitch()) {
- ft.detach(fragment)
+ //Attempt to restore from bundle, if not, initialize
+ if (!restoreFromBundle(savedInstanceState)) {
+ fragmentStacksTags.clear()
+ for (i in 0 until numberOfTabs) {
+ fragmentStacksTags.add(Stack())
+ }
+
+
+ currentStackIndex = index
+ if (currentStackIndex > fragmentStacksTags.size) {
+ throw IndexOutOfBoundsException("Starting index cannot be larger than the number of stacks")
+ }
+ fragNavTabHistoryController.switchTab(index)
+
+ currentStackIndex = index
+ clearFragmentManager()
+ clearDialogFragment()
+
+ if (index == NO_TAB) {
+ return
+ }
+
+ val ft = createTransactionWithOptions(defaultTransactionOptions, false)
+
+ val lowerBound = if (createEager) 0 else index
+ val upperBound = if (createEager) fragmentStacksTags.size else index + 1
+ for (i in lowerBound until upperBound) {
+ currentStackIndex = i
+ val fragment = getRootFragment(i)
+ val fragmentTag = generateTag(fragment)
+ fragmentStacksTags[currentStackIndex].push(fragmentTag)
+ ft.add(containerId, fragment, fragmentTag)
+ if (i != index) {
+ if (shouldDetachAttachOnSwitch()) {
+ ft.detach(fragment)
+ } else {
+ ft.hide(fragment)
+ }
} else {
- ft.hide(fragment)
+ mCurrentFrag = fragment
}
- } else {
- mCurrentFrag = fragment
}
+ currentStackIndex = index
+
+ commitTransaction(ft, defaultTransactionOptions)
+
+ transactionListener?.onTabTransaction(currentFrag, currentStackIndex)
+ } else {
+ fragNavTabHistoryController.restoreFromBundle(savedInstanceState)
}
- currentStackIndex = index
- commitTransaction(ft, defaultTransactionOptions)
- transactionListener?.onTabTransaction(currentFrag, currentStackIndex)
}
@@ -253,7 +278,12 @@ class FragNavController internal constructor(builder: Builder, savedInstanceStat
commitTransaction(ft, transactionOptions)
} else {
fragment = getRootFragment(currentStackIndex)
- ft.add(containerId, fragment, generateTag(fragment))
+ var tag = fragment.tag
+ if (tag.isNullOrEmpty()){
+ tag = generateTag(fragment)
+ fragmentStacksTags[currentStackIndex].push(tag)
+ }
+ ft.add(containerId, fragment, tag)
commitTransaction(ft, transactionOptions)
}
}
@@ -533,12 +563,12 @@ class FragNavController internal constructor(builder: Builder, savedInstanceStat
fragment = fragmentManger.findFragmentByTag(fragmentStacksTags[index].peek())
}
- if (fragment == null && rootFragmentListener != null) {
- fragment = rootFragmentListener.getRootFragment(index)
+ if (fragment == null) {
+ fragment = rootFragmentListener?.getRootFragment(index)
}
- if (fragment == null && index < rootFragments.size) {
- fragment = rootFragments[index]
+ if (fragment == null) {
+ fragment = rootFragments?.getOrNull(index)
}
@@ -803,24 +833,25 @@ class FragNavController internal constructor(builder: Builder, savedInstanceStat
}
//Declare the TabIndex annotation
- @IntDef(NO_TAB.toLong(), TAB1.toLong(), TAB2.toLong(), TAB3.toLong(), TAB4.toLong(), TAB5.toLong(), TAB6.toLong(), TAB7.toLong(), TAB8.toLong(), TAB9.toLong(), TAB10.toLong(), TAB11.toLong(), TAB12.toLong(), TAB13.toLong(), TAB14.toLong(), TAB15.toLong(), TAB16.toLong(), TAB17.toLong(), TAB18.toLong(), TAB19.toLong(), TAB20.toLong())
+ @IntDef(NO_TAB, TAB1, TAB2, TAB3, TAB4, TAB5, TAB6, TAB7, TAB8, TAB9, TAB10, TAB11, TAB12, TAB13, TAB14, TAB15, TAB16, TAB17, TAB18, TAB19, TAB20)
@kotlin.annotation.Retention(AnnotationRetention.SOURCE)
annotation class TabIndex
// Declare Transit Styles
- @IntDef(FragmentTransaction.TRANSIT_NONE.toLong(), FragmentTransaction.TRANSIT_FRAGMENT_OPEN.toLong(), FragmentTransaction.TRANSIT_FRAGMENT_CLOSE.toLong(), FragmentTransaction.TRANSIT_FRAGMENT_FADE.toLong())
+ @IntDef(FragmentTransaction.TRANSIT_NONE, FragmentTransaction.TRANSIT_FRAGMENT_OPEN, FragmentTransaction.TRANSIT_FRAGMENT_CLOSE, FragmentTransaction.TRANSIT_FRAGMENT_FADE)
@kotlin.annotation.Retention(AnnotationRetention.SOURCE)
internal annotation class Transit
/**
* Define what happens when we try to pop on a tab where root fragment is at the top
*/
- @IntDef(DETACH.toLong(), HIDE.toLong(), DETACH_ON_NAVIGATE_HIDE_ON_SWITCH.toLong())
+ @IntDef(DETACH, HIDE, DETACH_ON_NAVIGATE_HIDE_ON_SWITCH)
@kotlin.annotation.Retention(AnnotationRetention.SOURCE)
- internal annotation class FragmentHideStrategy
+ annotation class FragmentHideStrategy
interface RootFragmentListener {
+ val numberOfRootFragments: Int
/**
* Dynamically create the Fragment that will go on the bottom of the stack
*
@@ -876,10 +907,6 @@ class FragNavController internal constructor(builder: Builder, savedInstanceStat
private val EXTRA_CURRENT_FRAGMENT = FragNavController::class.java.name + ":EXTRA_CURRENT_FRAGMENT"
private val EXTRA_FRAGMENT_STACK = FragNavController::class.java.name + ":EXTRA_FRAGMENT_STACK"
- @JvmStatic
- fun newBuilder(savedInstanceState: Bundle?, fragmentManager: FragmentManager, containerId: Int): Builder {
- return Builder(savedInstanceState, fragmentManager, containerId)
- }
/**
* Using attach and detach methods of Fragment transaction to switch between fragments
diff --git a/frag-nav/src/main/java/com/ncapdevi/fragnav/tabhistory/FragNavTabHistoryController.kt b/frag-nav/src/main/java/com/ncapdevi/fragnav/tabhistory/FragNavTabHistoryController.kt
index 26bd2a92..7e1601d1 100644
--- a/frag-nav/src/main/java/com/ncapdevi/fragnav/tabhistory/FragNavTabHistoryController.kt
+++ b/frag-nav/src/main/java/com/ncapdevi/fragnav/tabhistory/FragNavTabHistoryController.kt
@@ -8,7 +8,7 @@ interface FragNavTabHistoryController {
/**
* Define what happens when we try to pop on a tab where root fragment is at the top
*/
- @IntDef(CURRENT_TAB.toLong(), UNIQUE_TAB_HISTORY.toLong(), UNLIMITED_TAB_HISTORY.toLong())
+ @IntDef(CURRENT_TAB, UNIQUE_TAB_HISTORY, UNLIMITED_TAB_HISTORY)
@kotlin.annotation.Retention(AnnotationRetention.SOURCE)
annotation class PopStrategy
diff --git a/frag-nav/src/test/java/com/ncapdevi/fragnav/FragNavControllerTest.kt b/frag-nav/src/test/java/com/ncapdevi/fragnav/FragNavControllerTest.kt
index 2812d7e0..6719a125 100644
--- a/frag-nav/src/test/java/com/ncapdevi/fragnav/FragNavControllerTest.kt
+++ b/frag-nav/src/test/java/com/ncapdevi/fragnav/FragNavControllerTest.kt
@@ -40,10 +40,11 @@ class FragNavControllerTest : FragNavController.TransactionListener {
rootFragments.add(Fragment())
rootFragments.add(Fragment())
- var mFragNavController = FragNavController.newBuilder(null, fragmentManager, frameLayout.id)
- .rootFragments(rootFragments)
- .selectedTabIndex(FragNavController.TAB1)
- .build()
+ val mFragNavController = FragNavController(fragmentManager, frameLayout.id).apply {
+ this.rootFragments = rootFragments
+ }
+ mFragNavController.initialize()
+
mFragNavController.switchTab(FragNavController.TAB2)
mFragNavController.pushFragment(Fragment())
@@ -56,10 +57,7 @@ class FragNavControllerTest : FragNavController.TransactionListener {
mFragNavController.onSaveInstanceState(bundle)
- mFragNavController = FragNavController.newBuilder(bundle, fragmentManager, frameLayout.id)
- .rootFragments(rootFragments)
- .selectedTabIndex(FragNavController.TAB1)
- .build()
+ mFragNavController.initialize(savedInstanceState = bundle)
Assert.assertEquals(FragNavController.TAB2.toLong(), mFragNavController.currentStackIndex.toLong())
Assert.assertEquals(3, mFragNavController.currentStack!!.size.toLong())
@@ -72,9 +70,11 @@ class FragNavControllerTest : FragNavController.TransactionListener {
rootFragments.add(Fragment())
rootFragments.add(Fragment())
- mFragNavController = FragNavController.newBuilder(null, fragmentManager, frameLayout.id)
- .rootFragments(rootFragments)
- .build()
+ mFragNavController = FragNavController(fragmentManager, frameLayout.id).apply {
+ this.rootFragments = rootFragments
+
+ }
+ mFragNavController.initialize()
Assert.assertEquals(FragNavController.TAB1.toLong(), mFragNavController.currentStackIndex.toLong())
Assert.assertNotNull(mFragNavController.currentStack)
@@ -86,11 +86,14 @@ class FragNavControllerTest : FragNavController.TransactionListener {
rootFragments.add(Fragment())
rootFragments.add(Fragment())
- mFragNavController = FragNavController.newBuilder(null, fragmentManager, frameLayout.id)
- .rootFragments(rootFragments)
- .fragmentHideStrategy(FragNavController.DETACH_ON_NAVIGATE_HIDE_ON_SWITCH)
- .eager(true)
- .build()
+ mFragNavController = FragNavController(fragmentManager, frameLayout.id).apply {
+ this.rootFragments = rootFragments
+ fragmentHideStrategy = FragNavController.DETACH_ON_NAVIGATE_HIDE_ON_SWITCH
+ createEager = true
+
+ }
+
+ mFragNavController.initialize()
Assert.assertEquals(FragNavController.TAB1.toLong(), mFragNavController.currentStackIndex.toLong())
Assert.assertNotNull(mFragNavController.currentStack)
@@ -105,9 +108,9 @@ class FragNavControllerTest : FragNavController.TransactionListener {
rootFragments.add(Fragment())
}
- mFragNavController = FragNavController.newBuilder(null, fragmentManager, frameLayout.id)
- .rootFragments(rootFragments)
- .build()
+ mFragNavController = FragNavController(fragmentManager, frameLayout.id).apply {
+ this.rootFragments = rootFragments
+ }
}
@Test
@@ -116,10 +119,12 @@ class FragNavControllerTest : FragNavController.TransactionListener {
rootFragments.add(Fragment())
rootFragments.add(Fragment())
- mFragNavController = FragNavController.newBuilder(null, fragmentManager, frameLayout.id)
- .rootFragments(rootFragments)
- .selectedTabIndex(FragNavController.NO_TAB)
- .build()
+ mFragNavController = FragNavController(fragmentManager, frameLayout.id).apply {
+ this.rootFragments = rootFragments
+ }
+
+ mFragNavController.initialize(FragNavController.NO_TAB)
+
Assert.assertEquals(FragNavController.NO_TAB.toLong(), mFragNavController.currentStackIndex.toLong())
Assert.assertNull(mFragNavController.currentStack)
@@ -129,34 +134,38 @@ class FragNavControllerTest : FragNavController.TransactionListener {
fun testConstructionWhenRootFragmentListenerAndTabSelected() {
val rootFragmentListener = mock()
doReturn(Fragment()).whenever(rootFragmentListener)
- .getRootFragment(any())
+ .getRootFragment(any())
+ doReturn(5).whenever(rootFragmentListener).numberOfRootFragments
- mFragNavController = FragNavController.newBuilder(null, fragmentManager, frameLayout.id)
- .rootFragmentListener(rootFragmentListener, 5)
- .selectedTabIndex(FragNavController.TAB3)
- .build()
+ mFragNavController = FragNavController(fragmentManager, frameLayout.id).apply {
+ this.rootFragmentListener = rootFragmentListener
+ }
+ mFragNavController.initialize(FragNavController.TAB3)
Assert.assertEquals(FragNavController.TAB3.toLong(), mFragNavController.currentStackIndex.toLong())
Assert.assertNotNull(mFragNavController.currentStack)
}
- @Test(expected = IllegalArgumentException::class)
+ @Test(expected = IndexOutOfBoundsException::class)
fun testConstructionWhenRootFragmentListenerAndTooManyTabs() {
val rootFragmentListener = mock()
- mFragNavController = FragNavController.newBuilder(null, fragmentManager, frameLayout.id)
- .rootFragmentListener(rootFragmentListener, 21)
- .selectedTabIndex(FragNavController.TAB3)
- .build()
+ mFragNavController = FragNavController(fragmentManager, frameLayout.id).apply {
+ this.rootFragmentListener = rootFragmentListener
+
+ }
+ mFragNavController.initialize(FragNavController.TAB20)
}
@Test
fun pushPopClear() {
- mFragNavController = FragNavController.newBuilder(Bundle(), fragmentManager, frameLayout.id)
- .transactionListener(this)
- .rootFragment(Fragment())
- .build()
+ mFragNavController = FragNavController(fragmentManager, frameLayout.id).apply {
+ transactionListener = this@FragNavControllerTest
+ rootFragments = listOf(Fragment())
+ }
+
+ mFragNavController.initialize()
Assert.assertEquals(FragNavController.TAB1.toLong(), mFragNavController.currentStackIndex.toLong())
Assert.assertNotNull(mFragNavController.currentStack)