Kotlin and Android Development featuring Jetpack: Cannot reach Settings Fragment in Penny Drop (p. 177)

Hi @mfazio23

I’ve reached the top of p. 177, and I can run Penny Drop both on my real Samsung tablet and on the in-IDE emulator, but I cannot reach the newly-created Settings fragment. Looking at the sentence on p. 173, “Instead of the bottom nav, settings are accessed via a gear icon in the app’s nav bar.” This raises a question for me: What is the “nav bar”? I thought that the “bottom nav” and the “nav bar” were the same thing, but apparently not?

Also, for some reason, it only just now dawned on me that the app screenshots in the book (such as on p. 168) show a large title bar of some kind (the “nav bar”?) at the top of both the Game and Pick Players screens, saying “Penny Drop”, but this is completely absent from my app! I’ve spent some time comparing my (typed-in) source code to the downloaded Ch. 6 and 7 source code, and I cannot figure out what is wrong with my version of the source code. I’d google how to make this show up or not, but Googling “nav bar” brought up pictures of what the book appears to call the “bottom nav”, so I’m confused.

(I will attach screenshots here of what Penny Drop looks like for me at this point.)

I’m sure I’ve made a very dumb mistake and disabled or removed… something, but what did I do? Suggestions?

I have been uploading my work on this book here: GitHub - dachristenson/PennyDrop4: Fourth attempt at working through "Kotlin and Android Development featuring Jetpack" due to changes in Android Studio.


Hey Derek!
First off, apologies for me taking a while to get back to you.

For your question, the “nav bar” in this context would probably be better listed as the “action bar” or “app bar”. It is indeed that title bar you noticed was missing, and thankfully it’s a simple change to re-add it.

In your values/themes.xml files (both normal and night), you’re using Theme.Material3.DayNight.NoActionBar as your parent theme. This will remove the action bar from the MainActivity that would normally be there. On the plus side, I added it back into your code and your navigation to the Settings screen works perfectly!

Let me know if that works!

Thank you, Sir! I just deleted the “.NoActionBar” part of the “parent” property of both themes, and it seems to be working more as I expected.

I am a little puzzled why Google apparently made that the default now, but that must be what happened. I have not yet reached the part of the chapter that instructs me to edit those themes, so they must have been created that way by Android Studio.

By the way, I still have two lines in my GameViewModel, which Android Studio highlights and marks as “unreachable” (lines 120 and 126, in my copy, both branches of a when statement. Is this normal, and something that will change by the time I finish the app, or do I have a bug? (Or is Android Studio making a static analysis error?) I thought that part of the program was complete.

Thanks again!

I think it’s just a shift in recommended styling, especially since you’re using Material Design 3. Most apps have gone away from using an action bar and instead handle settings and navigation elsewhere.

I just realized you mentioned this last time too. I looked a bit then and never found a sufficient answer. My thinking is that it’s thrown off by the nullability of previousPlayer and currentPlayer, but if you throw a debugger on that branch I bet it’ll work.

The extra odd part is that I tried the same thing in a Kotlin command line project to test out the code and the same issue doesn’t seem to show up there.

If you’re too troubled by the error, you can switch the when { ... } to skip the subject and instead do the comparisons manually:

when {
    status.playerId == result.previousPlayer?.playerId -> {
        status.copy(
            isRolling = false,
            pennies = status.pennies + (result.coinChangeCount ?: 0)
        )
    }
    status.playerId == result.currentPlayer?.playerId -> {
        status.copy(
            isRolling = !result.isGameOver,
            pennies = status.pennies +
                if (!result.playerChanged) {
                    result.coinChangeCount ?: 0
                } else 0
        )
    }
    else -> status
}

This will still have a warning telling you to use a subject, but it’s more subtle, at least. I really don’t think there’s an actual issue here, though, given that this is seen as fine and the other way isn’t while being the same logic.

Ah, that makes sense. I’ll just ignore it for now, then.

I did notice another odd thing about the App Bar, though. If I understand correctly, it should say “Penny Drop” on every screen except the Settings screen, where it should say “Settings” and have a back-arrow on the left, with which to return to the previous screen. On my build, it still just says “Penny Drop” and has no back-arrow. What else am I missing here?

There are three main things here:
You need to update MainActivity to include an AppBarConfiguration:

val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_nav)
bottomNav.setupWithNavController(this.navController)

val appBarConfiguration = AppBarConfiguration(bottomNav.menu)
setupActionBarWithNavController(this.navController, appBarConfiguration)

Then, you need to update your navigation/nav_graph.xml file to have proper names for the labels:

    <fragment
        android:id="@+id/pickPlayersFragment"
        android:name="com.example.pennydrop4.fragments.PickPlayersFragment"
        android:label="@string/pick_players" />
    <fragment
        android:id="@+id/gameFragment"
        android:name="com.example.pennydrop4.fragments.GameFragment"
        android:label="@string/penny_drop" />
    <fragment
        android:id="@+id/rankingsFragment"
        android:name="com.example.pennydrop4.fragments.RankingsFragment"
        android:label="@string/rankings" />

You need to create these new string resources, but that’ll look better.

Finally, in MainActivity, you need to override onSupportNavigateUp() to use the navController:

override fun onSupportNavigateUp(): Boolean =
    (this::navController.isInitialized && this.navController.navigateUp()) ||
        super.onSupportNavigateUp()

Let me know if this takes care of things!

Yes, those changes made it all work! Thank you!

Reader’s curiosity: Are these changes mentioned in the book, and I missed them? I see now that they have been made in the downloadable code for Ch. 7 (vs. Ch. 6 and earlier), but I don’t see them mentioned in the text itself. This is either me being blind (very possible!) or a mild criticism. :slight_smile:

In any case, I am very grateful for your assistance. Thanks again!

You didn’t miss anything here, this is indeed part of chapter 7 during the “Add an About the App Section” section. You likely just haven’t gotten to this spot yet.