如何像在FloatingButton中一样移动Snackbar上方的视图

Ily*_*man 40 android android-snackbar

当Snackbar出现时,我想要一个线性布局.

我看到了很多关于如何使用FloatingButton执行此操作的示例,但是常规视图呢?

Tra*_*llo 70

我将详细阐述已批准的答案,因为我认为实施的内容比该文章提供的稍微简单一些.

我无法找到处理通用视图移动的内置行为,但这个是一个很好的通用选项(来自http://alisonhuang-blog.logdown.com/posts/290009-design-support -library-coordinator-layout-and-behavior链接在另一个评论中):

import android.content.Context;
import android.support.annotation.Keep;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;

@Keep
public class MoveUpwardBehavior extends CoordinatorLayout.Behavior<View> {

    public MoveUpwardBehavior() {
        super();
    }

    public MoveUpwardBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        return dependency instanceof Snackbar.SnackbarLayout;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
        float translationY = Math.min(0, ViewCompat.getTranslationY(dependency) - dependency.getHeight());
        ViewCompat.setTranslationY(child, translationY);
        return true;
    }

    //you need this when you swipe the snackbar(thanx to ubuntudroid's comment)
    @Override
    public void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) {
        ViewCompat.animate(child).translationY(0).start();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,在您的布局文件中添加layout_behavior,如下所示:

<LinearLayout
    android:id="@+id/main_content"
    android:orientation="vertical"
    app:layout_behavior="com.example.MoveUpwardBehavior"/>
Run Code Online (Sandbox Code Playgroud)

其中layout_behavior是自定义行为的完整路径.除非您特别需要具有默认行为,否则不需要将LinearLayout子类化,这似乎并不常见.

  • 这个解决方案不需要子类化目标视图,我认为这是过度的.此外,通常最好的做法是内联解释答案,因为链接往往会在一段时间后消失. (12认同)
  • 好的解决方案 为了支持快餐到消除小吃吧,请添加以下代码:`@Override public void onDependentViewRemoved(CoordinatorLayout parent,View child,View dependency){super.onDependentViewRemoved(parent,child,dependency); child.setTranslationY(0); }` (8认同)
  • 如果你想要一个依赖视图的实际动画,请使用`child.animate().translationY(0)`而不是`child.setTranslation(0)`. (4认同)
  • 同样重要的是,`Snackbar.make(..)`传递一个`View`,即`CoordinatorLayout`或`CoordinatorLayout`的子节点.出于某种原因,我传递了`getRootView()`,这使得`layoutDependsOn(..)`永远不会返回true. (4认同)
  • `ViewCompat.getTranslationY(dependency)` 现在已弃用,请改用 `dependency.getTranslationY()`;同样使用`child.setTranslationY(translationY)` (2认同)

lig*_*igi 16

您需要向LinearLayout添加行为并将其嵌入CoordinatorLayout中.你可能想读这个:http://alisonhuang-blog.logdown.com/posts/290009-design-support-library-coordinator-layout-and-behavior


Ali*_*zaa 16

基于@Travis Castillo的回答.修复了以下问题:

import android.content.Context;
import android.support.annotation.Keep;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;

@Keep
public class MoveUpwardBehavior extends CoordinatorLayout.Behavior<View> {

    public MoveUpwardBehavior() {

        super();

    }

    public MoveUpwardBehavior(Context context, AttributeSet attrs) {

        super(context, attrs);

    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {

        return dependency instanceof Snackbar.SnackbarLayout;

    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {

        float translationY = Math.min(0, ViewCompat.getTranslationY(dependency) - dependency.getHeight());

        //Dismiss last SnackBar immediately to prevent from conflict when showing SnackBars immediately after eachother
        ViewCompat.animate(child).cancel();

        //Move entire child layout up that causes objects on top disappear
        ViewCompat.setTranslationY(child, translationY);

        //Set top padding to child layout to reappear missing objects
        //If you had set padding to child in xml, then you have to set them here by <child.getPaddingLeft(), ...>
        child.setPadding(0, -Math.round(translationY), 0, 0);

        return true;
    }

    @Override
    public void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) {

        //Reset paddings and translationY to its default
        child.setPadding(0, 0, 0, 0);
        ViewCompat.animate(child).translationY(0).start();

    }
}
Run Code Online (Sandbox Code Playgroud)

所以这里是MoveUpwardBehavior类的固定代码:

@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
    float translationY = Math.min(0, ViewCompat.getTranslationY(dependency) - dependency.getHeight());

    //Dismiss last SnackBar immediately to prevent from conflict when showing SnackBars immediately after eachother
    ViewCompat.animate(child).cancel();

    //Padding from bottom instead pushing top and padding from top.
    //If you had set padding to child in xml, then you have to set them here by <child.getPaddingLeft(), ...>
    child.setPadding(0, 0, 0, -Math.round(translationY));

    return true;
}
Run Code Online (Sandbox Code Playgroud)

此代码会提升用户在屏幕上看到的内容,此外,当SnackBar显示时,用户还可以访问布局中的所有对象.

如果您希望SnackBar覆盖对象而不是推送,除了用户可以访问所有对象,那么您需要更改onDependentViewChanged方法:

@Override
public void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) {

    //Reset paddings and translationY to its default
    child.setPadding(0, 0, 0, 0);

}
Run Code Online (Sandbox Code Playgroud)

和方法onDependentViewRemoved:

import android.content.Context;
import android.support.annotation.Keep;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;

@Keep
public class MoveUpwardBehavior extends CoordinatorLayout.Behavior<View> {

    public MoveUpwardBehavior() {

        super();

    }

    public MoveUpwardBehavior(Context context, AttributeSet attrs) {

        super(context, attrs);

    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {

        return dependency instanceof Snackbar.SnackbarLayout;

    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {

        float translationY = Math.min(0, ViewCompat.getTranslationY(dependency) - dependency.getHeight());

        //Dismiss last SnackBar immediately to prevent from conflict when showing SnackBars immediately after eachother
        ViewCompat.animate(child).cancel();

        //Move entire child layout up that causes objects on top disappear
        ViewCompat.setTranslationY(child, translationY);

        //Set top padding to child layout to reappear missing objects
        //If you had set padding to child in xml, then you have to set them here by <child.getPaddingLeft(), ...>
        child.setPadding(0, -Math.round(translationY), 0, 0);

        return true;
    }

    @Override
    public void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) {

        //Reset paddings and translationY to its default
        child.setPadding(0, 0, 0, 0);
        ViewCompat.animate(child).translationY(0).start();

    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,当用户滑动以删除SnackBar时,您将丢失动画.并且你必须使用ValueAnimator类来为填充更改制作动画,这会在这里产生一些冲突,你必须调试它们.

https://developer.android.com/reference/android/animation/ValueAnimator.html

任何关于滑动动画的评论,以删除SnackBar赞赏.

如果您可以跳过该动画,那么您可以使用它.

无论如何,我推荐第一种类型.