From e682efb079443eb2debd0bd4a0708114dd9baaf9 Mon Sep 17 00:00:00 2001 From: Nitin Dasari Date: Fri, 2 Nov 2018 10:48:00 -0700 Subject: [PATCH 01/13] cleared tab stack from different tab --- .idea/compiler.xml | 22 ------ .idea/copyright/profiles_settings.xml | 3 - .idea/encodings.xml | 6 -- .idea/misc.xml | 15 ++-- .idea/modules.xml | 2 +- .idea/vcs.xml | 2 +- build.gradle | 8 +-- frag-nav/build.gradle | 12 ++-- .../com/ncapdevi/fragnav/FragNavController.kt | 68 +++++++++++++++---- .../ncapdevi/fragnav/FragNavControllerTest.kt | 29 ++++++++ 10 files changed, 105 insertions(+), 62 deletions(-) delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/copyright/profiles_settings.xml delete mode 100644 .idea/encodings.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 96cc43ef..00000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf33..00000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba4..00000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 635999df..e0d5b93f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,26 +5,31 @@ - + diff --git a/.idea/modules.xml b/.idea/modules.xml index f4f9eb19..b833761f 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,9 +2,9 @@ + - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7f..35eb1ddf 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 59850f27..b176639c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.2.50' + ext.kotlin_version = '1.3.0' repositories { jcenter() google() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' + classpath 'com.android.tools.build:gradle:3.2.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "de.mannodermaus.gradle.plugins:android-junit5:1.0.32" } @@ -33,8 +33,8 @@ ext { // App dependencies junitVersion = '4.12' - supportVersion = '27.1.1' - buildToolsVersion = '28.0.0' + supportVersion = '28.0.0' + buildToolsVersion = '28.0.3' minSdkVersion = 14 targetSdkVersion = 28 compileSdkVersion = 28 diff --git a/frag-nav/build.gradle b/frag-nav/build.gradle index b208a035..7aa0aea3 100644 --- a/frag-nav/build.gradle +++ b/frag-nav/build.gradle @@ -41,7 +41,7 @@ android { compileSdkVersion rootProject.ext.compileSdkVersion buildToolsVersion rootProject.ext.buildToolsVersion - lintOptions{ + lintOptions { abortOnError false } defaultConfig { @@ -87,19 +87,19 @@ dependencies { implementation "com.android.support:support-annotations:$rootProject.ext.supportVersion" testImplementation "junit:junit:$rootProject.ext.junitVersion" - testImplementation "org.mockito:mockito-core:2.19.0" + testImplementation "org.mockito:mockito-core:2.23.0" testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.0.0-alpha04" - testImplementation "org.robolectric:robolectric:3.8" + testImplementation "org.robolectric:robolectric:4.0.1" testImplementation 'org.amshove.kluent:kluent-android:1.38' // Spek testImplementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" - testImplementation ('org.jetbrains.spek:spek-api:1.1.5') { + testImplementation('org.jetbrains.spek:spek-api:1.1.5') { exclude group: 'org.jetbrains.kotlin' } - testImplementation ('org.jetbrains.spek:spek-junit-platform-engine:1.1.5') { + testImplementation('org.jetbrains.spek:spek-junit-platform-engine:1.1.5') { exclude group: 'org.junit.platform' exclude group: 'org.jetbrains.kotlin' } @@ -175,7 +175,7 @@ if (project.hasProperty("android")) { // Android libraries }*/ artifacts { - // archives javadocJar + // archives javadocJar archives sourcesJar } 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 cbabfb99..988b494a 100644 --- a/frag-nav/src/main/java/com/ncapdevi/fragnav/FragNavController.kt +++ b/frag-nav/src/main/java/com/ncapdevi/fragnav/FragNavController.kt @@ -121,7 +121,7 @@ class FragNavController constructor(private val fragmentManger: FragmentManager, } else { //Else try to find one in the FragmentManager val fragmentManager: FragmentManager = getFragmentManagerForDialog() - mCurrentDialogFrag = fragmentManager.fragments?.firstOrNull { it is DialogFragment } as DialogFragment? + mCurrentDialogFrag = fragmentManager.fragments.firstOrNull { it is DialogFragment } as DialogFragment? } return mCurrentDialogFrag } @@ -408,6 +408,42 @@ class FragNavController constructor(private val fragmentManger: FragmentManager, } } + /** + * Clears the passed tab's stack to get to just the bottom Fragment. This will reveal the root fragment + * + * @param tabIndex Index of tab that needs to be cleared + * @param transactionOptions Transaction options to be displayed + */ + @JvmOverloads + fun clearTabStack(tabIndex: Int, transactionOptions: FragNavTransactionOptions? = defaultTransactionOptions) { + if (tabIndex == NO_TAB) { + return + } + + //Grab Current stack + val fragmentStack = fragmentStacksTags[tabIndex] + + // Only need to start popping and reattach if the stack is greater than 1 + if (fragmentStack.size > 1) { + val ft = createTransactionWithOptions(transactionOptions) + + //Pop all of the fragments on the stack and remove them from the FragmentManager + while (fragmentStack.size > 1) { + val fragment = getFragment(fragmentStack.pop()) + if (fragment != null) { + ft.removeSafe(fragment) + } + } + + // Attempt to reattach previous fragment + val fragment = addPreviousFragment(ft, shouldDetachAttachOnPushPop()) + + commitTransaction(ft, transactionOptions) + mCurrentFrag = fragment + transactionListener?.onFragmentTransaction(currentFrag, TransactionType.POP) + } + } + /** * Replace the current fragment * @@ -451,7 +487,7 @@ class FragNavController constructor(private val fragmentManger: FragmentManager, } else { val currentFrag = this.currentFrag val fragmentManager: FragmentManager = getFragmentManagerForDialog() - fragmentManager.fragments?.forEach { + fragmentManager.fragments.forEach { if (it is DialogFragment) { it.dismiss() } @@ -637,10 +673,10 @@ class FragNavController constructor(private val fragmentManger: FragmentManager, return fragmentManger.beginTransaction().apply { transactionOptions?.also { options -> setCustomAnimations( - options.enterAnimation, - options.exitAnimation, - options.popEnterAnimation, - options.popExitAnimation + options.enterAnimation, + options.exitAnimation, + options.popEnterAnimation, + options.popExitAnimation ) setTransitionStyle(options.transitionStyle) @@ -648,10 +684,14 @@ class FragNavController constructor(private val fragmentManger: FragmentManager, setTransition(options.transition) options.sharedElements.forEach { sharedElement -> - addSharedElement( - sharedElement.first, - sharedElement.second - ) + sharedElement.first?.let { + sharedElement.second?.let { it1 -> + addSharedElement( + it, + it1 + ) + } + } } when { @@ -720,7 +760,7 @@ class FragNavController constructor(private val fragmentManger: FragmentManager, fun getFragmentManagerForDialog(): FragmentManager { val currentFrag = this.currentFrag - return if(currentFrag?.isAdded == true) { + return if (currentFrag?.isAdded == true) { currentFrag.childFragmentManager } else { this.fragmentManger @@ -797,9 +837,9 @@ class FragNavController constructor(private val fragmentManger: FragmentManager, val stackArray = stackArrays.getJSONArray(x) val stack = Stack() (0 until stackArray.length()) - .map { stackArray.getString(it) } - .filter { !it.isNullOrEmpty() && !"null".equals(it, ignoreCase = true) } - .mapNotNullTo(stack) { it } + .map { stackArray.getString(it) } + .filter { !it.isNullOrEmpty() && !"null".equals(it, ignoreCase = true) } + .mapNotNullTo(stack) { it } fragmentStacksTags.add(stack) } 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 6719a125..23d629a5 100644 --- a/frag-nav/src/test/java/com/ncapdevi/fragnav/FragNavControllerTest.kt +++ b/frag-nav/src/test/java/com/ncapdevi/fragnav/FragNavControllerTest.kt @@ -190,6 +190,35 @@ class FragNavControllerTest : FragNavController.TransactionListener { Assert.assertTrue(mFragNavController.isRootFragment) } + @Test + fun testTabStackClear() { + val rootFragments = ArrayList() + rootFragments.add(Fragment()) + rootFragments.add(Fragment()) + + val mFragNavController = FragNavController(fragmentManager, frameLayout.id).apply { + this.rootFragments = rootFragments + } + mFragNavController.initialize() + + Assert.assertEquals(FragNavController.TAB1.toLong(), mFragNavController.currentStackIndex.toLong()) + Assert.assertNotNull(mFragNavController.currentStack) + + var size = mFragNavController.currentStack?.size ?: 1 + + mFragNavController.pushFragment(Fragment()) + Assert.assertTrue(mFragNavController.currentStack?.size == ++size) + + mFragNavController.pushFragment(Fragment()) + Assert.assertTrue(mFragNavController.currentStack?.size == ++size) + + mFragNavController.switchTab(FragNavController.TAB2) + + mFragNavController.clearTabStack(FragNavController.TAB1) + + mFragNavController.switchTab(FragNavController.TAB1) + Assert.assertTrue(mFragNavController.currentStack?.size == 1) + } override fun onTabTransaction(fragment: Fragment?, index: Int) { Assert.assertNotNull(fragment) From 20561b8e6e9aa5e8edf2ba65b6ae04a94cef3429 Mon Sep 17 00:00:00 2001 From: Mate Herber Date: Thu, 22 Nov 2018 23:18:00 +0100 Subject: [PATCH 02/13] Fixed popping animations When implementing 3.0 I've made the mistake of using the built in pop animation support for fragment transactions but our pops are not really pops as fragment manager usually interpret it. Hence I've reverted the change. * Introduced androidX and fixed issues * Updated library dependencies * Fixed failing test case * Migrated to Spek 2 * Fixed popping animations * Fixed Animation weirdness with eager initialization [176] --- app/build.gradle | 6 +- .../sample/activities/BottomTabsActivity.kt | 7 +- .../sample/activities/MainActivity.kt | 2 +- .../sample/activities/NavDrawerActivity.kt | 14 +- .../ncapdevi/sample/fragments/BaseFragment.kt | 2 +- .../main/res/layout/activity_nav_drawer.xml | 6 +- .../main/res/layout/app_bar_nav_drawer.xml | 10 +- app/src/main/res/values/styles.xml | 7 +- build.gradle | 7 +- frag-nav/build.gradle | 39 ++--- .../com/ncapdevi/fragnav/FragNavController.kt | 62 ++++---- .../fragnav/FragNavTransactionOptions.kt | 7 +- .../tabhistory/FragNavTabHistoryController.kt | 2 +- .../FragNavControllerRaceConditionSpec.kt | 141 +++++++++--------- .../ncapdevi/fragnav/FragNavControllerTest.kt | 6 +- .../fragnav/FragNavTransactionOptionsTest.kt | 12 +- gradle.properties | 4 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 18 files changed, 164 insertions(+), 172 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 566a4501..be459cb3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -27,10 +27,8 @@ repositories { dependencies { implementation project(':frag-nav') - // implementation 'com.ncapdevi:frag-nav:2.2.1' - implementation project(':frag-nav') - implementation "com.android.support:design:$rootProject.ext.supportVersion" - implementation "com.android.support:appcompat-v7:$rootProject.ext.supportVersion" + implementation "com.google.android.material:material:$rootProject.ext.supportVersion" + implementation "androidx.appcompat:appcompat:1.0.2" implementation "com.roughike:bottom-bar:2.3.1" testImplementation "junit:junit:$rootProject.ext.junitVersion" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 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 41f2acd8..667211d0 100644 --- a/app/src/main/java/com/ncapdevi/sample/activities/BottomTabsActivity.kt +++ b/app/src/main/java/com/ncapdevi/sample/activities/BottomTabsActivity.kt @@ -1,8 +1,8 @@ package com.ncapdevi.sample.activities import android.os.Bundle -import android.support.v4.app.Fragment -import android.support.v7.app.AppCompatActivity +import androidx.fragment.app.Fragment +import androidx.appcompat.app.AppCompatActivity import android.util.Log import android.view.MenuItem import com.ncapdevi.fragnav.FragNavController @@ -23,7 +23,7 @@ class BottomTabsActivity : AppCompatActivity(), BaseFragment.FragmentNavigation, override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(com.ncapdevi.sample.R.layout.activity_bottom_tabs) + setContentView(R.layout.activity_bottom_tabs) bottomBar = findViewById(R.id.bottomBar) @@ -37,6 +37,7 @@ class BottomTabsActivity : AppCompatActivity(), BaseFragment.FragmentNavigation, } } + 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() fragmentHideStrategy = FragNavController.DETACH_ON_NAVIGATE_HIDE_ON_SWITCH navigationStrategy = UniqueTabHistoryStrategy(object : FragNavSwitchController { diff --git a/app/src/main/java/com/ncapdevi/sample/activities/MainActivity.kt b/app/src/main/java/com/ncapdevi/sample/activities/MainActivity.kt index 9c1d1313..97c61e9a 100644 --- a/app/src/main/java/com/ncapdevi/sample/activities/MainActivity.kt +++ b/app/src/main/java/com/ncapdevi/sample/activities/MainActivity.kt @@ -2,7 +2,7 @@ package com.ncapdevi.sample.activities import android.content.Intent import android.os.Bundle -import android.support.v7.app.AppCompatActivity +import androidx.appcompat.app.AppCompatActivity import android.view.View import android.widget.Button import com.ncapdevi.fragnav.FragNavController 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 d1fc5f4e..ea8ed4a9 100644 --- a/app/src/main/java/com/ncapdevi/sample/activities/NavDrawerActivity.kt +++ b/app/src/main/java/com/ncapdevi/sample/activities/NavDrawerActivity.kt @@ -1,13 +1,13 @@ package com.ncapdevi.sample.activities import android.os.Bundle -import android.support.design.widget.NavigationView -import android.support.v4.app.Fragment -import android.support.v4.view.GravityCompat -import android.support.v4.widget.DrawerLayout -import android.support.v7.app.ActionBarDrawerToggle -import android.support.v7.app.AppCompatActivity -import android.support.v7.widget.Toolbar +import com.google.android.material.navigation.NavigationView +import androidx.fragment.app.Fragment +import androidx.core.view.GravityCompat +import androidx.drawerlayout.widget.DrawerLayout +import androidx.appcompat.app.ActionBarDrawerToggle +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.Toolbar import android.view.MenuItem import com.ncapdevi.fragnav.FragNavController import com.ncapdevi.fragnav.FragNavTransactionOptions diff --git a/app/src/main/java/com/ncapdevi/sample/fragments/BaseFragment.kt b/app/src/main/java/com/ncapdevi/sample/fragments/BaseFragment.kt index 3b688c33..2c72f25b 100644 --- a/app/src/main/java/com/ncapdevi/sample/fragments/BaseFragment.kt +++ b/app/src/main/java/com/ncapdevi/sample/fragments/BaseFragment.kt @@ -2,7 +2,7 @@ package com.ncapdevi.sample.fragments import android.content.Context import android.os.Bundle -import android.support.v4.app.Fragment +import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup diff --git a/app/src/main/res/layout/activity_nav_drawer.xml b/app/src/main/res/layout/activity_nav_drawer.xml index aa2aafa3..dcc39eaf 100644 --- a/app/src/main/res/layout/activity_nav_drawer.xml +++ b/app/src/main/res/layout/activity_nav_drawer.xml @@ -1,5 +1,5 @@ - - - + diff --git a/app/src/main/res/layout/app_bar_nav_drawer.xml b/app/src/main/res/layout/app_bar_nav_drawer.xml index f8ee6e46..334a0e3a 100644 --- a/app/src/main/res/layout/app_bar_nav_drawer.xml +++ b/app/src/main/res/layout/app_bar_nav_drawer.xml @@ -1,5 +1,5 @@ - - - - + @@ -29,4 +29,4 @@ android:id="@+id/container"/> - + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 16dbab30..2c393430 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,7 +1,7 @@ - -