cómo personalizar el diseño de snackBar?

¿Hay algún método para cambiar el diseño de una snackBar a una vista personalizada?

Ahora viene en negro y podemos cambiar el color de fondo. Pero no sé la forma correcta de inflar un nuevo diseño y hacerlo como fondo de snackBars?

Gracias…

Snackbar no le permite establecer un diseño personalizado. Sin embargo, como Primoz990 sugirió que puede obtener la Vista de Snackbar. La función getView devuelve Snackbar.SnackbarLayout, que es un objeto LinearLayout horizontal cuyos elementos secundarios son una Vista de texto y un Botón. Para agregar su propia Vista a Snackbar, solo necesita ocultar el TextView y agregar su Vista a Snackbar.SnackbarLayout.

// Create the Snackbar Snackbar snackbar = Snackbar.make(containerLayout, "", Snackbar.LENGTH_LONG); // Get the Snackbar's layout view Snackbar.SnackbarLayout layout = (Snackbar.SnackbarLayout) snackbar.getView(); // Hide the text TextView textView = (TextView) layout.findViewById(android.support.design.R.id.snackbar_text); textView.setVisibility(View.INVISIBLE); // Inflate our custom view View snackView = mInflater.inflate(R.layout.my_snackbar, null); // Configure the view ImageView imageView = (ImageView) snackView.findViewById(R.id.image); imageView.setImageBitmap(image); TextView textViewTop = (TextView) snackView.findViewById(R.id.text); textViewTop.setText(text); textViewTop.setTextColor(Color.WHITE); //If the view is not covering the whole snackbar layout, add this line layout.setPadding(0,0,0,0); // Add the view to the Snackbar's layout layout.addView(snackView, 0); // Show the Snackbar snackbar.show(); 

Es posible partir de la revisión 25.1.0 de la Biblioteca de soporte de Android

I. Declare el diseño personalizado en su carpeta de valores / diseño.

      

Sugerencias:

  • Use los valores de @dimen/design_snackbar para que coincidan con las pautas de diseño del material.
  • Utilice ?attr/colorAccent para aplicar los cambios del Tema de aplicación a Snackbar.

II. Extender la clase BaseTransientBottomBar .

 public class final CustomSnackbar extends BaseTransientBottomBar { /** * Constructor for the transient bottom bar. * * @param parent The parent for this transient bottom bar. * @param content The content view for this transient bottom bar. * @param contentViewCallback The content view callback for this transient bottom bar. */ private CustomSnackbar(ViewGroup parent, View content, ContentViewCallback contentViewCallback) { super(parent, content, contentViewCallback); } } 

