diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d33521a..000000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml deleted file mode 100644 index b268ef36c..000000000 --- a/.idea/deploymentTargetSelector.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml deleted file mode 100644 index 9a55c2de1..000000000 --- a/.idea/kotlinc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml deleted file mode 100644 index f8051a6f9..000000000 --- a/.idea/migrations.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/navEditor.xml b/.idea/navEditor.xml index 942912512..9a0d4d831 100644 --- a/.idea/navEditor.xml +++ b/.idea/navEditor.xml @@ -43,6 +43,36 @@ + + + + + + + + + diff --git a/README.md b/README.md index 397e60d6f..db24a2dac 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ This is the toy app for lesson 3 of the [Android App Development in Kotlin course on Udacity](https://www.udacity.com/course/developing-android-apps-with-kotlin--ud9012). -## Android Trivia +## Android Trivia -The Android Trivia application is an application that asks the user trivia questions about Android development. It makes use of the Navigation component within Jetpack to move the user between different screens. Each screen is implemented as a Fragment. +The Android Trivia application is an application that asks the user trivia questions about Android development. It makes use of the Navigation component within Jetpack to move the user between different screens. Each screen is implemented as a Fragment. The app navigates using buttons, the Action Bar, and the Navigation Drawer. -Since students haven't yet learned about saving data or the Android lifecycle, it tries to eliminate bugs caused by configuration changes. +Since students haven't yet learned about saving data or the Android lifecycle, it tries to eliminate bugs caused by configuration changes. ## Screenshots @@ -14,23 +14,29 @@ Since students haven't yet learned about saving data or the Android lifecycle, i ## How to use this repo while taking the course + Each code repository in this class has a chain of commits that looks like this: ![listofcommits](https://d17h27t6h515a5.cloudfront.net/topher/2017/March/58befe2e_listofcommits/listofcommits.png) -These commits show every step you'll take to create the app. Each commit contains instructions for completing that step. +These commits show every step you'll take to create the app. Each commit contains instructions for completing the that step. Each commit also has a **branch** associated with it of the same name as the commit message, seen below: -![branches](https://d17h27t6h515a5.cloudfront.net/topher/2017/April/590390fe_branches-ud855/branches-ud855.png) +![branches](https://d17h27t6h515a5.cloudfront.net/topher/2017/April/590390fe_branches-ud855/branches-ud855.png +) Access all branches from this tab -![listofbranches](https://d17h27t6h515a5.cloudfront.net/topher/2017/March/58befe76_listofbranches/listofbranches.png) +![listofbranches](https://d17h27t6h515a5.cloudfront.net/topher/2017/March/58befe76_listofbranches/listofbranches.png +) + -![branchesdropdown](https://d17h27t6h515a5.cloudfront.net/topher/2017/April/590391a3_branches-dropdown-ud855/branches-dropdown-ud855.png) +![branchesdropdown](https://d17h27t6h515a5.cloudfront.net/topher/2017/April/590391a3_branches-dropdown-ud855/branches-dropdown-ud855.png +) The branches are also accessible from the drop-down in the "Code" tab + ## Working with the Course Code Here are the basic steps for working with and completing exercises in the repo. @@ -44,6 +50,7 @@ The basic steps are: 5. Compare your code with the solution 6. Repeat steps 2-5 until you've gone trough all the steps to complete the toy app + **Step 1: Clone the repo** As you go through the course, you'll be instructed to clone the different exercise repositories, so you don't need to set these up now. You can clone a repository from github in a folder of your choice with the command: @@ -64,10 +71,11 @@ git checkout BRANCH_NAME **Step 3: Find and complete the TODOs** -Once you've checked out the branch, you'll have the code in the exact state you need. You'll even have TODOs, which are special comments that tell you all the steps you need to complete the exercise. You can easily navigate to all the TODOs using Android Studio's TODO tool. To open the TODO tool, click the button at the bottom of the screen that says TODO. This will display a list of all comments with TODO in the project. +Once you've checked out the branch, you'll have the code in the exact state you need. You'll even have TODOs, which are special comments that tell you all the steps you need to complete the exercise. You can easily navigate to all the TODOs using Android Studio's TODO tool. To open the TODO tool, click the button at the bottom of the screen that says TODO. This will display a list of all comments with TODO in the project. We've numbered the TODO steps so you can do them in order: -![todos](https://d17h27t6h515a5.cloudfront.net/topher/2017/March/58bf00e7_todos/todos.png) +![todos](https://d17h27t6h515a5.cloudfront.net/topher/2017/March/58bf00e7_todos/todos.png +) **Step 4: Commit your code changes** @@ -82,15 +90,17 @@ git commit -m "Your commit message" Most exercises will have a list of steps for you to check off in the classroom. Once you've checked these off, you'll see a pop up window with a link to the solution code. Note the **Diff** link: -![solutionwindow](https://d17h27t6h515a5.cloudfront.net/topher/2017/March/58bf00f9_solutionwindow/solutionwindow.png) +![solutionwindow](https://d17h27t6h515a5.cloudfront.net/topher/2017/March/58bf00f9_solutionwindow/solutionwindow.png +) The **Diff** link will take you to a Github diff as seen below: -![diff](https://d17h27t6h515a5.cloudfront.net/topher/2017/March/58bf0108_diffsceenshot/diffsceenshot.png) +![diff](https://d17h27t6h515a5.cloudfront.net/topher/2017/March/58bf0108_diffsceenshot/diffsceenshot.png +) -All of the code that was added in the solution is in green, and the removed code (which will usually be the TODO comments) is in red. +All of the code that was added in the solution is in green, and the removed code (which will usually be the TODO comments) is in red. You can also compare your code locally with the branch of the following step. ## Report Issues - Notice any issues with a repository? Please file a github issue in the repository. + diff --git a/app/build.gradle b/app/build.gradle index 58563a0b6..d19be74fc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,39 +1,47 @@ +/* + * Copyright 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + apply plugin: 'com.android.application' + apply plugin: 'kotlin-android' + apply plugin: 'kotlin-kapt' + apply plugin: 'androidx.navigation.safeargs' android { - namespace = "com.example.android.navigation" - compileSdkVersion 34 - + compileSdkVersion 30 buildFeatures { dataBinding true } - defaultConfig { - applicationId "com.example.android.navigation" - minSdkVersion 21 - targetSdkVersion 34 + applicationId 'com.example.android.navigation' + minSdkVersion 19 + targetSdkVersion 30 + vectorDrawables.useSupportLibrary = true versionCode 1 versionName "1.0" - vectorDrawables.useSupportLibrary = true } - buildTypes { release { minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - kotlinOptions { - jvmTarget = "17" + productFlavors { } } @@ -41,26 +49,18 @@ dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') // Kotlin - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version_kotlin" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$version_kotlin" - // AndroidX libraries - implementation "androidx.core:core-ktx:$version_core" - implementation "androidx.appcompat:appcompat:1.7.0" + // Constraint Layout implementation "androidx.constraintlayout:constraintlayout:$version_constraint_layout" + // Core + implementation "androidx.core:core:$version_core" + // Material Design implementation "com.google.android.material:material:$version_material" - // Navigation Component - implementation "androidx.navigation:navigation-fragment-ktx:$version_navigation" - implementation "androidx.navigation:navigation-ui-ktx:$version_navigation" - - // Lifecycle components - implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1" - implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.1" - - // Testing dependencies - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test:runner:1.5.2' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + // Navigation + implementation "android.arch.navigation:navigation-fragment-ktx:$version_navigation" + implementation "android.arch.navigation:navigation-ui-ktx:$version_navigation" } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index da95b4951..eb917a8d4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,8 +27,7 @@ android:theme="@style/AppTheme"> + android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"> @@ -36,4 +35,4 @@ - + \ No newline at end of file diff --git a/app/src/main/java/com/example/android/navigation/GameFragment.kt b/app/src/main/java/com/example/android/navigation/GameFragment.kt index ce089d0c9..0c0039469 100644 --- a/app/src/main/java/com/example/android/navigation/GameFragment.kt +++ b/app/src/main/java/com/example/android/navigation/GameFragment.kt @@ -16,13 +16,14 @@ package com.example.android.navigation +import androidx.databinding.DataBindingUtil import android.os.Bundle +import androidx.fragment.app.Fragment +import androidx.appcompat.app.AppCompatActivity import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.fragment.app.Fragment +import androidx.navigation.findNavController import com.example.android.navigation.databinding.FragmentGameBinding class GameFragment : Fragment() { @@ -75,8 +76,7 @@ class GameFragment : Fragment() { binding.game = this // Set the onClickListener for the submitButton - binding.submitButton.setOnClickListener @Suppress("UNUSED_ANONYMOUS_PARAMETER") - { view: View -> + binding.submitButton.setOnClickListener { view: View -> val checkedId = binding.questionRadioGroup.checkedRadioButtonId // Do nothing if nothing is checked (id == -1) if (-1 != checkedId) { @@ -97,9 +97,11 @@ class GameFragment : Fragment() { binding.invalidateAll() } else { // We've won! Navigate to the gameWonFragment. + view.findNavController().navigate(GameFragmentDirections.actionGameFragmentToGameWonFragment(numQuestions,questionIndex)) } } else { // Game over! A wrong answer sends us to the gameOverFragment. + view.findNavController().navigate(GameFragmentDirections.actionGameFragmentToGameOverFragment()) } } } diff --git a/app/src/main/java/com/example/android/navigation/GameOverFragment.kt b/app/src/main/java/com/example/android/navigation/GameOverFragment.kt index c40fc7a23..8b701a7d3 100644 --- a/app/src/main/java/com/example/android/navigation/GameOverFragment.kt +++ b/app/src/main/java/com/example/android/navigation/GameOverFragment.kt @@ -16,12 +16,13 @@ package com.example.android.navigation +import androidx.databinding.DataBindingUtil import android.os.Bundle +import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.databinding.DataBindingUtil -import androidx.fragment.app.Fragment +import androidx.navigation.findNavController import com.example.android.navigation.databinding.FragmentGameOverBinding class GameOverFragment : Fragment() { @@ -30,6 +31,9 @@ class GameOverFragment : Fragment() { // Inflate the layout for this fragment val binding: FragmentGameOverBinding = DataBindingUtil.inflate( inflater, R.layout.fragment_game_over, container, false) + binding.tryAgainButton.setOnClickListener { view: View -> + view.findNavController().navigate(GameOverFragmentDirections.actionGameOverFragmentToGameFragment()) + } return binding.root } } diff --git a/app/src/main/java/com/example/android/navigation/GameWonFragment.kt b/app/src/main/java/com/example/android/navigation/GameWonFragment.kt index 525a57afa..963017489 100644 --- a/app/src/main/java/com/example/android/navigation/GameWonFragment.kt +++ b/app/src/main/java/com/example/android/navigation/GameWonFragment.kt @@ -16,13 +16,24 @@ package com.example.android.navigation +import android.content.ActivityNotFoundException +import android.content.Intent +import androidx.databinding.DataBindingUtil import android.os.Bundle +import androidx.fragment.app.Fragment +import androidx.core.app.ShareCompat import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem import android.view.View import android.view.ViewGroup -import androidx.databinding.DataBindingUtil -import androidx.fragment.app.Fragment +import android.widget.Toast +import androidx.navigation.findNavController import com.example.android.navigation.databinding.FragmentGameWonBinding +import android.content.pm.ResolveInfo +import android.content.pm.PackageManager + class GameWonFragment : Fragment() { @@ -31,6 +42,40 @@ class GameWonFragment : Fragment() { // Inflate the layout for this fragment val binding: FragmentGameWonBinding = DataBindingUtil.inflate( inflater, R.layout.fragment_game_won, container, false) + binding.nextMatchButton.setOnClickListener { view: View -> + view.findNavController().navigate( + GameWonFragmentDirections.actionGameWonFragmentToGameFragment()) + } + setHasOptionsMenu(true) return binding.root } + + private fun getShareIntent() : Intent { + val args = GameWonFragmentArgs.fromBundle(requireArguments()) + return ShareCompat.IntentBuilder.from(activity!!) + .setText(getString(R.string.share_success_text, args.numCorrect, args.numQuestions)) + .setType("text/plain") + .intent + } + + private fun shareSuccess() { + startActivity(getShareIntent()) + } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + super.onCreateOptionsMenu(menu, inflater) + inflater.inflate(R.menu.winner_menu, menu) + // check if the activity resolves + if (null == getShareIntent().resolveActivity(requireActivity().packageManager)) { + // hide the menu item if it doesn't resolve + menu.findItem(R.id.share)?.isVisible = false + } + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.share -> shareSuccess() + } + return super.onOptionsItemSelected(item) + } } diff --git a/app/src/main/java/com/example/android/navigation/MainActivity.kt b/app/src/main/java/com/example/android/navigation/MainActivity.kt index 77831843f..c21b120cd 100644 --- a/app/src/main/java/com/example/android/navigation/MainActivity.kt +++ b/app/src/main/java/com/example/android/navigation/MainActivity.kt @@ -16,15 +16,40 @@ package com.example.android.navigation +import androidx.databinding.DataBindingUtil import android.os.Bundle import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil +import androidx.drawerlayout.widget.DrawerLayout +import androidx.navigation.NavController +import androidx.navigation.NavDestination +import androidx.navigation.findNavController +import androidx.navigation.ui.AppBarConfiguration +import androidx.navigation.ui.NavigationUI import com.example.android.navigation.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { + private lateinit var drawerLayout: DrawerLayout + private lateinit var appBarConfiguration : AppBarConfiguration override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - @Suppress("UNUSED_VARIABLE") val binding = DataBindingUtil.setContentView(this, R.layout.activity_main) + drawerLayout = binding.drawerLayout + val navController = this.findNavController(R.id.myNavHostFragment) + NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout) + appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout) + // prevent nav gesture if not on start destination + navController.addOnDestinationChangedListener { nc: NavController, nd: NavDestination, bundle: Bundle? -> + if (nd.id == nc.graph.startDestination) { + drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) + } else { + drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) + } + } + NavigationUI.setupWithNavController(binding.navView, navController) + } + + override fun onSupportNavigateUp(): Boolean { + val navController = this.findNavController(R.id.myNavHostFragment) + return NavigationUI.navigateUp(navController, appBarConfiguration) } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index df7e24a18..f7aaa714e 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -17,10 +17,30 @@ + + + + + diff --git a/app/src/main/res/layout/fragment_game_over.xml b/app/src/main/res/layout/fragment_game_over.xml index a3dffa896..bedc949c6 100644 --- a/app/src/main/res/layout/fragment_game_over.xml +++ b/app/src/main/res/layout/fragment_game_over.xml @@ -26,7 +26,7 @@ android:background="@color/gameOverBackground"> - + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 40be2f00d..42c636dcb 100644 --- a/build.gradle +++ b/build.gradle @@ -1,27 +1,47 @@ +/* + * Copyright 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext { - version_kotlin = "1.8.22" // Update to a compatible Kotlin version - version_core = "1.8.0" - version_constraint_layout = "2.1.4" - version_material = "1.5.0" - version_navigation = "2.5.1" + version_kotlin = "1.3.72" + version_core = "1.3.1" + version_constraint_layout = "2.0.0-rc1" + version_lifecycle_extensions = "2.2.0" + version_material = "1.2.0" + version_navigation = "2.3.0" } - repositories { google() - mavenCentral() + jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:8.1.1' + classpath 'com.android.tools.build:gradle:4.0.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$version_kotlin" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$version_navigation" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files } } allprojects { repositories { google() - mavenCentral() + jcenter() } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1ee260310..e6304c80d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,23 @@ +# +# Copyright 2018, The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +#Tue Aug 11 17:39:48 PDT 2020 +distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip -validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +android.databinding.enableV2=true