如何在屏幕顶部显示Snackbar

时间:2015-07-31 12:31:42

标签: android android-snackbar

正如Android文档所说

  

Snackbars提供有关操作的轻量级反馈。它们在移动屏幕底部显示简短消息,在较大设备上显示左下方。

我们可以在屏幕顶部而不是底部显示snackbars吗?

现在我正在做这样的事情,在屏幕底部显示snackbar

Snackbar.make(findViewById(android.R.id.content), "Hello this is a snackbar!!!", 
Snackbar.LENGTH_LONG).setAction("Undo", mOnClickListener)
.setActionTextColor(Color.RED)
.show();

10 个答案:

答案 0 :(得分:153)

可以使用以下方法使小吃条显示在屏幕顶部:

Snackbar snack = Snackbar.make(parentLayout, str, Snackbar.LENGTH_LONG);
View view = snack.getView();
FrameLayout.LayoutParams params =(FrameLayout.LayoutParams)view.getLayoutParams();
params.gravity = Gravity.TOP;
view.setLayoutParams(params);
snack.show();

来自OP:

  

我不得不改变第一行:

Snackbar snack = Snackbar.make(findViewById(android.R.id.content), "Had a snack at Snackbar", Snackbar.LENGTH_LONG);

答案 1 :(得分:37)

CoordinatorLayout coordinatorLayout=(CoordinatorLayout)findViewById(R.id.coordinatorLayout);
Snackbar snackbar = Snackbar.make(coordinatorLayout, "Text", Snackbar.LENGTH_LONG);
View view = snackbar.getView();
CoordinatorLayout.LayoutParams params=(CoordinatorLayout.LayoutParams)view.getLayoutParams();
params.gravity = Gravity.TOP;
view.setLayoutParams(params);
snackbar.show();

答案 2 :(得分:11)

以上组合的解决方案:

final ViewGroup.LayoutParams params = snackbar.getView().getLayoutParams();
if (params instanceof CoordinatorLayout.LayoutParams) {
    ((CoordinatorLayout.LayoutParams) params).gravity = Gravity.TOP;
} else {
    ((FrameLayout.LayoutParams) params).gravity = Gravity.TOP;
}
snackbar.getView().setLayoutParams(params);

仍然受到动画不当的影响。

答案 3 :(得分:3)

您可以执行以下操作将SnackBar放置在布局内的任何位置(此方法没有动画问题

1)根据:

https://developer.android.com/reference/android/support/design/widget/Snackbar.html#make(android.view.View, java.lang.CharSequence, int)

  

小吃店制作(查看视图,                   字符序列文本,                   整数持续时间)

     

制作一个Snackbar以显示一条消息 Snackbar将尝试找到一个父视图来保存Snackbar的视图   查看的值。小吃店将走上视图树,试图   查找合适的父对象,该父对象定义为CoordinatorLayout或   窗口装饰的内容视图,以先到者为准。

因此,只需在所需位置添加Coordinator Layout并将该Coordinator Layout用作上述Snackbar.make方法中的view自变量,就可以将快餐栏放置在布局内的任何位置。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".MainActivity"
android:orientation="vertical"
android:id="@+id/rl"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">

<!-- Coordinator Layout used to position the SnackBar -->

<android.support.design.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/cl"
    android:layout_alignParentTop="true"
    android:background="@android:color/transparent">
</android.support.design.widget.CoordinatorLayout>

<!-- add your layout here -->

</RelativeLayout>

2)用于显示SnackBar的协调器布局应位于所有其他视图的顶部(最高海拔)。为此,您可以在协调器布局上调用bringToFront()或提升协调器布局(添加 例如android:elevation="10dp"

3)此时,snakeBar将显示在所需的位置,但以从底部到顶部的动画(默认行为)显示SnackBar。为了实现从上到下的动画,您可以执行以下操作:

  • 在Snackbar.make方法内部使用的旋转协调器布局为180度

4)在第3步之后,snakeBar将显示为从上到下的动画,但是消息和动作文本被旋转并且重力被反转,因此作为最后一步,我执行了以下操作:

  • 获得了SnackBar视图,找到了负责显示消息的TextView和负责操作的TextView的LinearLayout,并将父LinearLayout旋转了180度。

5)示例:

