No Android, como faço para definir margens no dp programaticamente?

401

No presente , este e este segmento Tentei encontrar uma resposta sobre como definir as margens em um único ponto de vista. No entanto, eu queria saber se não há uma maneira mais fácil. Vou explicar por que preferiria não usar essa abordagem:

Eu tenho um botão personalizado que estende o botão. Se o plano de fundo estiver definido como algo diferente do plano de fundo padrão (chamando um setBackgroundResource(int id)ou setBackgroundDrawable(Drawable d)), desejo que as margens sejam 0. Se eu chamar isso:

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

Quero que as margens sejam redefinidas para -3dp (já li aqui como converter de pixels em dp, assim que souber definir margens em px, também posso gerenciar a conversão). Mas como isso é chamado na CustomButtonclasse, o pai pode variar de LinearLayout para TableLayout, e eu prefiro que ele não consiga o pai e verifique a instância desse pai. Isso também será bastante inoperante, imagino.

Além disso, ao chamar (usando LayoutParams) parentLayout.addView(myCustomButton, newParams), não sei se isso é adicionado à posição correta (ainda não tentei), digamos o botão do meio de uma linha de cinco.

Pergunta: Existe alguma maneira mais fácil de definir a margem de um único botão programaticamente além de usar LayoutParams?

EDIT: Eu sei da maneira LayoutParams, mas gostaria de uma solução que evite manipular cada tipo de contêiner 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);
    }
}

Porque this.getLayoutParams();retorna um ViewGroup.LayoutParams, que não têm os atributos topMargin, bottomMargin, leftMargin, rightMargin. A instância mc que você vê é apenas uma MarginContainerque contém margens de deslocamento (-3dp) e (oml, omr, omt, omb) e as margens originais (ml, mr, mt, mb).

stealthjong
fonte

Respostas:

797

Você deve usar LayoutParamspara definir as margens do botão:

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

Dependendo do layout que você estiver usando, você deve usar RelativeLayout.LayoutParamsou LinearLayout.LayoutParams.

E para converter sua medida de dp em pixel, tente o seguinte:

Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        yourdpmeasure, 
        r.getDisplayMetrics()
);
throrin19
fonte
152
De qual pacote devo importar esse LayoutParams específico?
Stealthjong 4/12/12
7
setMargins usou px e você usará dp, minha conversão está correta: dp -> px para definir o valor correto da margem.
throrin19
6
@ChristiaandeJong RelativeLayout.LayoutParams
stoefln
16
isso depende do seu layout atual. Se você estiver em LinearLayout, use LinearLayout.LayoutParams. RelativeLayout.LayoutParams de outra forma
throrin19
5
você deve importar layoutParams que é o seu layout pai, ex. <linearlayout><relativelayout> <gridlayout> e você está trabalhando com o layout da grade. então, você precisa usar relativelayout.layoutparams
Sruit A.Suk
228

LayoutParams - NÃO FUNCIONA! ! !

Precisa usar o tipo de: MarginLayoutParams

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

Exemplo de código para MarginLayoutParams:

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

Lyusten Elder
fonte
19
Correto, mas não há necessidade de recuperá-lo, os parâmetros alterados são refletidos automaticamente. Assim, você pode remover a linha: vector8.setLayoutParams (params);
Wirsing
Os LayaoutParams geralmente criam confusão ao definir a margem ... Portanto, este MarginLayoutParams é muito útil. Obrigado
Atul Bhardwaj
4
Você precisa fazer para setLayoutParams (params) após marging mudanças
Leo Droidcoder
Encontrei MarginLayoutParams como nova classe hoje #Obrigado.
Tushar Pandey #
Não funciona para a Buttonvisualização: ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) button.getLayoutParams()retornosnull
Konstantin Konopko
118

Melhor maneira de sempre:

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

Como chamar o método:

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

Espero que isso ajude você.

Hiren Patel
fonte
11
Estou enfrentando problema ao definir setMargins (holder.vCenter, 0, 20, 0,0); assim sua margem de saída de ambos os lados (superior e inferior) o que há de errado com os parâmetros acima?
Arbaz.in 17/09/18
11
Resposta perfeita impressionante !! Obrigado!!
SJD
33
int sizeInDP = 16;

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

Então

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);
sagits
fonte
15

Aqui está a resposta do multifuncional com atualizações recentes:

Etapa 1, para atualizar a margem

A idéia básica é obter margem e atualizá-la. A atualização será aplicada automaticamente e você não precisará restaurá-la. Para obter os parâmetros de layout, basta chamar este método:

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

