Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make Snackbar push view upwards

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

snackbar

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?

like image 749
Simon Avatar asked Nov 14 '15 15:11

Simon


People also ask

How do I get view on snackbar?

make(parentlayout, "This is main activity", Snackbar. LENGTH_LONG) . setAction("CLOSE", new View. OnClickListener() { @Override public void onClick(View view) { } }) .

How do I use snackbar in service?

Import the snackBarService and inject it inside the constructor of the component, in which you want to use the Snackbar. This will create an instance of the service say snackBService. Now call the openSnackBar function wherever it is required, with the help of snackBService.

What is a snackbar in Android?

Snackbars provide lightweight feedback about an operation. They show a brief message at the bottom of the screen on mobile and lower left on larger devices. Snackbars appear above all other elements on screen and only one can be displayed at a time.


3 Answers

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.

like image 70
sourcerebels Avatar answered Oct 13 '22 19:10

sourcerebels


Short Answer: If all you want is to push the View upwards when the Snackbar shows up, just add the following line to your View. No need to define FloatingActionButtonBehavior anymore.

app:layout_dodgeInsetEdges="bottom"

Long Answer: FloatingActionButtonBehavior described in the accepted answer certainly gets the job done.

One thing I noticed is that, if I have a CoordinatorLayout and a real FloatingActionButton with no FloatingActionButtonBehavior, then the FAB feels slightly "bouncy" when the Snackbar shows up. But if I use something else, such as a ConstraintLayout along with FloatingActionButtonBehavior, then the "bouncy" feeling is just not there; the View above the Snackbar just shows up with enough space at the bottom for the Snackbar, and the Snackbar gradually fills the space. It's rather subtle, and I'm sure most people don't even notice it nor care about it.

This is when the Snackbar starts to show up. Notice that its size is slightly smaller than its full size.

enter image description here

And a fraction of a second later, the Snackbar "expands" to its full size.

enter image description here

This is what contributes to the "bouncy" feeling; FAB's location is based on the Snackbar's current size, not the Snackbar's fully shown size.

To replicate this behavior, just let FloatingActionButtonBehavior know where to anchor FAB, instead of calculating the Y coordinate yourself. Better yet, refer to "Short Answer".

/*
Replicate real FAB's behavior. Code shamelessly stolen from
com/google/android/material/floatingactionbutton/FloatingActionButton.java
*/
class FloatingActionButtonBehavior(
    context: Context,
    attrs: AttributeSet
) : CoordinatorLayout.Behavior<View>() {
    override fun onAttachedToLayoutParams(params: CoordinatorLayout.LayoutParams) {
        super.onAttachedToLayoutParams(params)

        if (params.dodgeInsetEdges == Gravity.NO_GRAVITY) {
            params.dodgeInsetEdges = Gravity.BOTTOM
        }
    }
}
like image 43
solamour Avatar answered Oct 13 '22 19:10

solamour


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
    }
}
like image 41
Ryan Newsom Avatar answered Oct 13 '22 19:10

Ryan Newsom