public class MainActivity extends AppCompatActivity {

private final String TAG = MainActivity.class.getSimpleName();
private RelativeLayout rl;
private CoordinatorLayout cl;
private CoordinatorLayout cl1;
private CoordinatorLayout cl2;
private CoordinatorLayout cl3;
private CoordinatorLayout cl4;
private Snackbar snackbar_updated;
private Snackbar snackbar_updated1;
private Snackbar snackbar_updated2;
private Snackbar snackbar_updated3;
private Snackbar snackbar_updated4;
private Snackbar snackbar_ordinary;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    rl = (RelativeLayout) findViewById(R.id.rl);
    cl = (CoordinatorLayout) findViewById(R.id.cl);
    cl1 = (CoordinatorLayout) findViewById(R.id.cl1);
    cl2 = (CoordinatorLayout) findViewById(R.id.cl2);
    cl3 = (CoordinatorLayout) findViewById(R.id.cl3);
    cl4 = (CoordinatorLayout) findViewById(R.id.cl4);
    cl.bringToFront();
    cl1.bringToFront();
    cl2.bringToFront();
    cl3.bringToFront();
    cl4.bringToFront();

    snackbar_updated = Snackbar.make(cl, "Message", Snackbar.LENGTH_INDEFINITE);
    snackbar_updated.setAction("Ok", new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });
    /** Snackbar message and action TextViews are placed inside a LinearLayout
     */
    final Snackbar.SnackbarLayout snackBarLayout = (Snackbar.SnackbarLayout) snackbar_updated.getView();
    for (int i = 0; i < snackBarLayout.getChildCount(); i++) {
        View parent = snackBarLayout.getChildAt(i);
        if (parent instanceof LinearLayout) {
            ((LinearLayout) parent).setRotation(180);
            break;
        }
    }

    snackbar_updated1 = Snackbar.make(cl1, "Message", Snackbar.LENGTH_INDEFINITE);
    snackbar_updated1.setAction("Ok", new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });
    /** Snackbar message and action TextViews are placed inside a LinearLayout
     */
    final Snackbar.SnackbarLayout snackBarLayout1 = (Snackbar.SnackbarLayout) snackbar_updated1.getView();
    for (int i = 0; i < snackBarLayout1.getChildCount(); i++) {
        View parent = snackBarLayout1.getChildAt(i);
        if (parent instanceof LinearLayout) {
            ((LinearLayout) parent).setRotation(180);
            break;
        }
    }

    snackbar_updated2 = Snackbar.make(cl2, "Message", Snackbar.LENGTH_INDEFINITE);
    snackbar_updated2.setAction("Ok", new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });

    snackbar_updated3 = Snackbar.make(cl3, "Message", Snackbar.LENGTH_INDEFINITE);
    snackbar_updated3.setAction("Ok", new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });
    /** Snackbar message and action TextViews are placed inside a LinearLayout
     */
    Snackbar.SnackbarLayout snackBarLayout3 = (Snackbar.SnackbarLayout) snackbar_updated3.getView();
    for (int i = 0; i < snackBarLayout3.getChildCount(); i++) {
        View parent = snackBarLayout3.getChildAt(i);
        if (parent instanceof LinearLayout) {
            ((LinearLayout) parent).setRotation(180);
            break;
        }
    }

    snackbar_updated4 = Snackbar.make(cl4, "Message", Snackbar.LENGTH_INDEFINITE);
    snackbar_updated4.setAction("Ok", new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });

    snackbar_ordinary = Snackbar.make(rl, "Message", Snackbar.LENGTH_INDEFINITE);
    snackbar_ordinary.setAction("Ok", new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });

    rl.post(new Runnable() {
        @Override
        public void run() {
            snackbar_updated.show();
            rl.postDelayed(new Runnable() {
                @Override
                public void run() {
                    snackbar_updated1.show();
                    rl.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            snackbar_updated2.show();
                            rl.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    snackbar_updated3.show();
                                    rl.postDelayed(new Runnable() {
                                        @Override
                                        public void run() {
                                            snackbar_updated4.show();
                                            rl.postDelayed(new Runnable() {
                                                @Override
                                                public void run() {
                                                    snackbar_ordinary.show();
                                                }
                                            }, 2000);
                                        }
                                    }, 2000);
                                }
                            }, 2000);
                        }
                    }, 2000);
                }
            }, 2000);
        }
    });

}

}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".MainActivity"
android:orientation="vertical"
android:id="@+id/rl"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">

<!-- Coordinator Layout used to position the SnackBar -->

