[英]FAB not animated when one-line Snackbar is swiped away
我有一個支持FloatingActionButton
的CoordinatorLayout
,我想在其中顯示一個Snackbar
..
<android.support.design.widget.CoordinatorLayout
android:id="@+id/rootView"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
...
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_add_field"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/margin_default"
android:layout_marginBottom="@dimen/profile_floating_margin_bottom"
android:layout_marginRight="@dimen/profile_floating_margin_right"
android:clickable="true"
android:src="@drawable/icon_plus"
app:backgroundTint="@color/brand_green"
app:borderWidth="0dp"
app:elevation="@dimen/fac_icon_elevation"/>
</android.support.design.widget.CoordinatorLayout>
現在我像這樣展示 Snackbar
Snackbar.make(mRootView, "Something went wrong", Snackbar.LENGHT_SHORT)
.show();
當它顯示時,FAB 向上滑動,當它(在 LENGHT_SHORT 之后)消失時,FAB 向下滑動,一切正常。
但是,如果我將 Snackbar 滑開,FAB 會向下移動而不顯示幻燈片動畫。 它只是閃爍到初始位置。
有趣的是,如果 Snackbar 有兩行(不管它是否有動作)並且被滑動, FAB 會使用通常的幻燈片動畫正確地返回到它的位置。
這是android.support.design.widget.CoordinatorLayout
或android.support.design.widget.FloatingActionButton
中的錯誤嗎? 有什么解決方法嗎?
不使用基於Matteo Destro 帖子的ValueAnimator
的 Kotlin 解決方案:
class SnackBarAwareBehavior : CoordinatorLayout.Behavior<View> {
companion object {
private const val DURATION = 180
}
constructor() : super() {}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}
override fun layoutDependsOn(
parent: CoordinatorLayout,
child: View,
dependency: View
): Boolean {
return dependency is Snackbar.SnackbarLayout
}
override fun onDependentViewChanged(
parent: CoordinatorLayout,
child: View,
dependency: View
): Boolean {
if (dependency.visibility == View.VISIBLE) {
moveChildUp(child, dependency.height + dependency.marginBottom)
return true
}
return false
}
override fun onDependentViewRemoved(parent: CoordinatorLayout, child: View, dependency: View) {
moveChildToInitialPosition(child)
}
private fun moveChildUp(child: View, translation: Int) {
child.animate()
.translationY((-translation).toFloat())
.setInterpolator(DecelerateInterpolator())
.setDuration(DURATION.toLong())
.start()
}
private fun moveChildToInitialPosition(child: View) {
child.animate()
.translationY(0f)
.setInterpolator(AccelerateInterpolator())
.setDuration(DURATION.toLong())
.start()
}
}
我最近遇到了同樣的問題,我最終為 FAB 創建了一個自定義布局行為類,以便在輕掃小吃欄時執行動畫。
創建這個類:
public class SnackbarAwareBehavior extends CoordinatorLayout.Behavior<View> {
private static final int ANIMATION_DURATION = 180;
public SnackbarAwareBehavior() {
super();
}
public SnackbarAwareBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) {
return dependency instanceof Snackbar.SnackbarLayout;
}
@Override
public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) {
if (dependency.getVisibility() == View.VISIBLE) {
// Change the translation of the FAB only if the snackbar is visible
child.setTranslationY(dependency.getTranslationY() - getTranslationYBottom(dependency));
return true;
}
return false;
}
@Override
public void onDependentViewRemoved(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) {
if (dependency.getVisibility() == View.VISIBLE) {
child.setTranslationY(0f);
} else {
// Execute the animation only if the snackbar has been swiped away, i.e. when it's not visible
ValueAnimator animator = new ValueAnimator();
animator.setFloatValues(child.getTranslationY(), 0f);
animator.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR);
animator.setDuration(ANIMATION_DURATION);
animator.addUpdateListener(animation -> child.setTranslationY((float) animation.getAnimatedValue()));
animator.start();
}
}
private int getTranslationYBottom(View view) {
// Get the translation position of the snackbar when it's hidden.
// Method taken from BaseTransientBottomBar.Behavior class.
int translationY = view.getHeight();
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
translationY += ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin;
}
return translationY;
}
}
然后在您的布局中:
<android.support.design.widget.FloatingActionButton
...
app:layout_behavior="your.package.SnackbarAwareBehavior">
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.