Make Snackbar push view upwards

2019-04-05 15:58发布

问题:

Is there a way to make the snackbar push the view upwards when it is shown?

Currently, when the snackbar is shown, it overlays the view below so it looks like half the button is cut off but I want it to almost "adjustPan" similar to the way that the softkeyboard works when it is shown on the screen.

Does anyone know of any tricks to achieve this?

回答1:

Put your view inside a android.support.design.CoordinatorLayout

<android.support.design.widget.CoordinatorLayout
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true">

    <View
        android:id="@+id/my_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_behavior="com.example.FloatingActionButtonBehavior"/>

</android.support.design.widget.CoordinatorLayout>

The important part here is app:layout_behavior attribute. Here is implementing class:

public class FloatingActionButtonBehavior extends CoordinatorLayout.Behavior<FloatingActionButton> {

    public FloatingActionButtonBehavior(Context context, AttributeSet attrs) {
    }

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

        return dependency instanceof SnackbarLayout;
    }

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

        float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
        child.setTranslationY(translationY);
        return true;
    }
}

Then when you show the snackbar pass the reference to the CoordinatorLayout:

CoordinatorLayout coordinator = findViewById(R.id.coordinator);
Snackbar.make(coordinator, textResId, Snackbar.LENGTH_LONG)
        .setAction(R.string.accept_ok, new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        })
        .setDuration(Snackbar.LENGTH_INDEFINITE)
        .show();

Hope this will help you.



回答2:

Snackbar will find closest CoordinatorLayout as parentView;

 findViewById(R.id.tv_main).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(findViewById(R.id.tv_main), "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
            toolbar.getChildAt(1).setVisibility(View.GONE);
        }
    });

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
    android:text="s"
    android:layout_weight="1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_marginBottom="200dp"
        android:layout_height="100dp">
        <TextView
            android:id="@+id/tv_main"
            android:background="#4b14b1"
            android:layout_width="100dp"
            android:layout_height="100dp" />
    </android.support.design.widget.CoordinatorLayout>
</RelativeLayout>


回答3:

He is SourceRebeles solution using generics in Kotlin.

typealias T = View

class FloatingActionButtonBehavior(context: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior<T>() {

    override fun layoutDependsOn(parent: CoordinatorLayout, child: T, dependency: View): Boolean {

        return dependency is SnackbarLayout
    }

    override fun onDependentViewChanged(parent: CoordinatorLayout, child: T, dependency: View): Boolean {

        val translationY = Math.min(0.0f, (dependency.translationY - dependency.height).toFloat())
        child.translationY = translationY
        return true
    }
}