O LayoutParamsvem do layout da sua visualização. Se a visualização for de um layout linear, você precisará importar LinearLayout.LayoutParams. Se você usar o layout relativo, importar LinearLayout.LayoutParams, etc.

Agora, se você definir a margem usando Layout_marginLeft, Right, etc, você precisa margem de atualização desta forma

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

Se você definir margem usando o novo layout_marginStart, precisará atualizar a margem dessa maneira

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

Etapa 2, para atualizar a margem no dp

Todas as duas maneiras de atualizar a margem acima estão atualizando em pixels. Você precisa fazer uma tradução de dp em pixels.

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

Agora coloque o valor calculado nas funções de atualização de margem acima e você deve estar pronto

Fangming
fonte
9

layout_margin é uma restrição que um filho de exibição informa ao pai. No entanto, é papel dos pais escolher se deseja permitir margem ou não. Basicamente, definindo android: layout_margin = "10dp", o filho está pedindo ao grupo de visualizações pai que aloque espaço 10dp maior que o tamanho real. (padding = "10dp", por outro lado, significa que a visualização filho tornará seu próprio conteúdo 10dp menor .)

Conseqüentemente, nem todos os ViewGroups respeitam a margem . O exemplo mais notório seria listview, onde as margens dos itens são ignoradas. Antes de ligar setMargin()para um LayoutParam, você deve sempre garantir que a visualização atual esteja em um ViewGroup que suporte margem (por exemplo, LinearLayouot ou RelativeLayout) e converter o resultado getLayoutParams()nos LayoutParams específicos que você deseja. ( ViewGroup.LayoutParamsnem sequer temsetMargins() método!)

A função abaixo deve fazer o truque. No entanto, certifique-se de substituir RelativeLayout pelo tipo de exibição pai.

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

Este método permite definir a margem no 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);
}

ATUALIZAR

Você pode alterar o parâmetro que se adapte às suas necessidades.

neferpitou
fonte
8

No Kotlin, será assim:

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

Quando você está em uma Visualização personalizada, pode usar getDimensionPixelSize(R.dimen.dimen_value), no meu caso, adicionei a margem no LayoutParams criado eminit método

Na cidade 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)
}

em 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
fonte
1

Use este método para definir margem no 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();
    }
}

chame o método:

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

Para uma configuração rápida de uma linha, use

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

mas tenha cuidado com qualquer uso incorreto do LayoutParams, pois isso não terá nenhuma ifinstância de declaração chech

Dasser Basyouni
fonte
1

Criou uma função de extensão Kotlin para aqueles que acham útil.

Certifique-se de passar em pixels, não em dp. Feliz codificação :)

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
fonte
1

No meu exemplo, estou adicionando um ImageView a um LinearLayout programaticamente. Eu configurei as margens superior e inferior para o ImagerView. Em seguida, adicione o ImageView ao 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
fonte
1

Você pode usar esse método e colocar dimen estático como 20, ele converte de acordo com o seu dispositivo

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

Hoje, o melhor é provavelmente usar Paris , uma biblioteca fornecida pelo AirBnB.

Os estilos podem ser aplicados assim:

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

Ele também suporta exibição personalizada (se você estender uma exibição) usando anotações:

@Styleable and @Style
sonique
fonte
0

Você tem que ligar

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

igual a: your_view.setPadding(0,16,0,0)

O que você está tentando usar é apenas o getter.

O Android studio mostra o que padding...()realmente significa em java:

exemplo de preenchimento A imagem mostra apenas chamadasgetPadding...()

Se você deseja adicionar uma margem ao seu TextView, precisará do 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
fonte
-1
((FrameLayout.LayoutParams) linearLayout.getLayoutParams()).setMargins(450, 20, 0, 250);
        linearLayout.setBackgroundResource(R.drawable.smartlight_background);

Eu tive que converter o meu FrameLayoutpara um linearLayout como ele é herdado e definir margens para que a atividade apareça apenas em parte da tela, juntamente com um plano de fundo diferente dos parâmetros de layout originais no 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);

Nenhum dos outros trabalhou para usar a mesma atividade e alterar as margens com base na abertura da atividade em um menu diferente! O setLayoutParams nunca funcionou para mim - o dispositivo travava toda vez. Mesmo sendo números codificados - este é apenas um exemplo do código apenas para fins de demonstração.

ali mcnamara
fonte
-1

Você pode usar ViewGroup.MarginLayoutParamspara definir a largura, altura e margens

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

Onde o método setMargins();obtém valores para esquerda, superior, direita e inferior, respectivamente. No sentido horário !, a partir da esquerda.

mmmcho
fonte