III. Agregar BaseTransientBottomBar.ContentViewCallback

 public class final CustomSnackbar ...{ ... private static class ContentViewCallback implements BaseTransientBottomBar.ContentViewCallback { // view inflated from custom layout private View content; public ContentViewCallback(View content) { this.content = content; } @Override public void animateContentIn(int delay, int duration) { // add custom *in animations for your views // eg original snackbar uses alpha animation, from 0 to 1 ViewCompat.setScaleY(content, 0f); ViewCompat.animate(content) .scaleY(1f).setDuration(duration) .setStartDelay(delay); } @Override public void animateContentOut(int delay, int duration) { // add custom *out animations for your views // eg original snackbar uses alpha animation, from 1 to 0 ViewCompat.setScaleY(content, 1f); ViewCompat.animate(content) .scaleY(0f) .setDuration(duration) .setStartDelay(delay); } } } 

IV. Agregar método para crear Snackbar con diseño personalizado y métodos para llenarlo.

 public class final CustomSnackbar ...{ ... public static CustomSnackbar make(ViewGroup parent, @Duration int duration) { // inflate custom layout LayoutInflater inflater = LayoutInflater.from(parent.getContext()); View content = inflater.inflate(R.layout.snackbar_view, parent, false); // create snackbar with custom view ContentViewCallback callback= new ContentViewCallback(content); CustomSnackbar customSnackbar = new CustomSnackbar(parent, content, callback); // Remove black background padding on left and right customSnackbar.getView().setPadding(0, 0, 0, 0); // set snackbar duration customSnackbar.setDuration(duration); return customSnackbar; } // set text in custom layout public CustomSnackbar setText(CharSequence text) { TextView textView = (TextView) getView().findViewById(R.id.snackbar_text); textView.setText(text); return this; } // set action in custom layout public CustomSnackbar setAction(CharSequence text, final OnClickListener listener) { Button actionView = (Button) getView().findViewById(R.id.snackbar_action); actionView.setText(text); actionView.setVisibility(View.VISIBLE); actionView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { listener.onClick(view); // Now dismiss the Snackbar dismiss(); } }); return this; } } 

V. Crear instancia de CustomSnackbar y llamar al método show() .

 CustomSnackbar customSnackbar = CustomSnackbar.make(rooView, CustomSnackbar.LENGTH_INDEFINITE); customSnackbar.setText("No network connection!"); customSnackbar.setAction("Retry", new View.OnClickListener() { @Override public void onClick(View v) { // handle click here } }); customSnackbar.show(); 

Vea más sobre Snackbar y su personalización en materialdoc.com

Código completo CustomSnackbar.class :

 import android.support.annotation.NonNull; import android.support.design.widget.BaseTransientBottomBar; import android.support.v4.view.ViewCompat; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; public class CustomSnackbar extends BaseTransientBottomBar { /** * Constructor for the transient bottom bar. * * @param parent The parent for this transient bottom bar. * @param content The content view for this transient bottom bar. * @param callback The content view callback for this transient bottom bar. */ private CustomSnackbar(ViewGroup parent, View content, ContentViewCallback callback) { super(parent, content, callback); } public static CustomSnackbar make(@NonNull ViewGroup parent, @Duration int duration) { final LayoutInflater inflater = LayoutInflater.from(parent.getContext()); final View content = inflater.inflate(R.layout.snackbar_view, parent, false); final ContentViewCallback viewCallback = new ContentViewCallback(content); final CustomSnackbar customSnackbar = new CustomSnackbar(parent, content, viewCallback); customSnackbar.getView().setPadding(0, 0, 0, 0); customSnackbar.setDuration(duration); return customSnackbar; } public CustomSnackbar setText(CharSequence text) { TextView textView = (TextView) getView().findViewById(R.id.snackbar_text); textView.setText(text); return this; } public CustomSnackbar setAction(CharSequence text, final View.OnClickListener listener) { Button actionView = (Button) getView().findViewById(R.id.snackbar_action); actionView.setText(text); actionView.setVisibility(View.VISIBLE); actionView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { listener.onClick(view); // Now dismiss the Snackbar dismiss(); } }); return this; } private static class ContentViewCallback implements BaseTransientBottomBar.ContentViewCallback { private View content; public ContentViewCallback(View content) { this.content = content; } @Override public void animateContentIn(int delay, int duration) { ViewCompat.setScaleY(content, 0f); ViewCompat.animate(content).scaleY(1f).setDuration(duration).setStartDelay(delay); } @Override public void animateContentOut(int delay, int duration) { ViewCompat.setScaleY(content, 1f); ViewCompat.animate(content).scaleY(0f).setDuration(duration).setStartDelay(delay); } } } 

La forma XML:

El archivo xml de diseño original que se utiliza para Snackbar es este archivo:

design_layout_snackbar_include.xml :

       

Por lo tanto, para anular este diseño , debe escribir su propio diseño con el mismo android:id s como en este y en su archivo refs.xml debe agregar esta línea:

  ....  @layout/my_layout_snackbar  ....  

La respuesta es: No personalices la Snackbar. No debe contener más elementos que un texto breve y una acción. Consulte las pautas de diseño de Google Material .

ACTUALIZACIÓN: Si de todos modos quieres personalizar el Snackbar aquí, es lo que he implementado en mi aplicación:

 //generate the snackbar Snackbar sb = Snackbar.make(rootView, snack.text, duration); //set te action button text color sb.setActionTextColor(mCurrentActivity.getResources().getColor(R.color.snack_text_action)); //Get the view of the snackbar View sbView = sb.getView(); //set background color sbView.setBackgroundColor(mCurrentActivity.getResources().getColor(backgroudResId)); //Get the textview of the snackbar text TextView textView = (TextView) sbView.findViewById(android.support.design.R.id.snackbar_text); //set text color textView.setTextColor(mCurrentActivity.getResources().getColor(R.color.snack_text)); //increase max lines of text in snackbar. default is 2. textView.setMaxLines(10); 

Nunca lo intenté, pero al obtener la vista raíz de Snackbar, puedes agregar nuevas vistas programáticamente a Snackbar.

Pruebe el siguiente código.

 Snackbar snackbar = Snackbar.make(container, "No Internet Connection", Snackbar.LENGTH_LONG); View sbView = snackbar.getView(); sbView.setBackgroundColor(ContextCompat.getColor(this, R.color.colorPrimary)); snackbar.show(); 

Nota:

contenedor – vista principal del diseño.

¡Lo intenté y funciona!

  View custom = LayoutInflater.from(this).inflate(R.layout.custom_view, null); snackbar.getView().setPadding(0,0,0,0); ((ViewGroup) snackbar.getView()).removeAllViews(); ((ViewGroup) snackbar.getView()).addView(custom); TextView textView = custom.findViewById(R.id.text); View button = custom.findViewById(R.id.button); textView.setText("Your text here"); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // do something } }); 

Puedes probar esta biblioteca. Este es un contenedor para snackbar predeterminado de Android. https://github.com/ChathuraHettiarachchi/CSnackBar

 Snackbar.with(this,null) .type(Type.SUCCESS) .message("Profile updated successfully!") .duration(Duration.SHORT) .show(); 

o incluso puedes usar tu propia vista,

 View view = getLayoutInflater().inflate(R.layout.custom_view, null); Snackbar.with(this,null) .type(Type.UPDATE) .contentView(view, 76) .duration(Duration.SHORT) .show(); 

Actualmente solo es problema con el diseño personalizado, necesitamos pasar la altura de la vista en dp como entrada

 private Snackbar showSnackbar() { // Create the Snackbar Snackbar snackbar = Snackbar.make(coordinatorLayout, "", length); // 15 is margin from all the sides for snackbar int marginFromSides = 15; float hei[![enter image description here][1]][1]ght = 100; //inflate view View snackView = getLayoutInflater().inflate(R.layout.snackbar_layout, null); // White background snackbar.getView().setBackgroundColor(Color.WHITE); // for rounded edges snackbar.getView().setBackground(getResources().getDrawable(R.drawable.round_edges)); Snackbar.SnackbarLayout snackBarView = (Snackbar.SnackbarLayout) snackbar.getView(); FrameLayout.LayoutParams parentParams = (FrameLayout.LayoutParams) snackBarView.getLayoutParams(); parentParams.setMargins(marginFromSides, 0, marginFromSides, marginFromSides); parentParams.height = (int) height; parentParams.width = FrameLayout.LayoutParams.MATCH_PARENT; snackBarView.setLayoutParams(parentParams); snackBarView.addView(snackView, 0); return snackbar; } final Snackbar snackbar = showSnackbar(mainLayout, 90, Snackbar.LENGTH_LONG, R.layout.snackbar_layout); snackbar.show(); View view = snackbar.getView(); TextView tv = (TextView) view.findViewById(R.id.snackbar_action); tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { snackbar.dismiss(); } }); 

Para agregar a la respuesta de Yakiv Mospan, para hacer que su BaseTransientBottomBar personalizada se muestre desde la parte inferior como una Snackbar , copie este método de la clase Snackbar para encontrar un padre adecuado para el constructor BaseTransientBottomBar .

 private static ViewGroup findSuitableParent(View view) { ViewGroup fallback = null; do { if (view instanceof CoordinatorLayout) { // We've found a CoordinatorLayout, use it return (ViewGroup) view; } else if (view instanceof FrameLayout) { if (view.getId() == android.R.id.content) { // If we've hit the decor content view, then we didn't find a CoL in the // hierarchy, so use it. return (ViewGroup) view; } else { // It's not the content view but we'll use it as our fallback fallback = (ViewGroup) view; } } if (view != null) { // Else, we will loop and crawl up the view hierarchy and try to find a parent final ViewParent parent = view.getParent(); view = parent instanceof View ? (View) parent : null; } } while (view != null); // If we reach here then we didn't find a CoL or a suitable content view so we'll fallback return fallback; }