En Android, ¿cómo configuro los márgenes en dp mediante programación?

402

En este , este y este hilo intenté encontrar una respuesta sobre cómo establecer los márgenes en una sola vista. Sin embargo, me preguntaba si no hay una manera más fácil. Explicaré por qué preferiría no usar este enfoque:

Tengo un botón personalizado que extiende el botón. Si el fondo se establece en algo más que el fondo por defecto (ya sea llamando setBackgroundResource(int id)o setBackgroundDrawable(Drawable d)), quiero que los márgenes sean 0. Si llamo a esto:

public void setBackgroundToDefault() {
    backgroundIsDefault = true;
    super.setBackgroundResource(android.R.drawable.btn_default);
    // Set margins somehow
}

Quiero que los márgenes se restablezcan a -3dp (ya leí aquí cómo convertir de píxeles a dp, así que una vez que sepa cómo configurar los márgenes en px, puedo gestionar la conversión yo mismo). Pero como esto se llama en la CustomButtonclase, el padre puede variar de LinearLayout a TableLayout, y prefiero que no obtenga a su padre y verifique la instancia de ese padre. Eso también será bastante deficiente, me imagino.

Además, cuando llamo (usando LayoutParams) parentLayout.addView(myCustomButton, newParams), no sé si esto lo agrega a la posición correcta (sin embargo, no lo he intentado), diga el botón central de una fila de cinco.

Pregunta: ¿Hay alguna manera más fácil de establecer el margen de un solo botón mediante programación además de usar LayoutParams?

EDITAR: conozco la forma de LayoutParams, pero me gustaría una solución que evite manejar cada tipo de contenedor diferente:

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);
    }
}

Debido a que this.getLayoutParams();devuelve una ViewGroup.LayoutParams, que no tienen los atributos topMargin, bottomMargin, leftMargin, rightMargin. La instancia de mc que ve es solo una MarginContainerque contiene márgenes de desplazamiento (-3dp) y (oml, omr, omt, omb) y los márgenes originales (ml, mr, mt, mb).

stealthjong
fuente

Respuestas:

798

Debe usar LayoutParamspara configurar los márgenes de su botón:

LayoutParams params = new LayoutParams(
        LayoutParams.WRAP_CONTENT,      
        LayoutParams.WRAP_CONTENT
);
params.setMargins(left, top, right, bottom);
yourbutton.setLayoutParams(params);

Dependiendo de qué diseño esté usando, debe usar RelativeLayout.LayoutParamso LinearLayout.LayoutParams.

Y para convertir su medida dp a píxel, intente esto:

Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        yourdpmeasure, 
        r.getDisplayMetrics()
);
throrin19
fuente
152
¿Desde qué paquete debo importar ese LayoutParams en particular?
stealthjong
77
setMargins usó px y usarás dp, mi conversión es correcta: dp -> px para establecer el valor de margen correcto.
throrin19
66
@ChristiaandeJong RelativeLayout.LayoutParams
stoefln
16
Depende de su diseño actual. Si está en LinearLayout, use LinearLayout.LayoutParams. RelativeLayout.LayoutParams de lo contrario
throrin19
55
debe importar layoutParams que es su diseño principal, por ejemplo. <linearlayout><relativelayout> <gridlayout> y está trabajando con el diseño de cuadrícula. entonces, necesitas usar relativelayout.layoutparams
Sruit A.Suk
228

LayoutParams - ¡NO FUNCIONA! ! !

Necesita usar el tipo de: MarginLayoutParams

MarginLayoutParams params = (MarginLayoutParams) vector8.getLayoutParams();
params.width = 200; params.leftMargin = 100; params.topMargin = 200;

Ejemplo de código para MarginLayoutParams:

http://www.codota.com/android/classes/android.view.ViewGroup.MarginLayoutParams

