In this , this und this thread habe ich versucht, eine Antwort zu finden, wie man die Ränder auf eine einzige Ansicht setzt. Ich habe mich jedoch gefragt, ob es keinen einfacheren Weg gibt. Ich erkläre, warum ich diesen Ansatz lieber nicht verwenden möchte:
Ich habe einen benutzerdefinierten Button, der den Button erweitert. Wenn der Hintergrund auf etwas anderes als den Standardhintergrund eingestellt ist (durch Aufruf von setBackgroundResource(int id)
oder setBackgroundDrawable(Drawable d)
), möchte ich, dass die Ränder 0 sind.
public void setBackgroundToDefault() {
backgroundIsDefault = true;
super.setBackgroundResource(Android.R.drawable.btn_default);
// Set margins somehow
}
Ich möchte, dass die Ränder auf -3dp zurückgesetzt werden (ich habe bereits hier wie ich von Pixeln in dp umwandeln kann. Sobald ich also weiß, wie man Ränder in px setzt, kann ich die Konvertierung selbst durchführen). Da dies jedoch in der CustomButton
-Klasse aufgerufen wird, kann das übergeordnete Element von LinearLayout bis TableLayout variieren, und ich möchte lieber nicht, dass er seinen Elternteil erhält und die Instanz dieses Elternteils überprüft. Das ist auch ziemlich unperformant, denke ich.
Wenn ich (mit LayoutParams) parentLayout.addView(myCustomButton, newParams)
anrufe, weiß ich nicht, ob dies an der richtigen Position hinzugefügt wird (habe es jedoch nicht versucht), sagen Sie die mittlere Taste einer Fünferreihe.
Frage: Gibt es eine einfachere Methode, um den Rand einer einzelnen Schaltfläche programmgesteuert festzulegen außer LayoutParams?
EDIT: Ich kenne den LayoutParams-Weg, möchte aber eine Lösung, die den Umgang mit den verschiedenen Containertypen vermeidet:
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);
}
}
Weil this.getLayoutParams();
einen ViewGroup.LayoutParams
zurückgibt, der nicht die Attribute topMargin
, bottomMargin
, leftMargin
, rightMargin
..__ besitzt. Die mc-Instanz, die Sie sehen, ist nur eine MarginContainer
, die Ränder (-3dp) und (oml, omr, omt, omb) und enthält die ursprünglichen Ränder (ml, mr, mt, mb).
Sie sollten LayoutParams
verwenden, um Ihre Schaltflächenränder festzulegen:
LayoutParams params = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT
);
params.setMargins(left, top, right, bottom);
yourbutton.setLayoutParams(params);
Abhängig vom verwendeten Layout sollten Sie RelativeLayout.LayoutParams
oder LinearLayout.LayoutParams
verwenden.
Versuchen Sie Folgendes, um Ihr DP-Maß in Pixel zu konvertieren:
Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
yourdpmeasure,
r.getDisplayMetrics()
);
LayoutParams - funktioniert nicht! ! !
Benötigen Sie die Verwendung von: MarginLayoutParams
MarginLayoutParams params = (MarginLayoutParams) vector8.getLayoutParams();
params.width = 200; params.leftMargin = 100; params.topMargin = 200;
Codebeispiel für MarginLayoutParams:
http://www.codota.com/Android/classes/Android.view.ViewGroup.MarginLayoutParams
Bester Weg überhaupt:
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();
}
}
So rufen Sie die Methode auf:
setMargins(mImageView, 50, 50, 50, 50);
Hoffe, das wird dir helfen.
int sizeInDP = 16;
int marginInDp = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, sizeInDP, getResources()
.getDisplayMetrics());
Dann
layoutParams = myView.getLayoutParams()
layoutParams.setMargins(marginInDp, marginInDp, marginInDp, marginInDp);
myView.setLayoutParams(layoutParams);
Oder
LayoutParams layoutParams = new LayoutParams...
layoutParams.setMargins(marginInDp, marginInDp, marginInDp, marginInDp);
myView.setLayoutParams(layoutParams);
Mit dieser Methode können Sie die Margin 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);
}
UPDATE
Sie können den Parameter ändern, der Ihren Bedürfnissen entspricht.
layout_margin ist eine Einschränkung, die ein View-Child seinem übergeordneten Element mitteilt. Es ist jedoch die Aufgabe des Elternteils, zu entscheiden, ob eine Marge zulässig ist oder nicht. Im Wesentlichen durch Festlegen von Android: layout_margin = "10dp" bittet das Kind die übergeordnete Ansichtsgruppe, Platz zuzuordnen, der 10dp größer ist als ihre tatsächliche Größe. (padding = "10dp" bedeutet dagegen, dass die untergeordnete Ansicht ihren eigenen Inhalt 10dp kleiner macht .)
Demzufolge respektieren nicht alle ViewGroups die Marge . Das notorischste Beispiel wäre die Listenansicht, bei der die Ränder von Elementen ignoriert werden. Bevor Sie setMargin()
für ein LayoutParam aufrufen, sollten Sie immer sicherstellen, dass sich die aktuelle Ansicht in einer ViewGroup befindet, die Ränder unterstützt (z. B. LinearLayouot oder RelativeLayout), und das Ergebnis von getLayoutParams()
in die gewünschten LayoutParams umwandeln. (ViewGroup.LayoutParams
hat nicht einmal die setMargins()
-Methode!)
Die Funktion unten sollte den Trick tun. Stellen Sie jedoch sicher, dass Sie RelativeLayout durch den Typ der übergeordneten Ansicht ersetzen.
private void setMargin(int marginInPx) {
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
lp.setMargins(marginInPx,marginInPx, marginInPx, marginInPx);
setLayoutParams(lp);
}
Schritt 1, um die Marge zu aktualisieren
Die Grundidee besteht darin, eine Marge herauszuholen und sie dann zu aktualisieren. Das Update wird automatisch angewendet und Sie müssen es nicht zurücksetzen. Um die Layoutparameter abzurufen, rufen Sie einfach diese Methode auf:
LayoutParams layoutParams = (LayoutParams) yourView.findViewById(R.id.THE_ID).getLayoutParams();
LayoutParams
ergibt sich aus dem Layout Ihrer Ansicht. Wenn die Ansicht von einem linearen Layout stammt, müssen Sie LinearLayout.LayoutParams
importieren. Wenn Sie ein relatives Layout verwenden, importieren Sie LinearLayout.LayoutParams
usw.
Wenn Sie jetzt den Rand mit Layout_marginLeft
, Right
usw. festlegen, müssen Sie den Rand auf diese Weise aktualisieren
layoutParams.setMargins(left, top, right, bottom);
Wenn Sie den Rand mit dem neuen layout_marginStart
setzen, müssen Sie den Rand auf diese Weise aktualisieren
layoutParams.setMarginStart(start);
layoutParams.setMarginEnd(end);
Schritt 2, um die Marge in dp zu aktualisieren
Alle zwei Möglichkeiten, die Marge zu aktualisieren, werden in Pixel aktualisiert. Sie müssen eine Übersetzung von dp in Pixel vornehmen.
float dpRatio = context.getResources().getDisplayMetrics().density;
int pixelForDp = (int)dpValue * dpRatio;
Setzen Sie nun den berechneten Wert auf die obigen Margenaktualisierungsfunktionen und Sie sollten alle Einstellungen vornehmen
Wenn Sie sich in einer benutzerdefinierten Ansicht befinden, können Sie getDimensionPixelSize(R.dimen.dimen_value)
verwenden. In meinem Fall habe ich den Rand in LayoutParams hinzugefügt, der mit der Methode init
erstellt wurde.
In 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)
}
in 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);
}
}
Für ein schnelles Einzeilen-Setup verwenden
((LayoutParams) cvHolder.getLayoutParams()).setMargins(0, 0, 0, 0);
seien Sie jedoch vorsichtig, wenn Sie LayoutParams falsch verwenden, da dies keine if
-Anweisungsinstanz gibt
In meinem Beispiel füge ich einem LinearLayout programmgesteuert ein ImageView hinzu. Ich habe den oberen und unteren Rand von ImagerView festgelegt. Fügen Sie dann die ImageView zum LinearLayout hinzu.
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);
Es wurde eine Kotlin-Erweiterungsfunktion für diejenigen unter Ihnen erstellt, die es vielleicht nützlich finden.
Stellen Sie sicher, dass Sie Pixel eingeben, die nicht dp sind. Fröhliches Codieren :)
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 }
}
}
Sie können diese Methode verwenden und statische Dimensionen wie 20 setzen, die es entsprechend Ihrem Gerät konvertiert
public static int dpToPx(int dp)
{
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
Wie heute ist es wahrscheinlich am besten, die von AirBnB bereitgestellte Bibliothek Paris zu verwenden.
Styles können dann wie folgt angewendet werden:
Paris.style(myView).apply(R.style.MyStyle);
es unterstützt auch die benutzerdefinierte Ansicht (wenn Sie eine Ansicht erweitern) mithilfe von Anmerkungen:
@Styleable and @Style
Aktualisierte:
So wie Sie früher die Breite und Höhe des Layouts mit ViewGroup.LayoutParams
eingestellt haben
Sie können ViewGroup.MarginLayoutParams
verwenden, um Breite, Höhe und Ränder einzustellen, ziemlich selbsterklärend, oder?
ViewGroup.MarginLayoutParams marginLayoutParams = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
marginLayoutParams.setMargins(0,16,0,16);
linearLayout.setLayoutParams(marginLayoutParams);
Wobei die Methode setMargins();
Werte für left, top, right, bottom akzeptiert. Im Uhrzeigersinn !, beginnend von links.
Verwenden Sie diese Methode, um den Rand in dp einzustellen
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();
}
}
rufen Sie die Methode auf:
setMargins(linearLayout,5,0,5,0);
((FrameLayout.LayoutParams) linearLayout.getLayoutParams()).setMargins(450, 20, 0, 250);
linearLayout.setBackgroundResource(R.drawable.smartlight_background);
Ich musste meins in FrameLayout
für ein linearesLayout umwandeln, da es davon erbt und dort Ränder setzt, sodass die Aktivität nur auf einem Teil des Bildschirms mit einem anderen Hintergrund als den ursprünglichen Layoutparametern in setContentView
angezeigt wird.
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);
Keiner der anderen hat dafür gearbeitet, dieselbe Aktivität zu verwenden und die Ränder basierend auf dem Öffnen der Aktivität aus einem anderen Menü zu ändern! setLayoutParams hat für mich nie funktioniert - das Gerät würde jedes Mal abstürzen. Auch wenn es sich hierbei um fest codierte Zahlen handelt - dies ist nur ein Beispiel des Codes nur zu Demonstrationszwecken.