diff --git a/mobile/src/main/java/android/support/design/widget/SnackbarAnimation.kt b/mobile/src/main/java/android/support/design/widget/SnackbarAnimation.kt new file mode 100644 index 00000000..7c9169cb --- /dev/null +++ b/mobile/src/main/java/android/support/design/widget/SnackbarAnimation.kt @@ -0,0 +1,8 @@ +package android.support.design.widget + +import android.view.animation.Interpolator + +object SnackbarAnimation { + val FAST_OUT_SLOW_IN_INTERPOLATOR: Interpolator get() = AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR + const val ANIMATION_DURATION = BaseTransientBottomBar.ANIMATION_DURATION.toLong() +} diff --git a/mobile/src/main/java/com/github/shadowsocks/widget/BottomMarginBehavior.kt b/mobile/src/main/java/com/github/shadowsocks/widget/BottomMarginBehavior.kt new file mode 100644 index 00000000..e420f4df --- /dev/null +++ b/mobile/src/main/java/com/github/shadowsocks/widget/BottomMarginBehavior.kt @@ -0,0 +1,40 @@ +/******************************************************************************* + * * + * Copyright (C) 2017 by Max Lv * + * Copyright (C) 2017 by Mygod Studio * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +package com.github.shadowsocks.widget + +import android.content.Context +import android.support.design.widget.CoordinatorLayout +import android.util.AttributeSet +import android.view.View +import com.github.shadowsocks.R + +class BottomMarginBehavior : CoordinatorLayout.Behavior { + constructor() : super() + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) + + override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean = + dependency.id == R.id.stat // sorry I'm too lazy to write an attribute + + override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): Boolean { + (child.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = (parent.height - dependency.y).toInt() + return true + } +} diff --git a/mobile/src/main/java/com/github/shadowsocks/widget/MoveUpwardBehavior.kt b/mobile/src/main/java/com/github/shadowsocks/widget/MoveUpwardBehavior.kt new file mode 100644 index 00000000..c29759c4 --- /dev/null +++ b/mobile/src/main/java/com/github/shadowsocks/widget/MoveUpwardBehavior.kt @@ -0,0 +1,71 @@ +/******************************************************************************* + * * + * Copyright (C) 2017 by Max Lv * + * Copyright (C) 2017 by Mygod Studio * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +package com.github.shadowsocks.widget + +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.animation.ValueAnimator +import android.content.Context +import android.os.Build +import android.support.design.widget.CoordinatorLayout +import android.support.design.widget.SnackbarAnimation +import android.support.design.widget.Snackbar +import android.support.v4.view.ViewCompat +import android.util.AttributeSet +import android.view.View + +/** + * Full credits go to: https://stackoverflow.com/a/35904421/2245107 + */ +class MoveUpwardBehavior : CoordinatorLayout.Behavior { + constructor() : super() + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) + + override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean = + dependency is Snackbar.SnackbarLayout + + override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): Boolean { + child.translationY = Math.min(0f, dependency.translationY - dependency.height) + return true + } + + /** + * Based on BaseTransientBottomBar.animateViewOut (support lib 27.0.2). + */ + override fun onDependentViewRemoved(parent: CoordinatorLayout, child: View, dependency: View) { + val animator = ValueAnimator() + val start = child.translationY + animator.setFloatValues(start, 0f) + animator.interpolator = SnackbarAnimation.FAST_OUT_SLOW_IN_INTERPOLATOR + animator.duration = SnackbarAnimation.ANIMATION_DURATION + animator.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener { + private var previousValue = start + + override fun onAnimationUpdate(animator: ValueAnimator) { + val currentValue = animator.animatedValue as Float + if (Build.VERSION.SDK_INT > 19) child.translationY = currentValue + else ViewCompat.offsetTopAndBottom(child, (currentValue - previousValue).toInt()) + previousValue = currentValue + } + }) + animator.start() + } +} diff --git a/mobile/src/main/res/layout/layout_main.xml b/mobile/src/main/res/layout/layout_main.xml index 5bc8ebd8..6a19589c 100644 --- a/mobile/src/main/res/layout/layout_main.xml +++ b/mobile/src/main/res/layout/layout_main.xml @@ -1,70 +1,140 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -72,11 +142,11 @@ + android:elevation="6dp" + app:layout_anchor="@id/stat" + app:layout_anchorGravity="top|end"> - - +