Lyusten Elder
fuente
19
Correcto, pero no es necesario volver a configurarlo, los parámetros modificados se reflejan automáticamente. Por lo tanto, puede eliminar la línea: vector8.setLayoutParams (params);
Wirsing
Los LayaoutParams generalmente crean confusión al establecer el margen ... Entonces, este MarginLayoutParams es muy útil. Gracias
Atul Bhardwaj
44
usted necesita establecer LayoutParams (params) después de marcar los cambios
Leo Droidcoder
Encontré MarginLayoutParams como nueva clase hoy #Gracias.
Tushar Pandey
No funciona para la Buttonvista: ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) button.getLayoutParams()vuelvenull
Konstantin Konopko
119

La mejor manera:

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();
    }
}

Cómo llamar al método:

setMargins(mImageView, 50, 50, 50, 50);

Espero que esto te ayudará.

Hiren Patel
fuente
1
me enfrento a un problema cuando configuro setMargins (holder.vCenter, 0, 20, 0,0); como este su margen de licencia en ambos lados (arriba y abajo) ¿qué hay de malo con los parámetros anteriores?
Arbaz.in
1
Impresionante respuesta perfecta !! ¡¡Gracias!!
Sjd
33
int sizeInDP = 16;

int marginInDp = (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, sizeInDP, getResources()
                    .getDisplayMetrics());

Entonces

layoutParams = myView.getLayoutParams()
layoutParams.setMargins(marginInDp, marginInDp, marginInDp, marginInDp);
myView.setLayoutParams(layoutParams);

O

LayoutParams layoutParams = new LayoutParams...
layoutParams.setMargins(marginInDp, marginInDp, marginInDp, marginInDp);
myView.setLayoutParams(layoutParams);
sagits
fuente
15

Aquí está la respuesta todo en uno con actualizaciones recientes:

Paso 1, para actualizar el margen

La idea básica es obtener margen y luego actualizarlo. La actualización se aplicará automáticamente y no necesita volver a configurarla. Para obtener los parámetros de diseño, simplemente llame a este método:

LayoutParams layoutParams = (LayoutParams) yourView.findViewById(R.id.THE_ID).getLayoutParams();

El LayoutParamsviene del diseño de su vista. Si la vista es de un diseño lineal, debe importar LinearLayout.LayoutParams. Si usa diseño relativo, importación LinearLayout.LayoutParams, etc.

Ahora, si se establece el margen usando Layout_marginLeft, Right, etc, es necesario margen de actualización de esta manera

layoutParams.setMargins(left, top, right, bottom);

Si configura el margen usando el nuevo layout_marginStart, debe actualizar el margen de esta manera

layoutParams.setMarginStart(start);
layoutParams.setMarginEnd(end);

Paso 2, para actualizar el margen en dp

Las dos formas de actualizar el margen anterior se actualizan en píxeles. Necesita hacer una traducción de dp a píxeles.

float dpRatio = context.getResources().getDisplayMetrics().density;
int pixelForDp = (int)dpValue * dpRatio;

Ahora coloque el valor calculado en las funciones de actualización de margen anteriores y debería estar todo listo

Colmillo
fuente
9

layout_margin es una restricción que una vista secundaria le dice a su padre. Sin embargo, es el papel de los padres elegir si se permite el margen o no. Básicamente, al configurar android: layout_margin = "10dp", el niño está pidiendo al grupo de vista principal que asigne un espacio que es 10dp más grande que su tamaño real. (padding = "10dp", por otro lado, significa que la vista secundaria hará que su propio contenido sea 10dp más pequeño ).

En consecuencia, no todos los grupos de vista respetan el margen . El ejemplo más notorio sería la vista de lista, donde se ignoran los márgenes de los elementos. Antes de llamar setMargin()a un LayoutParam, siempre debe asegurarse de que la vista actual esté en un ViewGroup que admita márgenes (por ejemplo, LinearLayouot o RelativeLayout), y envíe el resultado getLayoutParams()a los LayoutParams específicos que desee. (¡ ViewGroup.LayoutParamsNi siquiera tiene setMargins()método!)

La siguiente función debería hacer el truco. Sin embargo, asegúrese de sustituir RelativeLayout por el tipo de vista principal.

private void setMargin(int marginInPx) {
    RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
    lp.setMargins(marginInPx,marginInPx, marginInPx, marginInPx);
    setLayoutParams(lp);
}
Ian Wong
fuente
9

