Skip to content
This repository was archived by the owner on Nov 21, 2024. It is now read-only.

Commit 26fa6ee

Browse files
committed
Add transition into course details screen.
Change-Id: Icea1622f1c4951ece903de6e65d59f7b285e29ec
1 parent f460c6d commit 26fa6ee

40 files changed

+1197
-121
lines changed

app/build.gradle

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ apply plugin: "androidx.navigation.safeargs.kotlin"
1919

2020
android {
2121
compileSdkVersion 29
22-
buildToolsVersion "29.0.0"
2322
defaultConfig {
2423
applicationId "com.materialstudies.owl"
2524
minSdkVersion 23
@@ -41,14 +40,17 @@ android {
4140
sourceCompatibility JavaVersion.VERSION_1_8
4241
targetCompatibility JavaVersion.VERSION_1_8
4342
}
43+
kotlinOptions {
44+
jvmTarget = "1.8"
45+
}
4446
}
4547

4648
dependencies {
4749
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
4850
implementation 'androidx.fragment:fragment:1.2.0-alpha01'
4951
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
5052
implementation 'androidx.core:core-ktx:1.0.2'
51-
implementation 'com.google.android.material:material:1.1.0-alpha08'
53+
implementation 'com.google.android.material:material:1.1.0-alpha09'
5254
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
5355

5456
implementation "androidx.navigation:navigation-runtime-ktx:$nav_version"

app/src/main/java/com/materialstudies/owl/model/Course.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ package com.materialstudies.owl.model
1818

1919
import androidx.recyclerview.widget.DiffUtil
2020

21+
typealias CourseId = Long
22+
2123
data class Course(
22-
val id: Long,
24+
val id: CourseId,
2325
val name: String,
2426
val subject: String,
2527
val thumbUrl: String,
@@ -35,6 +37,10 @@ object CourseDiff : DiffUtil.ItemCallback<Course>() {
3537
override fun areContentsTheSame(oldItem: Course, newItem: Course) = oldItem == newItem
3638
}
3739

40+
object CourseRepo {
41+
fun getCourse(id: CourseId) = courses.find { it.id == id } ?: courses.last()
42+
}
43+
3844
val courses = listOf(
3945
Course(
4046
id = 0,
@@ -150,8 +156,6 @@ val courses = listOf(
150156
subject = "Photography",
151157
thumbUrl = "https://source.unsplash.com/KxCJXXGsv9I",
152158
thumbContentDesc = "",
153-
description = "This video course introduces the photography of structures, including " +
154-
"urban and rural buildings, monuments, and less traditional structures. Instruction includes the handling of equipment and methods used to capture building interiors and exteriors. The discussion will be about the handling of distortion, varied light sources, and perspective.",
155159
steps = 4,
156160
step = 1
157161
)

app/src/main/java/com/materialstudies/owl/ui/MainActivity.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import androidx.navigation.ui.setupWithNavController
2525
import com.materialstudies.owl.R
2626
import com.materialstudies.owl.databinding.ActivityMainBinding
2727
import com.materialstudies.owl.util.contentView
28+
import com.materialstudies.owl.util.hide
29+
import com.materialstudies.owl.util.show
2830

2931
class MainActivity : AppCompatActivity() {
3032

@@ -38,9 +40,9 @@ class MainActivity : AppCompatActivity() {
3840

3941
// Hide bottom nav on screens which don't require it
4042
navController.addOnDestinationChangedListener { _, destination, _ ->
41-
bottomNav.visibility = when (destination.id) {
42-
R.id.myCourses, R.id.featured, R.id.search -> VISIBLE
43-
else -> GONE
43+
when (destination.id) {
44+
R.id.myCourses, R.id.featured, R.id.search -> bottomNav.show()
45+
else -> bottomNav.hide()
4446
}
4547
}
4648
}

app/src/main/java/com/materialstudies/owl/ui/featured/FeaturedAdapter.kt

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,47 +17,47 @@
1717
package com.materialstudies.owl.ui.featured
1818

1919
import android.view.LayoutInflater
20+
import android.view.View
2021
import android.view.ViewGroup
21-
import androidx.navigation.Navigation.findNavController
22-
import androidx.navigation.fragment.findNavController
2322
import androidx.recyclerview.widget.ListAdapter
2423
import androidx.recyclerview.widget.RecyclerView
25-
import com.bumptech.glide.Glide
26-
import com.materialstudies.owl.R
2724
import com.materialstudies.owl.databinding.FeaturedItemBinding
2825
import com.materialstudies.owl.model.Course
2926
import com.materialstudies.owl.model.CourseDiff
27+
import com.materialstudies.owl.model.CourseId
3028

31-
class FeaturedAdapter : ListAdapter<Course, FeaturedViewHolder>(CourseDiff) {
29+
class FeaturedAdapter(
30+
private val onClick: CourseViewClick
31+
) : ListAdapter<Course, FeaturedViewHolder>(CourseDiff) {
3232

3333
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FeaturedViewHolder {
34-
val binding = FeaturedItemBinding.inflate(
35-
LayoutInflater.from(parent.context),
36-
parent,
37-
false
38-
).apply {
39-
root.setOnClickListener {
40-
findNavController(it).navigate(R.id.learn)
41-
}
42-
}
43-
return FeaturedViewHolder(binding)
34+
return FeaturedViewHolder(
35+
FeaturedItemBinding.inflate(
36+
LayoutInflater.from(parent.context),
37+
parent,
38+
false
39+
)
40+
)
4441
}
4542

4643
override fun onBindViewHolder(holder: FeaturedViewHolder, position: Int) {
47-
holder.bind(getItem(position))
44+
holder.bind(getItem(position), onClick)
4845
}
46+
}
4947

48+
interface CourseViewClick {
49+
fun onClick(view: View, courseId: CourseId)
5050
}
5151

5252
class FeaturedViewHolder(
5353
private val binding: FeaturedItemBinding
5454
) : RecyclerView.ViewHolder(binding.root) {
5555

56-
fun bind(course: Course) {
56+
fun bind(course: Course, onClick: CourseViewClick) {
5757
binding.run {
5858
this.course = course
59+
clickHandler = onClick
5960
executePendingBindings()
6061
}
6162
}
62-
6363
}

app/src/main/java/com/materialstudies/owl/ui/featured/FeaturedFragment.kt

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,19 @@ import android.os.Bundle
2020
import android.view.LayoutInflater
2121
import android.view.View
2222
import android.view.ViewGroup
23-
import androidx.core.view.postDelayed
23+
import androidx.core.view.doOnNextLayout
2424
import androidx.fragment.app.Fragment
25+
import androidx.navigation.findNavController
26+
import androidx.navigation.fragment.FragmentNavigatorExtras
2527
import com.materialstudies.owl.databinding.FragmentFeaturedBinding
28+
import com.materialstudies.owl.model.CourseId
2629
import com.materialstudies.owl.model.courses
2730
import com.materialstudies.owl.util.SpringAddItemAnimator
31+
import java.util.concurrent.TimeUnit
2832

33+
/**
34+
* A [Fragment] displaying featured courses.
35+
*/
2936
class FeaturedFragment : Fragment() {
3037

3138
override fun onCreateView(
@@ -34,17 +41,35 @@ class FeaturedFragment : Fragment() {
3441
savedInstanceState: Bundle?
3542
): View? {
3643
val binding = FragmentFeaturedBinding.inflate(inflater, container, false).apply {
44+
val onClick: CourseViewClick = object : CourseViewClick {
45+
override fun onClick(view: View, courseId: CourseId) {
46+
val extras = FragmentNavigatorExtras(
47+
view to "shared_element"
48+
)
49+
val action = FeaturedFragmentDirections.actionFeaturedToLearn(courseId)
50+
/* awaiting aosp/987385 in fragment 1.2.0-alpha02
51+
exitTransition = Recede().apply {
52+
addTarget(root)
53+
excludeTarget(view, true)
54+
duration = 300L
55+
}*/
56+
view.findNavController().navigate(action, extras)
57+
}
58+
}
3759
featuredGrid.apply {
3860
itemAnimator = SpringAddItemAnimator()
39-
adapter = FeaturedAdapter().apply {
40-
// Add animations not running without this delay
41-
// TODO(nickbutcher) work out why
42-
postDelayed(100L) {
61+
adapter = FeaturedAdapter(onClick).apply {
62+
// add data after layout so that animations run
63+
doOnNextLayout {
4364
submitList(courses)
65+
doOnNextLayout {
66+
startPostponedEnterTransition()
67+
}
4468
}
4569
}
4670
}
4771
}
72+
postponeEnterTransition(1000L, TimeUnit.MILLISECONDS)
4873
return binding.root
4974
}
5075
}

app/src/main/java/com/materialstudies/owl/ui/learn/LearnFragment.kt

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,72 @@ import android.os.Bundle
2020
import android.view.LayoutInflater
2121
import android.view.View
2222
import android.view.ViewGroup
23+
import android.view.animation.AnimationUtils
2324
import androidx.fragment.app.Fragment
2425
import androidx.navigation.fragment.findNavController
26+
import androidx.navigation.fragment.navArgs
27+
import com.materialstudies.owl.R
2528
import com.materialstudies.owl.databinding.FragmentLearnBinding
29+
import com.materialstudies.owl.model.CourseRepo
2630
import com.materialstudies.owl.model.courses
31+
import com.materialstudies.owl.ui.lessons.LessonsSheetFragment
32+
import com.materialstudies.owl.util.transition.DiagonalSlide
33+
import com.materialstudies.owl.util.transition.MaterialContainerTransition
34+
import com.materialstudies.owl.util.loadListener
35+
import java.util.concurrent.TimeUnit
2736

2837
/**
2938
* A [Fragment] displaying the learn screen.
3039
*/
3140
class LearnFragment : Fragment() {
3241

42+
private val args: LearnFragmentArgs by navArgs()
43+
3344
override fun onCreateView(
3445
inflater: LayoutInflater,
3546
container: ViewGroup?,
3647
savedInstanceState: Bundle?
3748
): View? {
49+
val course = CourseRepo.getCourse(args.courseId)
3850
val binding = FragmentLearnBinding.inflate(inflater, container, false).apply {
39-
course = courses.last()
51+
this.course = course
52+
imageLoadListener = loadListener {
53+
startPostponedEnterTransition()
54+
}
4055
toolbar.setNavigationOnClickListener {
41-
findNavController().popBackStack()
56+
findNavController().navigateUp()
4257
}
4358
alsoLikeList.adapter = RelatedAdapter().apply {
4459
submitList(courses)
4560
}
4661
}
62+
(childFragmentManager.findFragmentById(R.id.lessons_sheet) as? LessonsSheetFragment)?.let {
63+
it.course = course
64+
}
65+
postponeEnterTransition(1000L, TimeUnit.MILLISECONDS)
66+
val interp = AnimationUtils.loadInterpolator(
67+
context,
68+
android.R.interpolator.fast_out_slow_in
69+
)
70+
sharedElementEnterTransition = MaterialContainerTransition(R.id.scroll).apply {
71+
duration = 400L
72+
interpolator = interp
73+
}
74+
enterTransition = DiagonalSlide().apply {
75+
addTarget(R.id.lessons_sheet)
76+
startDelay = 200L
77+
duration = 200L
78+
interpolator = interp
79+
}
80+
sharedElementReturnTransition = MaterialContainerTransition().apply {
81+
duration = 300L
82+
interpolator = interp
83+
}
84+
returnTransition = DiagonalSlide().apply {
85+
addTarget(R.id.lessons_sheet)
86+
duration = 100L
87+
interpolator = interp
88+
}
4789
return binding.root
4890
}
4991
}

app/src/main/java/com/materialstudies/owl/ui/lessons/LessonAdapter.kt

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,29 @@
1717
package com.materialstudies.owl.ui.lessons
1818

1919
import android.view.LayoutInflater
20-
import android.view.View
2120
import android.view.ViewGroup
22-
import androidx.navigation.Navigation
23-
import androidx.navigation.findNavController
2421
import androidx.recyclerview.widget.ListAdapter
2522
import androidx.recyclerview.widget.RecyclerView
26-
import com.materialstudies.owl.R
2723
import com.materialstudies.owl.databinding.LessonItemBinding
2824
import com.materialstudies.owl.model.Lesson
2925
import com.materialstudies.owl.model.LessonDiff
3026

31-
class LessonAdapter : ListAdapter<Lesson, LessonViewHolder>(LessonDiff) {
27+
class LessonAdapter(
28+
private val onClick: (Int) -> Unit
29+
) : ListAdapter<Lesson, LessonViewHolder>(LessonDiff) {
3230

3331
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LessonViewHolder {
34-
val binding = LessonItemBinding.inflate(
35-
LayoutInflater.from(parent.context), parent,
36-
false
37-
).apply {
38-
root.setOnClickListener {
39-
it.findNavController().navigate(R.id.lesson)
40-
}
32+
val binding = LessonItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
33+
val holder = LessonViewHolder(binding)
34+
binding.root.setOnClickListener {
35+
onClick(holder.adapterPosition)
4136
}
42-
return LessonViewHolder(binding)
37+
return holder
4338
}
4439

4540
override fun onBindViewHolder(holder: LessonViewHolder, position: Int) {
4641
holder.bind(getItem(position))
4742
}
48-
4943
}
5044

5145
class LessonViewHolder(

app/src/main/java/com/materialstudies/owl/ui/lessons/LessonFragment.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,27 @@
1717
package com.materialstudies.owl.ui.lessons
1818

1919
import android.os.Bundle
20-
import androidx.fragment.app.Fragment
2120
import android.view.LayoutInflater
2221
import android.view.View
2322
import android.view.ViewGroup
23+
import androidx.core.view.doOnLayout
24+
import androidx.fragment.app.Fragment
2425
import androidx.navigation.findNavController
25-
26+
import androidx.navigation.fragment.navArgs
27+
import androidx.transition.TransitionInflater
2628
import com.materialstudies.owl.R
2729
import com.materialstudies.owl.databinding.FragmentLessonBinding
30+
import com.materialstudies.owl.model.CourseRepo
2831
import com.materialstudies.owl.model.lessons
32+
import java.util.concurrent.TimeUnit
2933

3034
/**
3135
* A [Fragment] displaying a lesson.
3236
*/
3337
class LessonFragment : Fragment() {
3438

39+
private val args: LessonFragmentArgs by navArgs()
40+
3541
override fun onCreateView(
3642
inflater: LayoutInflater,
3743
container: ViewGroup?,
@@ -41,11 +47,15 @@ class LessonFragment : Fragment() {
4147
lesson = lessons.first()
4248
steps.apply {
4349
adapter = StepsAdapter(lessons, context)
50+
smoothScrollToPosition(args.stepNumber)
4451
}
4552
collapse.setOnClickListener {
4653
it.findNavController().popBackStack()
4754
}
4855
}
56+
(childFragmentManager.findFragmentById(R.id.lessons_sheet) as? LessonsSheetFragment)?.let {
57+
it.course = CourseRepo.getCourse(args.courseId)
58+
}
4959
return binding.root
5060
}
5161
}

0 commit comments

Comments
 (0)