<android.support.design.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/cl"
    android:rotation="180"
    android:layout_alignParentTop="true"
    android:background="@android:color/transparent">
</android.support.design.widget.CoordinatorLayout>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentTop="true"
    android:orientation="vertical">

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fitsSystemWindows="true">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:itemIconTint="#333"
        app:itemTextColor="#333"
        app:layout_collapseMode="pin"
        app:layout_scrollFlags="scroll|enterAlways"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Dark"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

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

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_below="@id/appbar"
        android:layout_gravity="bottom">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:id="@+id/tv_top"
            android:text="Layout Top"
            android:gravity="center"
            android:textSize="15sp"
            android:textColor="@android:color/white"
            android:layout_alignParentTop="true"
            android:background="@color/colorAccent">
        </TextView>

        <!-- Coordinator Layout used to position the SnackBar -->

        <android.support.design.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/cl1"
            android:rotation="180"
            android:layout_below="@id/tv_top"
            android:background="@android:color/transparent">
        </android.support.design.widget.CoordinatorLayout>


        <!-- Coordinator Layout used to position the SnackBar -->

        <android.support.design.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/cl2"
            android:paddingBottom="75dp"
            android:layout_centerInParent="true"
            android:background="@android:color/transparent">
        </android.support.design.widget.CoordinatorLayout>

        <!-- Coordinator Layout used to position the SnackBar -->

        <TextView
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:id="@+id/tv_center"
            android:text="Center"
            android:gravity="center"
            android:textSize="15sp"
            android:layout_centerInParent="true"
            android:textColor="@android:color/white"
            android:background="@color/colorAccent">
        </TextView>

        <android.support.design.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/cl3"
            android:rotation="180"
            android:paddingBottom="75dp"
            android:layout_centerInParent="true"
            android:background="@android:color/transparent">
        </android.support.design.widget.CoordinatorLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:id="@+id/tv_bottom"
            android:text="Layout Bottom"
            android:gravity="center"
            android:textSize="15sp"
            android:textColor="@android:color/white"
            android:layout_alignParentBottom="true"
            android:background="@color/colorAccent">
        </TextView>

        <!-- Coordinator Layout used to position the SnackBar -->

        <android.support.design.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/cl4"
            android:layout_above="@id/tv_bottom"
            android:background="@android:color/transparent">
        </android.support.design.widget.CoordinatorLayout>


    </RelativeLayout>

</RelativeLayout>

</RelativeLayout>

6)结果:

result

答案 4 :(得分:1)

Kotlin-

    val snackBarView = Snackbar.make(view, "SnackBar Message" , Snackbar.LENGTH_LONG)
    val view = snackBarView.view
    val params = view.layoutParams as FrameLayout.LayoutParams
    params.gravity = Gravity.TOP
    view.layoutParams = params
    view.background = ContextCompat.getDrawable(context,R.drawable.custom_drawable) // for custom background
    snackBarView.animationMode = BaseTransientBottomBar.ANIMATION_MODE_FADE
    snackBarView.show()

snackBarView.animationMode = BaseTransientBottomBar.ANIMATION_MODE_FADE

上一行将解决动画问题。

替代解决方案- snackBarView.anchorView =要在其上面显示SnackBar的人提及viewId

答案 5 :(得分:1)

这使Snackbar出现在顶部,而不会出现奇怪的幻灯片。

科特林最好的简单解决方案:

public function login(Request $request)
{

if(Auth::attempt($credentials))
{
 $userid = auth()->user()->id;
}

}

答案 6 :(得分:1)

在显示快餐栏之前,请添加以下代码

View snackbarView = snackbar.getView();

FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) snackbarView.getLayoutParams();
params.gravity = Gravity.TOP;
snackbarView.setLayoutParams(params);
snackbarView.startAnimation(AnimationUtils.loadAnimation(host, R.anim.slide_in_snack_bar));

当dismiss()时

View snackbarView = snackbar.getView();
  
snackbarView.startAnimation(AnimationUtils.loadAnimation(_snackbar.getContext(), R.anim.slide_out_snack_bar));
snackbar.dismiss()

slide_in_snack_bar.xml

<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_longAnimTime"
android:fromYDelta="-100%p"
android:toYDelta="0%p" />

slide_out_snack_bar.xml

<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_longAnimTime"
android:fromYDelta="0%p"
android:toYDelta="-100%p" />

答案 7 :(得分:0)

2年后,这是我的解决方法。