Este método le permitirá establecer el margen en DP

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);
}

ACTUALIZAR

Puede cambiar el parámetro que se adapte a sus necesidades.

Neferpitou
fuente
8

En Kotlin se verá así:

val layoutParams = (yourView?.layoutParams as? MarginLayoutParams)
layoutParams?.setMargins(40, 40, 40, 40)
yourView?.layoutParams = layoutParams
Morozov
fuente
3

Cuando está en una vista personalizada, puede usar getDimensionPixelSize(R.dimen.dimen_value), en mi caso, agregué el margen en LayoutParams creado eninit método.

En 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);
    }
}
aldajo92
fuente
2

Puede usar este método y poner un dimen estático como 20 que convierte según su dispositivo

 public static int dpToPx(int dp) 
      {
          float scale = context.getResources().getDisplayMetrics().density;
       return (int) (dp * scale + 0.5f);
  }
Kawatra disidente
fuente
1

Use este método para establecer el margen 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();
    }
}

llama al método:

setMargins(linearLayout,5,0,5,0);
Ridwan Bin Sarwar
fuente
1

Para una configuración rápida de una línea, use

((LayoutParams) cvHolder.getLayoutParams()).setMargins(0, 0, 0, 0);

pero tenga cuidado con cualquier uso incorrecto de LayoutParams, ya que esto no tendrá una ifinstancia de declaración chech

Dasser Basyouni
fuente
1

Creé una función de extensión de Kotlin para aquellos de ustedes que podrían encontrarla útil.

Asegúrese de pasar en píxeles no dp. Feliz codificación :)

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 }
            }
}
David Kim
fuente
1

En mi ejemplo, estoy agregando un ImageView a un LinearLayout programáticamente. He configurado los márgenes superior e inferior para ImagerView. Luego, agregue ImageView a 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);
Rajeev Shetty
fuente
0

Como hoy, lo mejor es probablemente usar París , una biblioteca proporcionada por AirBnB.

Los estilos se pueden aplicar así:

Paris.style(myView).apply(R.style.MyStyle);

También admite la vista personalizada (si extiende una vista) mediante anotaciones:

@Styleable and @Style
sonique
fuente
0

Tienes que llamar

setPadding(int left, int top, int right, int bottom)

al igual que: your_view.setPadding(0,16,0,0)

Lo que está tratando de usar es solo el captador.

Android Studio muestra lo que padding...()realmente significa en Java:

ejemplo de relleno La imagen muestra que solo llamagetPadding...()

Si desea agregar un margen a su TextView, deberá LayoutParams:

val params =  LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT)
params.setMargins(int left, int top, int right, int bottom)
your_view.layoutParams = params
Saadat Sayem
fuente
-1
((FrameLayout.LayoutParams) linearLayout.getLayoutParams()).setMargins(450, 20, 0, 250);
        linearLayout.setBackgroundResource(R.drawable.smartlight_background);

Tuve que lanzar el mío FrameLayoutpara un diseño lineal ya que hereda de él y establecer márgenes allí para que la actividad aparezca solo en una parte de la pantalla junto con un fondo diferente al de los parámetros de diseño originales en el 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);

¡Ninguno de los otros trabajó para usar la misma actividad y cambiar los márgenes basados ​​en abrir la actividad desde un menú diferente! setLayoutParams nunca funcionó para mí: el dispositivo se bloqueaba cada vez. Aunque estos son números codificados, este es solo un ejemplo del código solo con fines de demostración.

Ali Mcnamara
fuente
-1

Puede usar ViewGroup.MarginLayoutParamspara establecer el ancho, la altura y los márgenes

ViewGroup.MarginLayoutParams marginLayoutParams = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
marginLayoutParams.setMargins(0,16,0,16);
linearLayout.setLayoutParams(marginLayoutParams);

Donde el método setMargins();toma valores para izquierda, arriba, derecha, abajo respectivamente. En el sentido de las agujas del reloj !, comenzando desde la izquierda.

mmmcho
fuente