Skip to content
This repository was archived by the owner on Jul 11, 2025. It is now read-only.

Commit ff22c8f

Browse files
committed
Update constraint layout version to 2.0 beta 3.
Also add Histogram example.
1 parent 7178973 commit ff22c8f

11 files changed

Lines changed: 651 additions & 10 deletions

File tree

ConstraintLayoutExamples/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ buildscript {
2727
targetSdkVersion = 28
2828

2929
appCompatVersion = '1.1.0-alpha03'
30-
constraintLayoutVersion = '2.0.0-beta1'
30+
constraintLayoutVersion = '2.0.0-beta3'
3131
glideVersion = '4.8.0'
3232
kotlinVersion = '1.3.11'
3333
lifeCycleVersion = '2.0.0'

ConstraintLayoutExamples/motionlayout/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
<activity android:name=".fragmentsdemo.FragmentExampleActivity"/>
3737
<activity android:name=".fragmentsdemo.FragmentExample2Activity"/>
3838
<activity android:name=".youtubedemo.YouTubeDemoActivity" />
39+
<activity android:name=".histogramdemo.HistogramActivity" />
3940
</application>
4041

4142
</manifest>

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
88
import androidx.recyclerview.widget.RecyclerView
99
import com.google.androidstudio.motionlayoutexample.fragmentsdemo.FragmentExample2Activity
1010
import com.google.androidstudio.motionlayoutexample.fragmentsdemo.FragmentExampleActivity
11+
import com.google.androidstudio.motionlayoutexample.histogramdemo.HistogramActivity
1112
import com.google.androidstudio.motionlayoutexample.viewpagerdemo.ViewPagerActivity
1213
import com.google.androidstudio.motionlayoutexample.viewpagerdemo.ViewPagerActivity2
1314
import com.google.androidstudio.motionlayoutexample.youtubedemo.YouTubeDemoActivity
@@ -46,7 +47,8 @@ class MainActivity : AppCompatActivity(), CompoundButton.OnCheckedChangeListener
4647
DemosAdapter.Demo("Fragment Transition Example (2/2)", "Example showing transitioning fragments within MotionLayout", FragmentExample2Activity::class.java),
4748
DemosAdapter.Demo("YouTube like motion Example", "Example showing a transition like YouTube", YouTubeDemoActivity::class.java),
4849
DemosAdapter.Demo("Example using KeyTrigger", "Example that calls a method using KeyTrigger", R.layout.motion_25_keytrigger),
49-
DemosAdapter.Demo("Example using Multi State", "Example that transitions between multiple states", R.layout.motion_26_multistate)
50+
DemosAdapter.Demo("Example using Multi State", "Example that transitions between multiple states", R.layout.motion_26_multistate),
51+
DemosAdapter.Demo("Histogram Example", "Advanced MotionLayout example of creating transition in code and animating dynamic data.", HistogramActivity::class.java)
5052
)
5153

