Comments (9)
An Activity
's onBackPressed()
normally finishes the Activity.
The AcornActivity
overrides Activity.onBackPressed()
to prevent the Activity from closing and allowing the Navigator
to handle back press events, using the OnBackPressListener
.
If the Navigator returns true
in its onBackPressed()
function, it is assumed the Navigator successfully handled the event and no further action is necessary. If it returns false
, it is assumed the Navigator could not handle the back press, and the Activity's own onBackPressed()
function is called, finishing the Activity:
Thus, in short, returning true
from the root Navigator's onBackPressed()
will not finish the Activity, returning false
will finish it.
from acorn.
Giving it a thought, #144 introduced routing the back press to the currently active ViewController. If your ViewController implements the OnBackPressedListener interface, you have the control to intercept the event there.
I would probably handle such a requirement here, since you might want to show a notification to the user on the first back press. This will result in a similar setup as if you were to add a button to exit the app:
interface MyContainer {
fun setOnBackPressListener(f: () -> Unit)
}
class MyViewController(...) : ViewController, MyContainer, OnBackPressedListener {
private var onBackPressedListener: (() -> Unit)? = null
override fun setOnBackPressListener(f: () -> Unit) {
onBackPressedListener = f
}
private var backPressCount = 0
override fun onBackPressed() : Boolean {
backPressCount++
if(backPressCount < 2) {
// Return true here to 'claim' the back press event and prevent the Activity from being finished
return true
}
onBackPressedListener?.invoke()
// Always return true here, we're manually handling the back event now.
return true
}
}
class MyScene(
private val listener: Events
): Scene<MyContainer> {
override fun attach(c: MyContainer) {
c.setOnBackPressListener { listener.onBackPressed() }
}
interface Events {
fun onBackPressed()
}
}
Then call finish()
in the Navigator when you implement the MyScene.Events
interface. Something like this should work, I've typed this out without the compiler 🙃
from acorn.
Thus, in short, returning true from the root Navigator's onBackPressed() will not finish the Activity, returning false will finish it.
You can see that my simplified version of fun onBackPressed(): Boolean
from a CompositeStackNavigator
always return true but the activity will be normally finished
from acorn.
That is because you're invoking super.onBackPressed()
, which will result in an empty stack in the CompositeStackNavigator
, finishing the Activity because of that (Navigator.Events.finished()
will be invoked).
from acorn.
I got it, is there a way to avoid it happening without rewriting the entire navigator implementation?
from acorn.
I've edited my comment above with a sample, does that help?
from acorn.
An easier sample without the manual routing through the Scene (which might work well enough as well):
interface MyContainer : Container
class MyViewController(...) : ViewController, MyContainer, OnBackPressedListener {
private var backPressCount = 0
override fun onBackPressed() : Boolean {
backPressCount++
if(backPressCount < 2) {
// Return true here to 'claim' the back press event and prevent the Activity from being finished
return true
}
// Return false here, allowing the Navigator to handle the back press.
return false
}
}
from acorn.
An easier sample without the manual routing through the Scene (which might work well enough as well)
The scene could be present many times in the stack, and the back twice behavior should happen only when that scene is the last one.
Anyway I really apprecciate your work, using Acorn is a pleasure (far better than fragments). I love how you have separate the responsabilities of ui, data managment and navigation into several components but I think that Navigators are the least flexible components. This kind of issue proves it. I have to rewrite their implementation for every minimal behavior change
from acorn.
Here is my solution. I hope this could be helpful
class Navigator : Navigator.Events {
// true by default
var isRootSceneActive = true
var onLastBackPressListener: (() -> Boolean)? = null
// this listener is added to every child navigator
override fun scene(scene: Scene<out Container>, data: TransitionData?) {
isRootSceneActive = **some black magic based on the current scene**
}
override fun onBackPressed(): Boolean {
if (!isRootSceneActive || onLastBackPressListener?.invoke() == false)
return super.onBackPressed()
else
return true
}
}
class Activity {
override fun onCreate(savedInstanceState: Bundle?) {
navigator().onLastBackPressListener = { **back press twice logic** }
}
override fun onDestroy() {
// don't leak activity
navigator().onLastBackPressListener = null
}
}
from acorn.
Related Issues (20)
- Compile time issue HOT 9
- Reconsider Kotlin Android Extensions usage
- CircleCI builds fail due to memory issues
- BindingSceneTransitionFactory wrongly falls back to defaults
- Don't remove view on push HOT 14
- API 21 requirement? HOT 3
- Using Dagger to constructor inject Scenes that also receive saved state HOT 4
- Activity theme not applied into child views HOT 13
- No way to know if Transitions to same Scene class is backwards HOT 3
- Arrow Dependency in acorn-ext module HOT 1
- Lint check for providing savedstate without implementing SavableX
- Integration with unidirectional/mvi architecture HOT 5
- Gradle dependency issue in java module HOT 4
- ViewController reacts to the scene transition ends
- [BUG] Strange scene lifecycle using an ActivityController HOT 7
- Abstraction of AcornActivities to handle Jetpack Compose HOT 1
- Intercepts the controller view when it's immediately added to the root ViewGroup HOT 1
- Root navigator is not destroyed
- Use of mutation testing in acorn - Help needed HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from acorn.