From f97127d2f5085e54bc40bf7b46ad94f8d2003f55 Mon Sep 17 00:00:00 2001 From: andyang Date: Wed, 9 Sep 2020 00:00:35 +0800 Subject: [PATCH 1/4] add dependencies --- app/build.gradle | 5 +++++ build.gradle | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 07590c3..4c56948 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,7 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' +apply plugin: "androidx.navigation.safeargs.kotlin" android { compileSdkVersion 29 @@ -42,6 +43,10 @@ dependencies { implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0" + // navigation component + implementation "androidx.navigation:navigation-fragment-ktx:2.3.0" + implementation "androidx.navigation:navigation-ui-ktx:2.3.0" + testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' diff --git a/build.gradle b/build.gradle index 1241d12..cf8c48b 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { dependencies { classpath "com.android.tools.build:gradle:4.0.1" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - + classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.0" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } From 4fb9873c8e1e7099d5d292ef76d08d75cbc5aecd Mon Sep 17 00:00:00 2001 From: andyang Date: Wed, 9 Sep 2020 00:49:12 +0800 Subject: [PATCH 2/4] set up navigation component --- .../kotlinandroidworkshop/MainActivity.kt | 19 ------- .../kotlinandroidworkshop/TodoListFragment.kt | 49 +++++++++++++++++++ app/src/main/res/layout/activity_main.xml | 21 +++----- .../main/res/layout/fragment_todo_list.xml | 24 +++++++++ app/src/main/res/navigation/nav_graph.xml | 13 +++++ 5 files changed, 92 insertions(+), 34 deletions(-) create mode 100644 app/src/main/java/tw/andyang/kotlinandroidworkshop/TodoListFragment.kt create mode 100644 app/src/main/res/layout/fragment_todo_list.xml create mode 100644 app/src/main/res/navigation/nav_graph.xml diff --git a/app/src/main/java/tw/andyang/kotlinandroidworkshop/MainActivity.kt b/app/src/main/java/tw/andyang/kotlinandroidworkshop/MainActivity.kt index 8c4f46f..b857996 100644 --- a/app/src/main/java/tw/andyang/kotlinandroidworkshop/MainActivity.kt +++ b/app/src/main/java/tw/andyang/kotlinandroidworkshop/MainActivity.kt @@ -2,30 +2,11 @@ package tw.andyang.kotlinandroidworkshop import android.os.Bundle import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.* -import androidx.recyclerview.widget.DividerItemDecoration -import androidx.recyclerview.widget.LinearLayoutManager -import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - - val adapter = TodoAdapter() - recyclerView.adapter = adapter - recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) - recyclerView.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL)) - - val todoViewModel = ViewModelProvider(this).get() - - todoViewModel.todoLiveData.observe(this, Observer { todos: List -> - adapter.submitList(todos) - }) - - buttonAdd.setOnClickListener { - todoViewModel.onNewTodo.postValue(Unit) - } } } \ No newline at end of file diff --git a/app/src/main/java/tw/andyang/kotlinandroidworkshop/TodoListFragment.kt b/app/src/main/java/tw/andyang/kotlinandroidworkshop/TodoListFragment.kt new file mode 100644 index 0000000..30dc90d --- /dev/null +++ b/app/src/main/java/tw/andyang/kotlinandroidworkshop/TodoListFragment.kt @@ -0,0 +1,49 @@ +package tw.andyang.kotlinandroidworkshop + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.get +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.LinearLayoutManager +import kotlinx.android.synthetic.main.fragment_todo_list.* + +class TodoListFragment : Fragment() { + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_todo_list, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + val adapter = TodoAdapter() + recyclerView.adapter = adapter + recyclerView.layoutManager = + LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) + recyclerView.addItemDecoration( + DividerItemDecoration( + requireContext(), + LinearLayoutManager.VERTICAL + ) + ) + + val todoViewModel = ViewModelProvider(this).get() + + todoViewModel.todoLiveData.observe(viewLifecycleOwner, Observer { todos: List -> + adapter.submitList(todos) + }) + + buttonAdd.setOnClickListener { + todoViewModel.onNewTodo.postValue(Unit) + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index c348834..5dca6d4 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,24 +1,15 @@ + android:layout_height="match_parent"> - - - + app:defaultNavHost="true" + app:navGraph="@navigation/nav_graph" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_todo_list.xml b/app/src/main/res/layout/fragment_todo_list.xml new file mode 100644 index 0000000..4649395 --- /dev/null +++ b/app/src/main/res/layout/fragment_todo_list.xml @@ -0,0 +1,24 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml new file mode 100644 index 0000000..ca06a54 --- /dev/null +++ b/app/src/main/res/navigation/nav_graph.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file From c60e931b2b8aabaa98e674cfe2780bcfa38b946c Mon Sep 17 00:00:00 2001 From: andyang Date: Wed, 9 Sep 2020 01:14:04 +0800 Subject: [PATCH 3/4] create add todo page and navigate from todo list page --- app/src/main/AndroidManifest.xml | 4 +- .../kotlinandroidworkshop/AddTodoFragment.kt | 54 +++++++++++++++++++ .../kotlinandroidworkshop/TodoListFragment.kt | 6 +-- .../kotlinandroidworkshop/TodoViewModel.kt | 9 ++-- app/src/main/res/layout/fragment_add_todo.xml | 20 +++++++ app/src/main/res/navigation/nav_graph.xml | 15 +++++- app/src/main/res/values/strings.xml | 1 + 7 files changed, 98 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/tw/andyang/kotlinandroidworkshop/AddTodoFragment.kt create mode 100644 app/src/main/res/layout/fragment_add_todo.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9fd06fa..0dec640 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,7 +9,9 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> - + diff --git a/app/src/main/java/tw/andyang/kotlinandroidworkshop/AddTodoFragment.kt b/app/src/main/java/tw/andyang/kotlinandroidworkshop/AddTodoFragment.kt new file mode 100644 index 0000000..4b4f858 --- /dev/null +++ b/app/src/main/java/tw/andyang/kotlinandroidworkshop/AddTodoFragment.kt @@ -0,0 +1,54 @@ +package tw.andyang.kotlinandroidworkshop + +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.InputMethodManager +import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModelProvider +import androidx.navigation.fragment.findNavController +import kotlinx.android.synthetic.main.fragment_add_todo.* + +class AddTodoFragment : Fragment() { + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_add_todo, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + editTodo.requestFocus() + + val inputMethodManager = + requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + inputMethodManager.toggleSoftInput( + InputMethodManager.SHOW_FORCED, + InputMethodManager.HIDE_IMPLICIT_ONLY + ) + + val todoViewModel = ViewModelProvider(requireActivity()).get(TodoViewModel::class.java) + + buttonAdd.setOnClickListener { + if (editTodo.text.isNullOrEmpty()) { + editTodo.error = "請輸入你的代辦事項" + } else { + // clear error + editTodo.error = null + // post data to view model + todoViewModel.onNewTodo.postValue(editTodo.text.toString()) + // hide soft keyboard when item added + view.clearFocus() + inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0) + // back to list page + findNavController().popBackStack() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/tw/andyang/kotlinandroidworkshop/TodoListFragment.kt b/app/src/main/java/tw/andyang/kotlinandroidworkshop/TodoListFragment.kt index 30dc90d..0a6c152 100644 --- a/app/src/main/java/tw/andyang/kotlinandroidworkshop/TodoListFragment.kt +++ b/app/src/main/java/tw/andyang/kotlinandroidworkshop/TodoListFragment.kt @@ -7,7 +7,7 @@ import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.get +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.android.synthetic.main.fragment_todo_list.* @@ -36,14 +36,14 @@ class TodoListFragment : Fragment() { ) ) - val todoViewModel = ViewModelProvider(this).get() + val todoViewModel = ViewModelProvider(requireActivity()).get(TodoViewModel::class.java) todoViewModel.todoLiveData.observe(viewLifecycleOwner, Observer { todos: List -> adapter.submitList(todos) }) buttonAdd.setOnClickListener { - todoViewModel.onNewTodo.postValue(Unit) + findNavController().navigate(TodoListFragmentDirections.actionMainFragmentToAddTodoFragment()) } } } \ No newline at end of file diff --git a/app/src/main/java/tw/andyang/kotlinandroidworkshop/TodoViewModel.kt b/app/src/main/java/tw/andyang/kotlinandroidworkshop/TodoViewModel.kt index fdfab8b..4386393 100644 --- a/app/src/main/java/tw/andyang/kotlinandroidworkshop/TodoViewModel.kt +++ b/app/src/main/java/tw/andyang/kotlinandroidworkshop/TodoViewModel.kt @@ -7,16 +7,13 @@ import androidx.lifecycle.ViewModel class TodoViewModel : ViewModel() { - val onNewTodo = MutableLiveData() + val onNewTodo = MutableLiveData() val todoLiveData: LiveData> = MediatorLiveData>().apply { - addSource(onNewTodo) { - val todo = Todo.Item("note $count", false) + addSource(onNewTodo) { text -> + val todo = Todo.Item(text, false) this.value = this.value!! + listOf(todo) - count++ } value = mutableListOf(Todo.Title("This is a title")) } - - private var count = 0 } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_add_todo.xml b/app/src/main/res/layout/fragment_add_todo.xml new file mode 100644 index 0000000..a00d6ae --- /dev/null +++ b/app/src/main/res/layout/fragment_add_todo.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index ca06a54..4dd99e9 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -8,6 +8,19 @@ + tools:layout="@layout/fragment_todo_list"> + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 960ef27..08becb5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2,4 +2,5 @@ KotlinAndroidWorkshop 備忘錄 新增 + 你的待辦事項 \ No newline at end of file From f97fa435dd6fd90b87e5270d3675bfc511843a63 Mon Sep 17 00:00:00 2001 From: andyang Date: Wed, 9 Sep 2020 01:21:05 +0800 Subject: [PATCH 4/4] pass data between two page by argument --- .../tw/andyang/kotlinandroidworkshop/AddTodoFragment.kt | 9 ++++++++- app/src/main/res/navigation/nav_graph.xml | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/tw/andyang/kotlinandroidworkshop/AddTodoFragment.kt b/app/src/main/java/tw/andyang/kotlinandroidworkshop/AddTodoFragment.kt index 4b4f858..0be5ef1 100644 --- a/app/src/main/java/tw/andyang/kotlinandroidworkshop/AddTodoFragment.kt +++ b/app/src/main/java/tw/andyang/kotlinandroidworkshop/AddTodoFragment.kt @@ -9,10 +9,13 @@ import android.view.inputmethod.InputMethodManager import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs import kotlinx.android.synthetic.main.fragment_add_todo.* class AddTodoFragment : Fragment() { + private val args by navArgs() + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -24,8 +27,8 @@ class AddTodoFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + // auto open soft keyboard editTodo.requestFocus() - val inputMethodManager = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager inputMethodManager.toggleSoftInput( @@ -33,6 +36,10 @@ class AddTodoFragment : Fragment() { InputMethodManager.HIDE_IMPLICIT_ONLY ) + // setup argument + editTodo.setText(args.memo) + editTodo.setSelection(args.memo.length) + val todoViewModel = ViewModelProvider(requireActivity()).get(TodoViewModel::class.java) buttonAdd.setOnClickListener { diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 4dd99e9..3cb54aa 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -21,6 +21,13 @@ + tools:layout="@layout/fragment_add_todo"> + + + + \ No newline at end of file