https://kotlinlang.org logo
Channels
100daysofcode
100daysofkotlin
100daysofkotlin-2021
advent-of-code
aem
ai
alexa
algeria
algolialibraries
amsterdam
android
android-architecture
android-databinding
android-studio
androidgithubprojects
androidthings
androidx
androidx-xprocessing
anime
anko
announcements
apollo-kotlin
appintro
arabic
argentina
arkenv
arksemdevteam
armenia
arrow
arrow-contributors
arrow-meta
ass
atlanta
atm17
atrium
austin
australia
austria
awesome-kotlin
ballast
bangladesh
barcelona
bayarea
bazel
beepiz-libraries
belgium
benchmarks
berlin
big-data
books
boston
brazil
brikk
budapest
build
build-tools
bulgaria
bydgoszcz
cambodia
canada
carrat
carrat-dev
carrat-feed
chicago
chile
china
chucker
cincinnati-user-group
cli
clikt
cloudfoundry
cn
cobalt
code-coverage
codeforces
codemash-precompiler
codereview
codingame
codingconventions
coimbatore
collaborations
colombia
colorado
communities
competitive-programming
competitivecoding
compiler
compose
compose-android
compose-desktop
compose-hiring
compose-ios
compose-mp
compose-ui-showcase
compose-wear
compose-web
confetti
connect-audit-events
corda
cork
coroutines
couchbase
coursera
croatia
cryptography
cscenter-course-2016
cucumber-bdd
cyprus
czech
dagger
data2viz
databinding
datascience
dckotlin
debugging
decompose
decouple
denmark
deprecated
detekt
detekt-hint
dev-core
dfw
docs-revamped
dokka
domain-driven-design
doodle
dsl
dublin
dutch
eap
eclipse
ecuador
edinburgh
education
effective-kotlin
effectivekotlin
emacs
embedded-kotlin
estatik
event21-community-content
events
exposed
failgood
fb-internal-demo
feed
firebase
flow
fluid-libraries
forkhandles
forum
fosdem
fp-in-kotlin
framework-elide
freenode
french
fritz2
fuchsia
functional
funktionale
gamedev
ge-kotlin
general-advice
georgia
geospatial
german-lang
getting-started
github-workflows-kt
glance
godot-kotlin
google-io
gradle
graphic
graphkool
graphql
graphql-kotlin
graviton-browser
greece
grpc
gsoc
gui
hackathons
hacktoberfest
hamburg
hamkrest
helios
helsinki
hexagon
hibernate
hikari-cp
hire-me
hiring
hongkong
hoplite
http4k
hungary
hyderabad
image-processing
india
indonesia
inkremental
intellij
intellij-plugins
intellij-tricks
internships
introduce-yourself
io
ios
iran
israel
istanbulcoders
italian
jackson-kotlin
jadx
japanese
jasync-sql
java-to-kotlin-refactoring
javadevelopers
javafx
javalin
javascript
jdbi
jhipster-kotlin
jobsworldwide
jpa
jshdq
juul-libraries
jvm-ir-backend-feedback
jxadapter
k2-early-adopters
kaal
kafka
kakao
kalasim
kapt
karachi
karg
karlsruhe
kash_shell
kaskade
kbuild
kdbc
kgen-doc-tools
kgraphql
kinta
klaxon
klock
kloudformation
kmdc
kmm-español
kmongo
knbt
knote
koalaql
koans
kobalt
kobweb
kodein
kodex
kohesive
koin
koin-dev
komapper
kondor-json
kong
kontent
kontributors
korau
korean
korge
korim
korio
korlibs
korte
kotest
kotest-contributors
kotless
kotlick
kotlin-asia
kotlin-beam
kotlin-by-example
kotlin-csv
kotlin-data-storage
kotlin-foundation
kotlin-fuel
kotlin-in-action
kotlin-inject
kotlin-latam
kotlin-logging
kotlin-multiplatform-contest
kotlin-mumbai
kotlin-native
kotlin-pakistan
kotlin-plugin
kotlin-pune
kotlin-roadmap
kotlin-samples
kotlin-sap
kotlin-serbia
kotlin-spark
kotlin-szeged
kotlin-website
kotlinacademy
kotlinbot
kotlinconf
kotlindl
kotlinforbeginners
kotlingforbeginners
kotlinlondon
kotlinmad
kotlinprogrammers
kotlinsu
kotlintest
kotlintest-devs
kotlintlv
kotlinultimatechallenge
kotlinx-datetime
kotlinx-files
kotlinx-html
kotrix
kotson
kovenant
kprompt
kraph
krawler
kroto-plus
ksp
ktcc
ktfmt
ktlint
ktor
ktp
kubed
kug-leads
kug-torino
kvision
kweb
lambdaworld_cadiz
lanark
language-evolution
language-proposals
latvia
leakcanary
leedskotlinusergroup
lets-have-fun
libgdx
libkgd
library-development
lincheck
linkeddata
lithuania
london
losangeles
lottie
love
lychee
macedonia
machinelearningbawas
madrid
malaysia
mathematics
meetkotlin
memes
meta
metro-detroit
mexico
miami
micronaut
minnesota
minutest
mirror
mockk
moko
moldova
monsterpuzzle
montreal
moonbean
morocco
motionlayout
mpapt
mu
multiplatform
mumbai
munich
mvikotlin
mvrx
myndocs-oauth2-server
naming
navigation-architecture-component
nepal
new-mexico
new-zealand
newname
nigeria
nodejs
norway
npm-publish
nyc
oceania
ohio-kotlin-users
oldenburg
oolong
opensource
orbit-mvi
osgi
otpisani
package-search
pakistan
panamá
pattern-matching
pbandk
pdx
peru
philippines
phoenix
pinoy
pocketgitclient
polish
popkorn
portugal
practical-functional-programming
proguard
prozis-android-backup
pyhsikal
python
python-contributors
quasar
random
re
react
reaktive
realm
realworldkotlin
reductor
reduks
redux
redux-kotlin
refactoring-to-kotlin
reflect
refreshversions
reports
result
rethink
revolver
rhein-main
rocksdb
romania
room
rpi-pico
rsocket
russian
russian_feed
russian-kotlinasfirst
rx
rxjava
san-diego
science
scotland
scrcast
scrimage
script
scripting
seattle
serialization
server
sg-user-group
singapore
skia-wasm-interop-temp
skrape-it
slovak
snake
sofl-user-group
southafrica
spacemacs
spain
spanish
speaking
spek
spin
splitties
spotify-mobius
spring
spring-security
squarelibraries
stackoverflow
stacks
stayhungrystayfoolish
stdlib
stlouis
strife-discord-lib
strikt
students
stuttgart
sudan
swagger-gradle-codegen
swarm
sweden
swing
swiss-user-group
switzerland
talking-kotlin
tallinn
tampa
teamcity
tegal
tempe
tensorflow
terminal
test
testing
testtestest
texas
tgbotapi
thailand
tornadofx
touchlab-tools
training
tricity-kotlin-user-group
trójmiasto
truth
tunisia
turkey
turkiye
twitter-feed
uae
udacityindia
uk
ukrainian
uniflow
unkonf
uruguay
utah
uuid
vancouver
vankotlin
vertx
videos
vienna
vietnam
vim
vkug
vuejs
web-mpp
webassembly
webrtc
wimix_sentry
wwdc
zircon
Powered by
Title
m

