Skip to content

Commit

Permalink
Implement ExpandableAnimation & expandableHeight functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
skydoves committed Oct 29, 2019
1 parent 9b62814 commit 313fcb2
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 30 deletions.
4 changes: 2 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".MainActivity" />
<activity android:name=".CustomActivity">
<activity android:name=".CustomActivity" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class MainActivity : AppCompatActivity() {
if (expandable1.isExpanded) {
expandable1.collapse()
} else {
expandable1.expand()
expandable1.expand(370)
}
}
expandable1.secondLayout.setOnClickListener { toast("clicked the second layout") }
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
app:expandable_animation="bounce"
app:expandable_duration="300"
app:expandable_isExpanded="false"
app:expandable_parentLayout="@layout/layout_parent"
Expand All @@ -21,6 +22,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:expandable_animation="bounce"
app:expandable_duration="200"
app:expandable_isExpanded="false"
app:expandable_parentLayout="@layout/layout_parent1"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2019 skydoves
*
* 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.
*/

package com.skydoves.expandablelayout

import android.animation.Animator
import android.view.animation.AccelerateInterpolator
import android.view.animation.BounceInterpolator
import android.view.animation.LinearInterpolator

internal fun Animator.applyInterpolator(liftAnimation: ExpandableAnimation) {
when (liftAnimation) {
ExpandableAnimation.NORMAL -> this.interpolator = LinearInterpolator()
ExpandableAnimation.ACCELERATE -> this.interpolator = AccelerateInterpolator()
ExpandableAnimation.BOUNCE -> this.interpolator = BounceInterpolator()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2019 skydoves
*
* 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.
*/

package com.skydoves.expandablelayout

/** ExpandableAnimation is an animation attribute of the expanding and collapsing. */
@Suppress("unused")
enum class ExpandableAnimation(val value: Int) {
NORMAL(0),
ACCELERATE(1),
BOUNCE(2)
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class ExpandableLayout : FrameLayout {
var secondLayoutHeight: Int = 0
var isExpanded: Boolean = false
var duration: Long = 250L
var expandableAnimation: ExpandableAnimation = ExpandableAnimation.NORMAL
var spinnerRotation: Int = -180
var spinnerAnimate: Boolean = true
var onExpandListener: OnExpandListener? = null
Expand Down Expand Up @@ -117,6 +118,13 @@ class ExpandableLayout : FrameLayout {
a.getResourceId(R.styleable.ExpandableLayout_expandable_secondLayout, this.secondLayoutResource)
this.duration =
a.getInteger(R.styleable.ExpandableLayout_expandable_duration, this.duration.toInt()).toLong()
val animation =
a.getInteger(R.styleable.ExpandableLayout_expandable_animation, this.expandableAnimation.value)
when (animation) {
ExpandableAnimation.NORMAL.value -> expandableAnimation = ExpandableAnimation.NORMAL
ExpandableAnimation.ACCELERATE.value -> expandableAnimation = ExpandableAnimation.ACCELERATE
ExpandableAnimation.BOUNCE.value -> expandableAnimation = ExpandableAnimation.BOUNCE
}
this.spinnerDrawable = a.getDrawable(R.styleable.ExpandableLayout_expandable_spinner)
this.showSpinner =
a.getBoolean(R.styleable.ExpandableLayout_expandable_showSpinner, this.showSpinner)
Expand Down Expand Up @@ -150,7 +158,7 @@ class ExpandableLayout : FrameLayout {

private fun updateParentLayout() {
this.parentFrameLayout = inflate(R.layout.expandable_layout_parent) as RelativeLayout
this.parentLayout = inflate(parentLayoutResource)
this.parentLayout = inflate(this.parentLayoutResource)
this.parentLayout.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED)
this.parentFrameLayout.cover.addView(this.parentLayout)
this.parentFrameLayout.cover.updateLayoutParams { height = parentLayout.measuredHeight }
Expand Down Expand Up @@ -224,23 +232,29 @@ class ExpandableLayout : FrameLayout {
}

/** Expand the second layout with indicator animation. */
fun expand() {
fun expand(expandableHeight: Int = 0) {
post {
if (!this.isExpanded) {
val animator = ValueAnimator.ofFloat(0f, 1f)
animator.duration = this.duration
animator.addUpdateListener {
val value = it.animatedValue as Float
this.secondLayout.updateLayoutParams {
height = (secondLayoutHeight * value).toInt() + parentLayout.height
}
if (this.spinnerAnimate) {
this.parentFrameLayout.arrow.rotation = this.spinnerRotation * value
ValueAnimator.ofFloat(0f, 1f).apply {
duration = this@ExpandableLayout.duration
applyInterpolator(expandableAnimation)
addUpdateListener {
val value = it.animatedValue as Float
secondLayout.updateLayoutParams {
height = if (expandableHeight != 0) {
(expandableHeight * value).toInt() + parentLayout.height
} else {
(secondLayoutHeight * value).toInt() + parentLayout.height
}
}
if (spinnerAnimate) {
parentFrameLayout.arrow.rotation = spinnerRotation * value
}
}
isExpanded = true
onExpandListener?.onExpand(isExpanded)
start()
}
this.isExpanded = true
this.onExpandListener?.onExpand(this.isExpanded)
animator.start()
}
}
}
Expand All @@ -249,21 +263,23 @@ class ExpandableLayout : FrameLayout {
fun collapse() {
post {
if (this.isExpanded) {
val animator = ValueAnimator.ofFloat(1f, 0f)
animator.duration = this.duration
animator.addUpdateListener {
val value = it.animatedValue as Float
this.secondLayout.updateLayoutParams {
height =
((height - parentLayout.height) * value).toInt() + parentLayout.height
}
if (this.spinnerAnimate) {
this.parentFrameLayout.arrow.rotation = this.spinnerRotation * value
ValueAnimator.ofFloat(1f, 0f).apply {
duration = this@ExpandableLayout.duration
applyInterpolator(expandableAnimation)
addUpdateListener {
val value = it.animatedValue as Float
secondLayout.updateLayoutParams {
height =
((height - parentLayout.height) * value).toInt() + parentLayout.height
}
if (spinnerAnimate) {
parentFrameLayout.arrow.rotation = spinnerRotation * value
}
}
isExpanded = false
onExpandListener?.onExpand(isExpanded)
start()
}
this.isExpanded = false
this.onExpandListener?.onExpand(this.isExpanded)
animator.start()
}
}
}
Expand Down Expand Up @@ -302,6 +318,7 @@ class ExpandableLayout : FrameLayout {
fun setSpinnerSize(value: Float) = apply { this.expandableLayout.spinnerSize = value }
fun setSpinnerMargin(value: Float) = apply { this.expandableLayout.spinnerMargin = value }
fun setDuration(value: Long) = apply { this.expandableLayout.duration = value }
fun setExpandableAnimation(value: ExpandableAnimation) = apply { this.expandableLayout.expandableAnimation = value }
fun setOnExpandListener(value: OnExpandListener) = apply { this.expandableLayout.onExpandListener = value }
fun setOnExpandListener(block: (Boolean) -> Unit) = apply {
this.expandableLayout.onExpandListener = object : OnExpandListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,10 @@
<attr name="expandable_spinner_rotation" format="integer" />
<attr name="expandable_spinner_size" format="dimension" />
<attr name="expandable_spinner_margin" format="dimension" />
<attr name="expandable_animation" format="enum">
<enum name="normal" value="0" />
<enum name="accelerate" value="1" />
<enum name="bounce" value="2" />
</attr>
</declare-styleable>
</resources>
Empty file modified gradlew
100644 → 100755
Empty file.

0 comments on commit 313fcb2

Please sign in to comment.