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

Commit 5e70734

Browse files
committed
Add YouTube like animiation.
Submit the PR as of now because the animation works similarly as the YouTube app. But ideally only the height of the animated image should change first until the image moves close to the bottom of the screen, then the width shrinks after that. But looks like it's not supported to interpolate the size of an view using KeyAttribute or KeyPosition. I think if MotionLayout allows an intermediate ConstraintSet, the animation becomes possible.
1 parent 24c46c5 commit 5e70734

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+688
-10
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ local.properties
77
/build
88
/captures
99
.externalNativeBuild
10+
.idea/

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
// Top-level build file where you can add configuration options common to all sub-projects/modules.
1818

1919
buildscript {
20-
ext.kotlin_version = '1.2.41'
20+
ext.kotlin_version = '1.3.0'
2121
repositories {
2222
google()
2323
jcenter()
2424
}
2525
dependencies {
26-
classpath 'com.android.tools.build:gradle:3.2.0-beta01'
26+
classpath 'com.android.tools.build:gradle:3.2.1'
2727
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
2828

2929
// NOTE: Do not place your application dependencies here; they belong

constraintlayout/build.gradle

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
apply plugin: 'com.android.application'
1818

1919
android {
20-
compileSdkVersion 27
20+
compileSdkVersion 28
2121
defaultConfig {
2222
applicationId "com.example.android.constraintlayoutexamples"
2323
minSdkVersion 19
24-
targetSdkVersion 27
24+
targetSdkVersion 28
2525
versionCode 1
2626
versionName "1.0"
2727
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -34,7 +34,8 @@ dependencies {
3434
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
3535
exclude group: 'com.android.support', module: 'support-annotations'
3636
})
37-
implementation 'com.android.support:appcompat-v7:27.1.1'
37+
implementation 'com.android.support:design:28.0.0'
38+
implementation 'com.android.support:appcompat-v7:28.0.0'
3839
testImplementation 'junit:junit:4.12'
39-
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
40+
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
4041
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#Fri Feb 10 14:44:40 PST 2017
1+
#Fri Nov 16 15:14:01 JST 2018
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip

motionlayout/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ dependencies {
4747
implementation 'android.arch.lifecycle:extensions:1.1.1'
4848
implementation 'com.android.support:design:27.1.1'
4949
implementation 'com.airbnb.android:lottie:2.5.1'
50+
implementation 'com.github.bumptech.glide:glide:4.8.0'
51+
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
5052
testImplementation 'junit:junit:4.12'
5153
androidTestImplementation 'com.android.support.test:runner:1.0.2'
5254
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

motionlayout/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
<activity android:name=".viewpagerdemo.ViewPagerActivity2"/>
3636
<activity android:name=".fragmentsdemo.FragmentExampleActivity"/>
3737
<activity android:name=".fragmentsdemo.FragmentExample2Activity"/>
38+
<activity android:name=".youtubedemo.YouTubeDemoActivity" />
3839
</application>
3940

4041
</manifest>

motionlayout/src/main/java/com/google/androidstudio/motionlayoutexample/MainActivity.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.google.androidstudio.motionlayoutexample.fragmentsdemo.FragmentExampl
1010
import com.google.androidstudio.motionlayoutexample.fragmentsdemo.FragmentExampleActivity
1111
import com.google.androidstudio.motionlayoutexample.viewpagerdemo.ViewPagerActivity
1212
import com.google.androidstudio.motionlayoutexample.viewpagerdemo.ViewPagerActivity2
13+
import com.google.androidstudio.motionlayoutexample.youtubedemo.YouTubeDemoActivity
1314
import kotlinx.android.synthetic.main.activity_main.*
1415

1516
class MainActivity : AppCompatActivity(), CompoundButton.OnCheckedChangeListener {
@@ -41,7 +42,9 @@ class MainActivity : AppCompatActivity(), CompoundButton.OnCheckedChangeListener
4142
DemosAdapter.Demo("Complex Motion Example (3/4)", "Advanced CoordinatorLayout-like behavior (adding a FAB). Implemented with MotionLayout only, using direct resizing of the view.", R.layout.motion_19_coordination),
4243
DemosAdapter.Demo("Complex Motion Example (4/4)", "Advanced Synchronized reval motion + helper (bounce). Implemented with MotionLayout only.", R.layout.motion_20_reveal),
4344
DemosAdapter.Demo("Fragment Transition Example (1/2)", "Example showing transitioning fragments within MotionLayout", FragmentExampleActivity::class.java),
44-
DemosAdapter.Demo("Fragment Transition Example (2/2)", "Example showing transitioning fragments within MotionLayout", FragmentExample2Activity::class.java)
45+
DemosAdapter.Demo("Fragment Transition Example (2/2)", "Example showing transitioning fragments within MotionLayout", FragmentExample2Activity::class.java),
46+
DemosAdapter.Demo("Fragment Transition Example (2/2)", "Example showing transitioning fragments within MotionLayout", FragmentExample2Activity::class.java),
47+
DemosAdapter.Demo("YouTube like motion Example", "Example showing a transition like YouTube", YouTubeDemoActivity::class.java)
4548
)
4649

4750
override fun onCreate(savedInstanceState: Bundle?) {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2018 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.androidstudio.motionlayoutexample.youtubedemo
18+
19+
import com.google.androidstudio.motionlayoutexample.R
20+
21+
object Cats {
22+
23+
val catImages = intArrayOf(
24+
R.drawable.cat_1,
25+
R.drawable.cat_2,
26+
R.drawable.cat_3,
27+
R.drawable.cat_4,
28+
R.drawable.cat_5,
29+
R.drawable.cat_6,
30+
R.drawable.cat_7,
31+
R.drawable.cat_8,
32+
R.drawable.cat_9,
33+
R.drawable.cat_10,
34+
R.drawable.cat_11,
35+
R.drawable.cat_12,
36+
R.drawable.cat_13,
37+
R.drawable.cat_14,
38+
R.drawable.cat_15,
39+
R.drawable.cat_16,
40+
R.drawable.cat_17,
41+
R.drawable.cat_18,
42+
R.drawable.cat_19
43+
)
44+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Copyright 2018 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.androidstudio.motionlayoutexample.youtubedemo
18+
19+
import android.support.v7.widget.RecyclerView
20+
import android.view.LayoutInflater
21+
import android.view.View
22+
import android.view.ViewGroup
23+
import android.widget.ImageView
24+
import android.widget.TextView
25+
import com.bumptech.glide.Glide
26+
import com.google.androidstudio.motionlayoutexample.youtubedemo.YouTubeDemoViewHolder.CatRowViewHolder
27+
import com.google.androidstudio.motionlayoutexample.youtubedemo.YouTubeDemoViewHolder.TextDescriptionViewHolder
28+
import com.google.androidstudio.motionlayoutexample.youtubedemo.YouTubeDemoViewHolder.TextHeaderViewHolder
29+
import com.google.androidstudio.motionlayoutexample.R
30+
31+
class FrontPhotosAdapter : RecyclerView.Adapter<YouTubeDemoViewHolder>() {
32+
33+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): YouTubeDemoViewHolder {
34+
val inflater = LayoutInflater.from(parent.context)
35+
val itemView = inflater.inflate(viewType, parent, false)
36+
return when (viewType) {
37+
R.layout.motion_24_recyclerview_expanded_text_header -> TextHeaderViewHolder (itemView)
38+
R.layout.motion_24_recyclerview_expanded_text_description -> TextDescriptionViewHolder (itemView)
39+
R.layout.motion_24_recyclerview_expanded_row -> CatRowViewHolder(itemView)
40+
else -> throw IllegalStateException("Unknown viewType $viewType")
41+
}
42+
}
43+
44+
override fun onBindViewHolder(holder: YouTubeDemoViewHolder, position: Int) {
45+
when (holder) {
46+
is TextHeaderViewHolder -> {}
47+
is TextDescriptionViewHolder -> {}
48+
is CatRowViewHolder -> {
49+
val imagePosition = position - 2
50+
holder.textView.text = holder.textView.resources.getString(R.string.cat_n, imagePosition)
51+
Glide.with(holder.imageView)
52+
.load(Cats.catImages[imagePosition])
53+
.into(holder.imageView)
54+
}
55+
}
56+
}
57+
58+
override fun getItemViewType(position: Int): Int {
59+
60+
return when (position) {
61+
0 -> R.layout.motion_24_recyclerview_expanded_text_header
62+
1 -> R.layout.motion_24_recyclerview_expanded_text_description
63+
else -> R.layout.motion_24_recyclerview_expanded_row
64+
}
65+
}
66+
67+
override fun getItemCount() = Cats.catImages.size + 2 // For text header and text description
68+
}
69+
70+
/**
71+
* [RecyclerView.ViewHolder] types used by this adapter.
72+
*/
73+
sealed class YouTubeDemoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
74+
75+
class TextHeaderViewHolder(
76+
itemView: View
77+
) : YouTubeDemoViewHolder(itemView)
78+
79+
class TextDescriptionViewHolder(
80+
itemView: View
81+
) : YouTubeDemoViewHolder(itemView)
82+
83+
class CatRowViewHolder(
84+
itemView: View
85+
) : YouTubeDemoViewHolder(itemView) {
86+
val imageView = itemView.findViewById(R.id.image_row) as ImageView
87+
val textView = itemView.findViewById(R.id.text_row) as TextView
88+
}
89+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (C) 2018 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.androidstudio.motionlayoutexample.youtubedemo
18+
19+
import android.os.Bundle
20+
import android.support.constraint.motion.MotionLayout
21+
import android.support.v7.app.AppCompatActivity
22+
import android.support.v7.widget.LinearLayoutManager
23+
import android.support.v7.widget.RecyclerView
24+
import com.google.androidstudio.motionlayoutexample.R
25+
26+
class YouTubeDemoActivity : AppCompatActivity() {
27+
28+
override fun onCreate(savedInstanceState: Bundle?) {
29+
super.onCreate(savedInstanceState)
30+
setContentView(R.layout.motion_24_youtube)
31+
val motionLayout = findViewById<MotionLayout>(R.id.motionLayout).apply {
32+
savedInstanceState
33+
}
34+
findViewById<RecyclerView>(R.id.recyclerview_front).apply {
35+
adapter = FrontPhotosAdapter()
36+
isNestedScrollingEnabled = false
37+
layoutManager = LinearLayoutManager(this@YouTubeDemoActivity)
38+
}
39+
val doShowPaths = intent.getBooleanExtra("showPaths", false)
40+
motionLayout.setShowPaths(doShowPaths)
41+
}
42+
}

0 commit comments

Comments
 (0)