Existe-t-il une méthode permettant de modifier la présentation d'un snackBar en vue personnalisée?
Maintenant, il vient en noir et nous pouvons changer la couleur de fond. Mais je ne connais pas la bonne façon de gonfler une nouvelle mise en page et de la transformer en arrière-plan de snackBars?
Merci...
La Snackbar ne vous permet pas de définir une disposition personnalisée. Cependant, comme Primoz990 l'a suggéré, vous pouvez obtenir la vue de la barre de coupe. La fonction getView renvoie l'objet Snackbar.SnackbarLayout, qui est un objet LinearLayout horizontal dont les enfants sont un TextView et un Button. Pour ajouter votre propre vue à la barre, il vous suffit de masquer la vue TextView et d'ajouter votre vue à la barre 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();
Il est possible à partir de révision 25.1.0 de Android Bibliothèque de support
I. Déclarez la disposition personnalisée dans votre dossier de valeurs/disposition.
_<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="horizontal"
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<Button
Android:id="@+id/snackbar_action"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_marginLeft="@dimen/design_snackbar_extra_spacing_horizontal"
Android:layout_marginStart="@dimen/design_snackbar_extra_spacing_horizontal"
Android:layout_gravity="center_vertical|right|end"
Android:paddingTop="@dimen/design_snackbar_padding_vertical"
Android:paddingBottom="@dimen/design_snackbar_padding_vertical"
Android:paddingLeft="@dimen/design_snackbar_padding_horizontal"
Android:paddingRight="@dimen/design_snackbar_padding_horizontal"
Android:visibility="gone"
Android:textColor="?attr/colorAccent"
style="?attr/borderlessButtonStyle"/>
<TextView
Android:gravity="center_vertical|right"
Android:id="@+id/snackbar_text"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_weight="1"
Android:paddingTop="@dimen/design_snackbar_padding_vertical"
Android:paddingBottom="@dimen/design_snackbar_padding_vertical"
Android:paddingLeft="@dimen/design_snackbar_padding_horizontal"
Android:paddingRight="@dimen/design_snackbar_padding_horizontal"
Android:textAppearance="@style/TextAppearance.Design.Snackbar.Message"
Android:maxLines="@integer/design_snackbar_text_max_lines"
Android:layout_gravity="center_vertical|left|start"
Android:ellipsize="end"/>
</LinearLayout>
_
Conseils:
@dimen/design_snackbar
_ pour faire correspondre les directives de conception des matériaux. ?attr/colorAccent
_ pour appliquer vos modifications de thème d'application à Snackbar. II. Étendre BaseTransientBottomBar classe.
_public class final CustomSnackbar extends BaseTransientBottomBar<CustomSnackbar> {
/**
* 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. Ajouter 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
// e.g. 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
// e.g. original snackbar uses alpha animation, from 1 to 0
ViewCompat.setScaleY(content, 1f);
ViewCompat.animate(content)
.scaleY(0f)
.setDuration(duration)
.setStartDelay(delay);
}
}
}
_
IV Ajouter une méthode pour créer une barre avec une mise en page personnalisée et des méthodes pour la remplir.
_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. Créez une instance de CustomSnackbar
et appelez la méthode 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();
_
En savoir plus sur Snackbar et sa personnalisation sur materialdoc.com
Code complet _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<CustomSnackbar> {
/**
* 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);
}
}
}
_
Le fichier XML de mise en page d'origine utilisé pour le fichier Snackbar
est le suivant:
design_layout_snackbar_include.xml
:_<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:Android="http://schemas.Android.com/apk/res/Android">
<TextView
Android:id="@+id/snackbar_text"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_weight="1"
...
Android:ellipsize="end"/>
<Button
Android:id="@+id/snackbar_action"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:visibility="gone"
...
Android:textColor="?attr/colorAccent"
style="?attr/borderlessButtonStyle"/>
</merge>
_
Donc, pour remplacer cette mise en page vous devez écrire votre propre mise en page avec les mêmes _Android:id
_s que dans celle-ci et dans votre fichier refs.xml
vous devriez ajoutez cette ligne:
_<resources xmlns:tools="http://schemas.Android.com/tools">
....
<item name="design_layout_snackbar_include" tools:override="true" type="layout">
@layout/my_layout_snackbar
</item>
....
</resources>
_
La réponse est: ne personnalisez pas la barre. Il ne doit pas contenir plus d'éléments qu'un texte court et une action. Voir Consignes de conception de Google Material .
MISE À JOUR: Si vous souhaitez quand même personnaliser la barre, voici ce que j'ai implémenté dans mon application:
//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);
Je n'ai jamais essayé, mais avec la vue racine de la barre, vous pouvez ajouter par programme de nouvelles vues à la barre.
private Snackbar showSnackbar(CoordinatorLayout coordinatorLayout, int duration) { // Create the Snackbar
Snackbar snackbar = Snackbar.make(coordinatorLayout, "", duration);
// 15 is margin from all the sides for snackbar
int marginFromSides = 15;
float height = 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;
}
Dans onCreate of the Activity:
CoordinatorLayout coordinatorLayout = findViewById(R.id.coordinator_layout);
final Snackbar snackbar = showSnackbar(coordinatorLayout, Snackbar.LENGTH_LONG);
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();
}
});
Je l'ai essayé et il fonctionne!
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
}
});
Essayez le code suivant.
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();
Note:
conteneur - vue parente de la mise en page.
Pour ajouter à la réponse de Yakiv Mospan, pour que votre nom personnalisé BaseTransientBottomBar
apparaisse comme un Snackbar
, copiez cette méthode à partir de la classe Snackbar
pour trouver un parent approprié pour le constructeur 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;
}
Vous pouvez essayer cette bibliothèque. Ceci est un emballage pour le snackbar par défaut Android. https://github.com/ChathuraHettiarachchi/CSnackBar
Snackbar.with(this,null)
.type(Type.SUCCESS)
.message("Profile updated successfully!")
.duration(Duration.SHORT)
.show();
ou vous pouvez même utiliser votre propre point de vue,
View view = getLayoutInflater().inflate(R.layout.custom_view, null);
Snackbar.with(this,null)
.type(Type.UPDATE)
.contentView(view, 76)
.duration(Duration.SHORT)
.show();
Actuellement, seul le problème avec la disposition personnalisée est, nous devons passer la hauteur de vue en dp en entrée.