Skip to content

Commit

Permalink
Merge branch 'release/2.0.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcel Vojtkovszky committed Nov 3, 2020
2 parents d4c76b6 + 58f5e60 commit 2d0e90d
Show file tree
Hide file tree
Showing 16 changed files with 333 additions and 269 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# SingleActivityNavigation
A simple single activity application framework with straightforward navigation controlls, allowing
to reuse fragments and move between them as root views, dialogs, bottom sheets, modals etc. with minimal dependencies.
<br/><br/>
<img src="example.gif" alt="Example Flow" width="320"/>

## How does it work?
Your single activity must extend from BaseSingleActivity and all your fragments extend from BaseSingleFragment.
Then you can simply move between your fragments by using public methods in your activity or fragment
Then you can simply move between your fragments by using public methods in your activity or fragment.

``` kotlin
// take any fragment of your choosing
Expand All @@ -22,7 +24,7 @@ openDialog(myFragment)
// you can simply navigate through the back stack using:
navigateBack()
navigateBackToRoot()
navigateBackToFragment("fragmentName")
navigateBackTo("fragmentName")

// define your root fragment(s). Those will be held at the bottom of stack, intended as the initial activity's fragment
override fun getNewRootFragmentInstance(positionIndex: Int): BaseSingleFragment? {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,25 @@ import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : BaseSingleActivity() {

companion object {
// positions for root fragments in bottom navigation
private const val ROOT_FRAGMENT_POS_HOME = 0
private const val ROOT_FRAGMENT_POS_DASHBOARD = 1
private const val ROOT_FRAGMENT_POS_NOTIFICATIONS = 2
}

// define main fragments based on position
override fun getNewRootFragmentInstance(positionIndex: Int): BaseSingleFragment? {
return when (positionIndex) {
0 -> MainFragment.newInstance(getString(R.string.title_home), isRoot = true)
1 -> MainFragment.newInstance(getString(R.string.title_dashboard), isRoot = true)
2 -> MainFragment.newInstance(getString(R.string.title_notifications), isRoot = true)
// we'll use same fragment for all root positions
ROOT_FRAGMENT_POS_HOME, ROOT_FRAGMENT_POS_DASHBOARD, ROOT_FRAGMENT_POS_NOTIFICATIONS ->
MainFragment()
else -> null
}
}

// define container where fragments will be held
override val fragmentContainerId: Int = R.id.fragmentContainer
// define containers where fragments will be held
override val defaultFragmentContainerId: Int = R.id.fragmentContainer

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -28,9 +35,9 @@ class MainActivity : BaseSingleActivity() {
// we'll be switching main fragments with out bottom navigation
navigationView.setOnNavigationItemSelectedListener {
when (it.itemId) {
R.id.navigation_home -> selectRootFragment(0)
R.id.navigation_dashboard -> selectRootFragment(1)
R.id.navigation_notifications -> selectRootFragment(2)
R.id.navigation_home -> selectRootFragment(ROOT_FRAGMENT_POS_HOME)
R.id.navigation_dashboard -> selectRootFragment(ROOT_FRAGMENT_POS_DASHBOARD)
R.id.navigation_notifications -> selectRootFragment(ROOT_FRAGMENT_POS_NOTIFICATIONS)
else -> return@setOnNavigationItemSelectedListener false
}
return@setOnNavigationItemSelectedListener true
Expand All @@ -46,8 +53,8 @@ class MainActivity : BaseSingleActivity() {
R.anim.enter_from_right, R.anim.exit_to_left_short,
R.anim.enter_from_left_short, R.anim.exit_to_right)

// select default fragment on tab 1
selectRootFragment()
// use home fragment as default
selectRootFragment(ROOT_FRAGMENT_POS_HOME)
}

override fun onBackStackChanged(backStackCount: Int) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.vojtkovszky.singleactivitynavigationexample

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.vojtkovszky.singleactivitynavigation.BaseSingleFragment
import com.vojtkovszky.singleactivitynavigation.FragmentType
import kotlinx.android.synthetic.main.fragment_main.*

class MainFragment : BaseSingleFragment() {

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_main, container, false)
}

override fun onResume() {
super.onResume()

// Set title. Determine type of current fragment with fragmentType parameter
val title = getString(when(fragmentType) {
FragmentType.BOTTOM_SHEET -> R.string.type_bottom_sheet
FragmentType.DIALOG -> R.string.type_dialog
FragmentType.ROOT -> R.string.type_root
FragmentType.MODAL -> R.string.type_modal
FragmentType.DEFAULT -> R.string.type_regular
FragmentType.INVALID -> 0
})

// use it to set status text
textStatus.text = getString(R.string.this_is_type_fragment, title)
// and change title, but not needed in dialog
if (!fragmentType.isDialogOrBottomSheet()) {
baseSingleActivity?.supportActionBar?.title = title
}

// click listeners on buttons
buttonOpenRegular.let {
it.text = getString(R.string.open_type_fragment, getString(R.string.type_regular))
it.setOnClickListener { navigateTo(MainFragment()) }
}
buttonOpenModal.let {
it.text = getString(R.string.open_type_fragment, getString(R.string.type_modal))
it.setOnClickListener { navigateTo(MainFragment(), openAsModal = true) }
}
buttonOpenBottomSheet.let {
it.text = getString(R.string.open_type_fragment, getString(R.string.type_bottom_sheet))
it.setOnClickListener { openBottomSheet(MainFragment()) }
}
buttonOpenDialog.let {
it.text = getString(R.string.open_type_fragment, getString(R.string.type_dialog))
it.setOnClickListener { openDialog(MainFragment())}
}
buttonBackToRoot.let {
it.text = getString(R.string.back_to_root)
it.setOnClickListener { navigateBackToRoot() }
}
}
}
22 changes: 0 additions & 22 deletions app/src/main/res/layout/fragment_dashboard.xml

This file was deleted.

22 changes: 0 additions & 22 deletions app/src/main/res/layout/fragment_home.xml

This file was deleted.

14 changes: 5 additions & 9 deletions app/src/main/res/layout/fragment_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,31 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/open_new_regular_fragment"/>

tools:text="@string/open_type_fragment"/>
<Button
android:id="@+id/buttonOpenModal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/open_new_modal_fragment"/>

tools:text="@string/open_type_fragment"/>
<Button
android:id="@+id/buttonOpenBottomSheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/open_bottom_sheet"/>

tools:text="@string/open_type_fragment"/>
<Button
android:id="@+id/buttonOpenDialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
android:text="@string/open_dialog"/>
tools:text="@string/open_type_fragment"/>

<Button
android:id="@+id/buttonBackToRoot"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/back_to_root"/>

tools:text="@string/back_to_root"/>
</LinearLayout>

</ScrollView>
22 changes: 0 additions & 22 deletions app/src/main/res/layout/fragment_notifications.xml

This file was deleted.

14 changes: 9 additions & 5 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
<string name="title_home">Home</string>
<string name="title_dashboard">Dashboard</string>
<string name="title_notifications">Notifications</string>
<string name="open_new_modal_fragment">Open Modal Fragment</string>
<string name="open_new_regular_fragment">Open Regular Fragment</string>
<string name="open_bottom_sheet">Open Bottom Sheet Fragment</string>
<string name="open_dialog">Open Dialog Fragment</string>
<string name="back_to_root">Go Back To Root</string>

<string name="type_root">Root</string>
<string name="type_regular">Regular</string>
<string name="type_modal">Modal</string>
<string name="type_bottom_sheet">Bottom Sheet</string>
<string name="type_dialog">Dialog</string>
<string name="back_to_root">Back To Root</string>
<string name="open_type_fragment">Open %s Fragment</string>
<string name="this_is_type_fragment">This is %s Fragment</string>
</resources>
Binary file modified example.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 24 additions & 1 deletion singleactivitynavigation/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,20 @@ android {
minSdkVersion 17
targetSdkVersion 30
versionCode 1
versionName "1.0.0"
versionName "2.0.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}

buildTypes {
release {
minifyEnabled false
}
}
}

dependencies {
Expand Down Expand Up @@ -78,4 +84,21 @@ static def addDependency(dependencyNode, dependency, scope) {
dependencyNode.appendNode('artifactId', dependency.name)
dependencyNode.appendNode('version', dependency.version)
dependencyNode.appendNode('scope', scope)
}

task javadoc(type: Javadoc) {
failOnError false
source = android.sourceSets.main.java.sourceFiles
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile
}

// build a jar with javadoc
task javadocJar(type: Jar, dependsOn: javadoc) {
archiveClassifier = 'javadoc'
from javadoc.destinationDir
}

artifacts {
archives javadocJar
}
Loading

0 comments on commit 2d0e90d

Please sign in to comment.