Marcin Wisniowski

03/27/2023, 8:48 PM
I have implemented a bottom nav bar same as in the docs: https://developer.android.com/jetpack/compose/navigation#bottom-nav It's at the root of the app, and I would expect a back press to close the app, and it does when at the start destination. But at another screen, it navigates to the start screen instead of going out of the app. I would expect going to another screen to clear the backstack so the new screen is at the root of the backstack, but that doesn't happen. Is there something I am missing? I would expect
popUpTo
with
include = true
to result in the behavior I want, but it does not.
Solved: I needed to use
popUpTo(0)
, which doesn't seem documented anywhere.
s

Stylianos Gakis

03/27/2023, 10:29 PM
The doc for popUpTo seem to say
Pop up to a given destination before navigating. This pops all non-matching destinations from the back stack until this destination is found.
So I guess it will try to pop everything since none of your destinations will have an ID of 0? But with that said, I don’t think what you explain is how navigation works with this library, it always expects you to have a fixed startDestination, so going back should always lead to there before it leads to exiting the app. When you say “would expect going to another screen to clear the backstack so the new screen is at the root of the backstack” do you mean that you’d expect this to happen by default? Might be interesting to give this https://developer.android.com/guide/navigation/navigation-principles#fixed_start_destination a read to see what I mean by that
m