设置顶部和底部边距会改变效果结果,...我已尝试添加尽可能多的自定义选项,覆盖动画是此处未编写的另一个选项。

感谢大家在几个问题上的回答...

{
    // usage for setSnackBar
    int view = R.id.toolbar;
    String snackMessage = "";
    boolean useAction = false;
    Runnable ifUseActionRunnable = null;
    String actionText = "";
    int leftMargin = 0;
    int topMargin = 0;
    int rightMargin = 0;
    int bottomMargin = 0;
    int backgroundColour = Color.BLACK;
    int textColor = Color.WHITE;
    int duration = Snackbar.LENGTH_LONG;
    setSnackBar(view, snackMessage, useAction, ifUseActionRunnable, actionText, leftMargin, topMargin, rightMargin, bottomMargin, backgroundColour, textColor, duration);

}

Snackbar snb;
public void setSnackBar(int targetView, String snackMessage, boolean useAction, final Runnable ifUseActionRunnable, String actionText , int leftMargin, int topMargin, int rightMargin, int bottomMargin, int backgroundColour, int textColor, int duration)
{
    snb = Snackbar.make(findViewById(targetView), snackMessage, duration);
    View view = snb.getView();
    view.setBackgroundColor(backgroundColour);
    snb.setActionTextColor(textColor);
    FrameLayout.LayoutParams params =(FrameLayout.LayoutParams)view.getLayoutParams();
    params.gravity =  Gravity.CENTER_HORIZONTAL | Gravity.TOP;
    params.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
    view.setLayoutParams(params);
    if (useAction)
    {
        snb.setAction(actionText, new View.OnClickListener(){
                @Override
                public void onClick(View p1)
                {
                    ifUseActionRunnable.run();

                }
            });
    }
    if (snb.isShown())
    {
        snb.dismiss();
        snb.show();
    }
    else
    {
        snb.show();
    }
}

答案 8 :(得分:0)

在屏幕顶部显示小食(kotlin)

// Custom snackbar : banner model
            val customSnackBar   = Snackbar.make(snackbar_id, "", Snackbar.LENGTH_INDEFINITE)

            val view = customSnackBar.view
            val params = view.layoutParams as CoordinatorLayout.LayoutParams
            params.gravity = Gravity.TOP
            view.layoutParams = params

            val layout           = customSnackBar.view as Snackbar.SnackbarLayout
            val customSnackView  = layoutInflater.inflate(R.layout.snackbar_banner, null)

            val actionButton1   = customSnackView.findViewById(R.id.action_button_1) as MaterialButton
            actionButton1.setOnClickListener {
                customSnackBar.dismiss()
            }
            val actionButton   = customSnackView.findViewById(R.id.action_button_2) as MaterialButton
            actionButton.setOnClickListener {
                customSnackBar.dismiss()
            }

            // We can also customize the above controls
            layout.setPadding(0, 0, 0, 0)
            layout.addView(customSnackView, 0)


            customSnackBar.show()

XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@android:color/white"
   >

    <TextView
        android:padding="16dp"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/snackbar_banner_message"
        android:textColor="@android:color/black"
        android:textSize="16sp" />

    <LinearLayout
        android:gravity="end"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:orientation="horizontal">

        <com.google.android.material.button.MaterialButton
            android:id="@+id/action_button_1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            android:layout_weight="1"
            android:background="@android:color/black"
            android:text="Close"
            style="@style/Widget.MaterialComponents.Button.TextButton"
           />

        <com.google.android.material.button.MaterialButton
            android:id="@+id/action_button_2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@android:color/black"
            android:text="Fix it"
            android:textStyle="bold"
            style="@style/Widget.MaterialComponents.Button.TextButton"
           />

    </LinearLayout>

</LinearLayout>

enter image description here

答案 9 :(得分:0)

如果您使用 Constraintlayoutas 作为根父级,在指南和 CoordinatorLayout 的帮助下,您可以尝试:

更改 Guideline 中的 layout_constraintGuide_end="Your bottom margin value" 值,如下例所示。

<androidx.coordinatorlayout.widget.CoordinatorLayout
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toBottomOf="@id/guideline3" />

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_end="150dp" />

在活动中,您可以将 CoordinatorLayout 作为小吃店的视图传递

mSnackBar = Snackbar.make(
            coordinator,
            getString(R.string.no_internet_connection),
            Snackbar.LENGTH_INDEFINITE
        )
        mSnackBar.show()