5254
override fun onCreate(savedInstanceState: Bundle?) {

ConstraintLayoutExamples/motionlayout/src/main/java/com/google/androidstudio/motionlayoutexample/fragmentsdemo/FragmentExample2Activity.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,6 @@ class FragmentExample2Activity: AppCompatActivity(), View.OnClickListener, Motio
7272
override fun onTransitionCompleted(p0: MotionLayout?, p1: Int) {
7373
}
7474

75-
override fun allowsTransition(p0: MotionScene.Transition?): Boolean {
76-
return true
77-
}
78-
7975
override fun onCreate(savedInstanceState: Bundle?) {
8076
super.onCreate(savedInstanceState)
8177
setContentView(R.layout.main_activity)

ConstraintLayoutExamples/motionlayout/src/main/java/com/google/androidstudio/motionlayoutexample/fragmentsdemo/FragmentExampleActivity.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,6 @@ class FragmentExampleActivity : AppCompatActivity(), View.OnClickListener, Motio
7272
override fun onTransitionCompleted(p0: MotionLayout?, p1: Int) {
7373
}
7474

75-
override fun allowsTransition(p0: MotionScene.Transition?): Boolean {
76-
return true
77-
}
78-
7975
override fun onCreate(savedInstanceState: Bundle?) {
8076
super.onCreate(savedInstanceState)
8177
setContentView(R.layout.main_activity)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (C) 2019 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.histogramdemo
18+
19+
import android.graphics.Color
20+
import androidx.annotation.ColorInt
21+
22+
class ColorHelper {
23+
companion object {
24+
private const val GRADIENT = 20
25+
26+
/**
27+
* Returns a different color somewhat gradient.
28+
*/
29+
@JvmStatic
30+
fun getNextColor(@ColorInt color: Int): Int {
31+
return Color.argb(
32+
alpha(color),
33+
(red(color) + GRADIENT) % 256,
34+
(green(color) + GRADIENT) % 256,
35+
(blue(color) + GRADIENT) % 256)
36+
}
37+
/**
38+
* Returns a different color somewhat contrasting.
39+
*/
40+
@JvmStatic
41+
fun getContrastColor(@ColorInt color: Int): Int {
42+
return Color.argb(
43+
alpha(color),
44+
255 - red(color),
45+
255 - green(color),
46+
255 - blue(color)
47+
)
48+
}
49+
50+
private fun alpha(@ColorInt color: Int): Int {
51+
return color shr 24 and 0xff
52+
}
53+
54+
private fun red(@ColorInt color: Int): Int {
55+
return color shr 16 and 0xff
56+
}
57+
58+
private fun green(@ColorInt color: Int): Int {
59+
return color shr 8 and 0xff
60+
}
61+
62+
private fun blue(@ColorInt color: Int): Int {
63+
return color and 0xff
64+
}
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* Copyright (C) 2019 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.histogramdemo
18+
19+
import android.os.Bundle
20+
import android.view.View
21+
import android.view.ViewTreeObserver.OnGlobalLayoutListener
22+
import androidx.annotation.Nullable
23+
import androidx.appcompat.app.AppCompatActivity
24+
import androidx.constraintlayout.motion.widget.MotionLayout
25+
import androidx.constraintlayout.motion.widget.MotionLayout.TransitionListener
26+
import androidx.core.content.ContextCompat
27+
import com.google.androidstudio.motionlayoutexample.R
28+
import kotlinx.android.synthetic.main.histogram_layout.*
29+
import java.lang.RuntimeException
30+
import java.util.*
31+
import java.util.concurrent.atomic.AtomicBoolean
32+
import kotlin.collections.ArrayList
33+
34+
class HistogramActivity : AppCompatActivity() {
35+
36+
companion object {
37+
private const val DEFAULT_COLOUR_ID = R.color.colorAccent
38+
private const val HISTOGRAM_BARS_RESTORE_KEY = "HISTOGRAM"
39+
}
40+
41+
// List used for save and restoring data to the widget
42+
private var bars: ArrayList<HistogramBarMetaData> = ArrayList()
43+
44+
// The main widget
45+
private var widget: HistogramWidget? = null
46+
47+
// Animation guard
48+
private val animating = AtomicBoolean(false)
49+
private val animationListener: TransitionListener = object : TransitionListener {
50+
override fun onTransitionStarted(motionLayout: MotionLayout, startId: Int, endId: Int) {
51+
animating.set(true)
52+
}
53+
54+
override fun onTransitionCompleted(motionLayout: MotionLayout, currentId: Int) {
55+
animating.set(false)
56+
}
57+
58+
override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) { }
59+
override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) { }
60+
}
61+
62+
override fun onCreate(@Nullable savedInstanceState: Bundle?) {
63+
super.onCreate(savedInstanceState)
64+
setContentView(R.layout.histogram_layout)
65+
widget = histogram
66+
restoreView(savedInstanceState)
67+
widget!!.setTransitionListener(animationListener)
68+
}
69+
70+
/**
71+
* Add random data to the histogram.
72+
*/
73+
fun onClickAdd(view: View?) {
74+
if (animating.get()) {
75+
return
76+
}
77+
add()
78+
widget!!.animateWidget()
79+
}
80+
81+
fun onClickSort(view: View?) {
82+
if (animating.get()) {
83+
return
84+
}
85+
bars = widget!!.sort()
86+
widget!!.animateWidget()
87+
}
88+
89+
fun onClickRandom(view: View) {
90+
if (animating.get()) {
91+
return
92+
}
93+
add()
94+
bars = widget!!.sort()
95+
widget!!.animateWidget()
96+
}
97+
98+
private fun add() {
99+
val rand = Random()
100+
var barColour = ContextCompat.getColor(this, DEFAULT_COLOUR_ID)
101+
val barDataList = ArrayList<HistogramBarMetaData>(widget!!.barsSize)
102+
var name = 0
103+
for (id in widget!!.barIds) {
104+
val barData = HistogramBarMetaData(
105+
id,
106+
rand.nextFloat(),
107+
barColour,
108+
ColorHelper.getContrastColor(barColour),
109+
name.toString())
110+
barColour = ColorHelper.getNextColor(barColour)
111+
barDataList.add(barData)
112+
name++
113+
}
114+
bars = barDataList
115+
widget!!.setData(barDataList)
116+
}
117+
118+
override fun onSaveInstanceState(outState: Bundle) {
119+
if (bars.isNotEmpty()) {
120+
outState.putParcelableArrayList(HISTOGRAM_BARS_RESTORE_KEY, bars)
121+
}
122+
super.onSaveInstanceState(outState)
123+
}
124+
125+
private fun restoreView(savedInstance: Bundle?) {
126+
if (savedInstance == null) { // nothing to restore.
127+
return
128+
}
129+
bars = savedInstance.getParcelableArrayList(HISTOGRAM_BARS_RESTORE_KEY) ?: ArrayList()
130+
if (bars.isEmpty()) {
131+
return
132+
}
133+
134+
widget!!.viewTreeObserver.addOnGlobalLayoutListener(object :
135+
OnGlobalLayoutListener {
136+
override fun onGlobalLayout() {
137+
// Because we're creating all views in code, all the view ids are recreated.
138+
if (widget!!.barIds.size != bars.size) {
139+
throw RuntimeException("Restoring array doesn't match the view size.")
140+
}
141+
142+
bars = ArrayList(bars.mapIndexed{ i, metaData ->
143+
HistogramBarMetaData(widget!!.barIds[i], metaData)
144+
})
145+
widget!!.setData(bars)
146+
widget!!.animateWidget()
147+
widget!!.viewTreeObserver.removeOnGlobalLayoutListener(this)
148+
}
149+
})
150+
}
151+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (C) 2019 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.histogramdemo
18+
19+
import android.os.Parcel
20+
import android.os.Parcelable
21+
import android.os.Parcelable.Creator
22+
23+
/**
24+
* Meta data for animating Histogram bars.
25+
*
26+
* @param id View Id
27+
* @param height ranged from [0-1]
28+
* @param barColour background bar color in the form 0xAARRGGBB
29+
* @param barTextColour text color in the form 0xAARRGGBB
30+
*/
31+
data class HistogramBarMetaData(
32+
val id: Int,
33+
val height: Float,
34+
val barColour: Int,
35+
val barTextColour: Int,
36+
val name: String = id.toString()) : Parcelable {
37+
38+
constructor(id: Int, other: HistogramBarMetaData): this(
39+
id,
40+
other.height,
41+
other.barColour,
42+
other.barTextColour,
43+
other.name)
44+
45+
private constructor(source: Parcel): this(
46+
source.readInt(),
47+
source.readFloat(),
48+
source.readInt(),
49+
source.readInt(),
50+
source.readString()!!)
51+
52+
override fun writeToParcel(dest: Parcel, flags: Int) {
53+
dest.writeInt(id)
54+
dest.writeFloat(height)
55+
dest.writeInt(barColour)
56+
dest.writeInt(barTextColour)
57+
dest.writeString(name)
58+
}
59+
60+
override fun describeContents(): Int {
61+
return 0
62+
}
63+
64+
companion object CREATOR : Creator<HistogramBarMetaData> {
65+
override fun createFromParcel(parcel: Parcel): HistogramBarMetaData {
66+
return HistogramBarMetaData(parcel)
67+
}
68+
69+
override fun newArray(size: Int): Array<HistogramBarMetaData?> {
70+
return arrayOfNulls(size)
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)