Dans this , this et this thread, j’ai essayé de trouver une réponse sur la manière de définir les marges sur une seule vue. Cependant, je me demandais s'il n'y avait pas de moyen plus facile. Je vais expliquer pourquoi je préférerais ne pas utiliser cette approche:
J'ai un bouton personnalisé qui étend le bouton. Si l'arrière-plan est défini sur autre chose que l'arrière-plan par défaut (en appelant soit setBackgroundResource(int id)
ou setBackgroundDrawable(Drawable d)
), je souhaite que les marges soient égales à 0. Si j'appelle cela:
public void setBackgroundToDefault() {
backgroundIsDefault = true;
super.setBackgroundResource(Android.R.drawable.btn_default);
// Set margins somehow
}
Je veux que les marges se réinitialisent à -3dp (je lis déjà ici comment convertir des pixels en dp, donc une fois que je sais comment définir des marges en px, je peux gérer la conversion moi-même). Mais puisque ceci est appelé dans la classe CustomButton
, le parent peut varier de LinearLayout à TableLayout, et je préférerais qu'il ne récupère pas son parent et ne vérifie pas l'instance de ce parent. Ce sera aussi assez performant, j'imagine.
De plus, lors de l'appel (à l'aide de LayoutParams) parentLayout.addView(myCustomButton, newParams)
, je ne sais pas si cela l'ajoute à la position correcte (je n'ai pas essayé cependant), dites le bouton du milieu d'une rangée de cinq.
Question: Existe-t-il un moyen plus simple de définir la marge d’un bouton unique par programmation en plus de LayoutParams?
EDIT: Je connais la méthode LayoutParams, mais j'aimerais une solution qui évite de manipuler chaque type de conteneur différent:
ViewGroup.LayoutParams p = this.getLayoutParams();
if (p instanceof LinearLayout.LayoutParams) {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)p;
if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
this.setLayoutParams(lp);
}
else if (p instanceof RelativeLayout.LayoutParams) {
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)p;
if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
this.setLayoutParams(lp);
}
else if (p instanceof TableRow.LayoutParams) {
TableRow.LayoutParams lp = (TableRow.LayoutParams)p;
if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
this.setLayoutParams(lp);
}
}
Parce que this.getLayoutParams();
renvoie un ViewGroup.LayoutParams
, qui ne possède pas les attributs topMargin
, bottomMargin
, leftMargin
, rightMargin
. L'instance mc que vous voyez est simplement une MarginContainer
qui contient offset (-3dp) margin et (oml, omr, omt, omb) les marges d'origine (ml, mr, mt, mb).
Vous devez utiliser LayoutParams
pour définir les marges de vos boutons:
LayoutParams params = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT
);
params.setMargins(left, top, right, bottom);
yourbutton.setLayoutParams(params);
Selon la disposition que vous utilisez, vous devez utiliser RelativeLayout.LayoutParams
ou LinearLayout.LayoutParams
.
Et pour convertir votre mesure dp en pixel, essayez ceci:
Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
yourdpmeasure,
r.getDisplayMetrics()
);
LayoutParams - ne fonctionne pas! ! !
Besoin d'utiliser type de: MarginLayoutParams
MarginLayoutParams params = (MarginLayoutParams) vector8.getLayoutParams();
params.width = 200; params.leftMargin = 100; params.topMargin = 200;
Exemple de code pour MarginLayoutParams:
http://www.codota.com/Android/classes/Android.view.ViewGroup.MarginLayoutParams
Le meilleur moyen de ma vie:
private void setMargins (View view, int left, int top, int right, int bottom) {
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
p.setMargins(left, top, right, bottom);
view.requestLayout();
}
}
Comment appeler la méthode:
setMargins(mImageView, 50, 50, 50, 50);
J'espère que ceci vous aidera.
int sizeInDP = 16;
int marginInDp = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, sizeInDP, getResources()
.getDisplayMetrics());
Ensuite
layoutParams = myView.getLayoutParams()
layoutParams.setMargins(marginInDp, marginInDp, marginInDp, marginInDp);
myView.setLayoutParams(layoutParams);
Ou
LayoutParams layoutParams = new LayoutParams...
layoutParams.setMargins(marginInDp, marginInDp, marginInDp, marginInDp);
myView.setLayoutParams(layoutParams);
Cette méthode vous permettra de définir la Marge inDP
public void setMargin(Context con,ViewGroup.LayoutParams params,int dp) {
final float scale = con.getResources().getDisplayMetrics().density;
// convert the DP into pixel
int pixel = (int)(dp * scale + 0.5f);
ViewGroup.MarginLayoutParams s =(ViewGroup.MarginLayoutParams)params;
s.setMargins(pixel,pixel,pixel,pixel);
yourView.setLayoutParams(params);
}
METTRE À JOUR
Vous pouvez modifier le paramètre qui convient à vos besoins.
layout_margin est une contrainte qu'un enfant de vue dit à son parent. Cependant, le rôle du parent est de choisir d'autoriser ou non la marge. Fondamentalement en définissant Android: layout_margin = "10dp", l’enfant demande au groupe de vues parent d’allouer un espace supérieur de 10dp à sa taille réelle. (padding = "10dp", par contre, signifie que la vue enfant réduira son propre contenu 10dp plus petit .)
Par conséquent, tous les ViewGroups ne respectent pas la marge . L'exemple le plus notoire serait listview, où les marges des éléments sont ignorées. Avant d'appeler setMargin()
vers un LayoutParam, vous devez toujours vous assurer que la vue actuelle réside dans un ViewGroup prenant en charge la marge (par exemple, LinearLayouot ou RelativeLayout) et transtyper le résultat de getLayoutParams()
vers le LayoutParams spécifique de votre choix. (ViewGroup.LayoutParams
n'a même pas de méthode setMargins()
!)
La fonction ci-dessous devrait faire l'affaire. Cependant, assurez-vous de substituer RelativeLayout au type de la vue parent.
private void setMargin(int marginInPx) {
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
lp.setMargins(marginInPx,marginInPx, marginInPx, marginInPx);
setLayoutParams(lp);
}
Étape 1, mettre à jour la marge
L'idée de base est d'obtenir une marge puis de la mettre à jour. La mise à jour sera appliquée automatiquement et vous n'avez pas besoin de la réinitialiser. Pour obtenir les paramètres de présentation, appelez simplement cette méthode:
LayoutParams layoutParams = (LayoutParams) yourView.findViewById(R.id.THE_ID).getLayoutParams();
La LayoutParams
provient de la disposition de votre vue. Si la vue provient d'une disposition linéaire, vous devez importer LinearLayout.LayoutParams
. Si vous utilisez une disposition relative, importez LinearLayout.LayoutParams
, etc.
Maintenant, si vous définissez la marge en utilisant Layout_marginLeft
, Right
, etc., vous devez mettre à jour la marge de cette manière.
layoutParams.setMargins(left, top, right, bottom);
Si vous définissez la marge à l'aide du nouveau layout_marginStart
, vous devez mettre à jour la marge de cette manière.
layoutParams.setMarginStart(start);
layoutParams.setMarginEnd(end);
Étape 2, mettre à jour la marge en dp
Les deux manières de mettre à jour la marge ci-dessus sont des mises à jour en pixels. Vous devez faire une traduction de dp en pixels.
float dpRatio = context.getResources().getDisplayMetrics().density;
int pixelForDp = (int)dpValue * dpRatio;
Maintenant, placez la valeur calculée sur les fonctions de mise à jour de la marge ci-dessus et vous devriez être tous ensemble
Lorsque vous êtes dans une vue personnalisée, vous pouvez utiliser getDimensionPixelSize(R.dimen.dimen_value)
; dans mon cas, j'ai ajouté la marge dans LayoutParams créée sur la méthode init
.
À Kotlin
init {
LayoutInflater.from(context).inflate(R.layout.my_layout, this, true)
layoutParams = LayoutParams(MATCH_PARENT, WRAP_CONTENT).apply {
val margin = resources.getDimensionPixelSize(R.dimen.dimen_value)
setMargins(0, margin, 0, margin)
}
en Java:
public class CustomView extends LinearLayout {
//..other constructors
public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
int margin = getResources().getDimensionPixelSize(R.dimen.spacing_dime);
params.setMargins(0, margin, 0, margin);
setLayoutParams(params);
}
}
Pour une installation rapide en une ligne, utilisez
((LayoutParams) cvHolder.getLayoutParams()).setMargins(0, 0, 0, 0);
mais faites attention à toute utilisation incorrecte de LayoutParams, car cela n'aura aucune instance if
Dans mon exemple, j'ajoute un ImageView à un programme LinearLayout. J'ai défini les marges supérieure et inférieure sur ImagerView. Ajoutez ensuite ImageView à LinearLayout.
ImageView imageView = new ImageView(mContext);
imageView.setImageBitmap(bitmap);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.setMargins(0, 20, 0, 40);
imageView.setLayoutParams(params);
linearLayout.addView(imageView);
Création d’une fonction d’extension Kotlin pour ceux qui le trouvent utile.
Assurez-vous de passer en pixels pas dp. Bonne codage :)
fun View.addLayoutMargins(left: Int? = null, top: Int? = null,
right: Int? = null, bottom: Int? = null) {
this.layoutParams = ViewGroup.MarginLayoutParams(this.layoutParams)
.apply {
left?.let { leftMargin = it }
top?.let { topMargin = it }
right?.let { rightMargin = it }
bottom?.let { bottomMargin = it }
}
}
Vous pouvez utiliser cette méthode et mettre dimen statique comme 20 il convertit en fonction de votre appareil
public static int dpToPx(int dp)
{
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
Comme aujourd’hui, le mieux est probablement d’utiliser Paris , une bibliothèque fournie par AirBnB.
Les styles peuvent ensuite être appliqués comme ceci:
Paris.style(myView).apply(R.style.MyStyle);
il prend également en charge la vue personnalisée (si vous étendez une vue) en utilisant des annotations:
@Styleable and @Style
Mis à jour:
Tout comme vous aviez l'habitude de régler la largeur et la hauteur de la mise en page avec ViewGroup.LayoutParams
Vous pouvez utiliser ViewGroup.MarginLayoutParams
pour définir la largeur, la hauteur et les marges, assez explicite, non?
ViewGroup.MarginLayoutParams marginLayoutParams = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
marginLayoutParams.setMargins(0,16,0,16);
linearLayout.setLayoutParams(marginLayoutParams);
Où la méthode setMargins();
prend respectivement les valeurs de gauche, haut, droite et bas. Dans le sens horaire !, en commençant par la gauche.
Utilisez cette méthode pour définir la marge en dp
private void setMargins (View view, int left, int top, int right, int bottom) {
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
final float scale = getBaseContext().getResources().getDisplayMetrics().density;
// convert the DP into pixel
int l = (int)(left * scale + 0.5f);
int r = (int)(right * scale + 0.5f);
int t = (int)(top * scale + 0.5f);
int b = (int)(bottom * scale + 0.5f);
p.setMargins(l, t, r, b);
view.requestLayout();
}
}
appelez la méthode:
setMargins(linearLayout,5,0,5,0);
((FrameLayout.LayoutParams) linearLayout.getLayoutParams()).setMargins(450, 20, 0, 250);
linearLayout.setBackgroundResource(R.drawable.smartlight_background);
J'ai dû attribuer le mien à FrameLayout
pour un linearLayout car il en hérite et y définir des marges afin que l'activité n'apparaisse que sur une partie de l'écran avec un arrière-plan différent de celui de la mise en page originale dans setContentView
.
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.activity);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(WindowManager.LayoutParams.FILL_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
linearLayout.setBackgroundColor(getResources().getColor(R.color.full_white));
setContentView(linearLayout,layoutParams);
Aucun des autres n'a travaillé pour utiliser la même activité et modifier les marges en fonction de l'ouverture de l'activité à partir d'un menu différent! setLayoutParams n'a jamais fonctionné pour moi - le périphérique plantait à chaque fois. Même s'il s'agit de nombres codés en dur, il ne s'agit que d'un exemple de code à des fins de démonstration uniquement.