Marcin Wisniowski

03/28/2023, 12:53 AM
When you say “would expect going to another screen to clear the backstack so the new screen is at the root of the backstack” do you mean that you’d expect this to happen by default?
Not by default, but when I use popUpTo(startDestination) with
inclusive = true
.
it always expects you to have a fixed startDestination, so going back should always lead to there before it leads to exiting the app.
That's a fair default, but if the app contains 3 screens switchable with a bottom navbar, then none of the screens is more "root" than the other. Screen A is the start destination, but pressing back at screen B shouldn't switch you to screen A. Switching screens with a bottom navbar should not populate the backstack.
i

Ian Lake

03/28/2023, 3:11 AM
Nope. The screen you start the user on should be the screen they exit the app from. This has been confirmed through multiple UX studies we've ran (which is where those Principles came from) - accidentally leaving the app is a huge net negative for users
s

Stylianos Gakis

03/28/2023, 9:35 AM
What do these studies say regarding apps that have distinct logged in and logged out situations that do not have a start destination which works for both logged in and logged out users? If you follow the steps from

this video

you end up with being redirected to a login screen on top of the backstack. Pressing back will actually make you exit the app if your start destination does not support being in a logged out state, as suggested at 9:30 in that video. And further explained in 9:42 where popping to the start destination with
val startDestination = navController.graph.startDestination
navController.navigate(startDestination, navOptions { popUpTo(startDestination) {inclusive = true } })
is only suggested if “this would be appropriate if your start destination does not require login”. Meaning that if it does not you need to exit the app. And since you’re doing all this from the top of the backstack you don’t get the predictive back gesture animation either which would help the users understand that they are exiting the app. Not to mention in Android 14 they’d actually get the predictive back gesture which shows they’ll stay in the app, then that screen comes up,
navController.currentBackStackEntry!!.savedStateHandle
and from it
savedStateHandle.getLiveData<Boolean>(LOGIN_SUCCESSFUL)
is fetched and it is
false
, and then you exit the app, completely changing the expectations the users have when seeing that animation as they don’t stay in the app.
m

Marcin Wisniowski

03/28/2023, 9:04 PM
Nope. The screen you start the user on should be the screen they exit the app from. This has been confirmed through multiple UX studies we've ran
All right then, that is useful information! I feel like this could be mentioned here that it's intentional, it just felt like a bug to me.
i

Ian Lake

03/28/2023, 9:41 PM
That the code we provide follows the Principles of Navigation?
m

Marcin Wisniowski

03/28/2023, 10:46 PM
I get that there should be a fixed starting destination, it's just that I thought of the container with the navbar as that fixed destination. I went to the screen with the navbar, I press back, I go back to where I was before I saw the navbar, regardless if I used the navbar to switch the "internal" screen or not. The page itself says we want to avoid building a backstack as the user selects items. That "special case" of actually keeping the initial navbar screen on the backstack may seem obvious to you but it wasn't obvious to me, even after rereading about the Principles of Navigation now. This is different to having tabs on top of the screen, where pressing back does go back to before the screen-with-tabs, without going to the initial tab first, even though it seems like the same UI, just on top of the screen or the bottom.
i

Ian Lake

03/28/2023, 11:04 PM
Ah, tabs vs bottom nav have always been very distinct concepts for very, very distinct use cases in terms of the Material guidance; they've never actually been interchangeable, but I could see how that could be thought to be the case
m

Marcin Wisniowski

03/29/2023, 9:42 AM
I can see that now, although the Material Design 3 guidance for navbar says to use tabs if you have less than 3 or more than 5 entries, which makes it seem like they are interchangeable components, not for a separate purpose. The Google Chat app for example has a navbar with 2 entries (Chat, Spaces), which makes sense to me now knowing they have different behavior from tabs, but if I just looked at the M3 guidance I would think it should be using tabs (because it makes it seem like it's just a matter of the number of entries, not actually having different behavior for a different use case).