Definir margens em um LinearLayout programaticamente

266

Estou tentando usar Java ( não XML ) para criar um LinearLayout com botões que preenchem a tela e têm margens. Aqui está o código que funciona sem margens:

LinearLayout buttonsView = new LinearLayout(this);
buttonsView.setOrientation(LinearLayout.VERTICAL);
for (int r = 0; r < 6; ++r) {
    Button btn = new Button(this);
    btn.setText("A");

    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT); // Verbose!
    lp.weight = 1.0f; // This is critical. Doesn't work without it.
    buttonsView.addView(btn, lp);
}

ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
setContentView(buttonsView, lp);

Então, isso funciona bem, mas como você dá margens aos botões para que haja espaço entre eles? Eu tentei usar LinearLayout.MarginLayoutParams, mas isso não tem weightmembro, então não é bom. E isso não funciona se você o passar lpno construtor também.

Isso é impossível? Porque com certeza parece, e não seria a primeira tarefa de layout do Android que você só pode executar em XML.

Timmmm
fonte
1
developer.android.com/reference/android/view/… , int, int, int) Em vez de layoutParams.setMargins (30, 20, 30, 0); você coloca layoutParams.setMargins (30dp, 20dp, 30dp, 0dp);
DarthestVader
3
SetMargins leva int como argumentos .. você só pode fornecer "dp" usando attributtes XML
jyavenard

Respostas:

496

Aqui está um pequeno código para realizá-lo:

LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);

LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
     LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);

layoutParams.setMargins(30, 20, 30, 0);

Button okButton=new Button(this);
okButton.setText("some text");
ll.addView(okButton, layoutParams);
Mauro
fonte
6
Graças a uma-a-ponto exemplo de código - muito mais benéfico do que apenas descrições
alguém em algum lugar
25
Parece que os parâmetros de margem estão definidos em pixels. Alguma maneira de configurá-los em dps?
Artem Russakovskii
30
@ArtemRussakovskii Como a maioria das funções do Android, elas recebem pixels. Sugiro uma função de utilitário global que converte mergulhos em px. Foi o que fiz em todos os meus aplicativos. A API do Android é péssima.
Mxcl 26/01
7
@ MaxHowell Foi o que acabei fazendo. É incrível que algumas coisas básicas assim estejam faltando às vezes.
Artem Russakovskii
5
@ArtemRussakovskii - use TypedValue.applyDimension (...) para converter DIP em PX. Veja stackoverflow.com/questions/2238883/…
Gautam
64

Então, isso funciona bem, mas como você dá margens aos botões para que haja espaço entre eles?

Você chama setMargins()o LinearLayout.LayoutParamsobjeto.

Eu tentei usar LinearLayout.MarginLayoutParams, mas como não há membro de peso, não é bom.

LinearLayout.LayoutParamsé uma subclasse de LinearLayout.MarginLayoutParams, conforme indicado na documentação .

Isso é impossível?

Não.

não seria a primeira tarefa de layout do Android que você só pode executar em XML

Você pode fornecer provas dessa reivindicação.

Pessoalmente, não conheço nada que possa ser realizado apenas via XML e não através de métodos Java no SDK. De fato, por definição, tudo deve ser factível via Java (embora não necessariamente via métodos alcançáveis ​​pelo SDK), pois o XML não é um código executável. Mas, se você estiver ciente de algo, lembre-o, porque esse é um bug no SDK que deve ser corrigido algum dia.

CommonsWare
fonte
2
Ha, ok eu entendo agora. Estava ficando um pouco perdido no sistema de layout, o que é bastante complicado. Eu acho que não há como definir layout_widgth / height em tempo de execução.
Timmmm em 20/05
2
E não há como definir o estilo: stackoverflow.com/questions/2016249/…
Timmmm
1
Eu não tive um problema com a configuração de largura e altura no tempo de execução via LayoutPararms. I termos de estilos ... sim, bem, há uma razão para eu não usá-los. :-)
CommonsWare
6
Eu quero saber por que é tão PITA gerar programaticamente uma interface do usuário
Someone Somewhere
3
Levei muito tempo para perceber que, de fato, há alguns dias, importei os LayoutParams errados que não suportavam Margens ... Lendo essas respostas, decidi remover minha importação. Existem mais de 10 opções D: fui para linearLayout.LayoutParams. Trabalho.
Doomsknight 17/05/12
31

Para adicionar margens diretamente aos itens (alguns itens permitem a edição direta de margens), você pode:

LayoutParams lp = ((ViewGroup) something).getLayoutParams();
if( lp instanceof MarginLayoutParams )
{
    ((MarginLayoutParams) lp).topMargin = ...;
    ((MarginLayoutParams) lp).leftMargin = ...;
    //... etc
}
else
    Log.e("MyApp", "Attempted to set the margins on a class that doesn't support margins: "+something.getClass().getName() );

... isso funciona sem a necessidade de conhecer / editar o layout circundante. Observe a verificação "instanceof" no caso de você tentar executar isso em algo que não suporta margens.

Adão
fonte
2
É exatamente o que estou procurando.
djdance
21

Devido à variação nas densidades de pixel da tela do dispositivo, é bom sempre usar a DIPunidade para definir a margem programaticamente. Como abaixo_

//get resources
Resources r = getResources();
float pxLeftMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, r.getDisplayMetrics());
float pxTopMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, r.getDisplayMetrics());
float pxRightMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, r.getDisplayMetrics());
float pxBottomMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, r.getDisplayMetrics());

//get layout params...
LayoutParams params=new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
params.setMargins(Math.round(pxLeftMargin), Math.round(pxTopMargin), Math.round(pxRightMargin), Math.round(pxBottomMargin));

//set margin...
yourLayoutTOsetMargin.setLayoutParams(params); 

Espero que isso ajude.

Rupesh Yadav
fonte
10

Configurei margens diretamente usando o código abaixo

LinearLayout layout = (LinearLayout)findViewById(R.id.yourrelative_layout);
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT);            
params.setMargins(3, 300, 3, 3); 
layout.setLayoutParams(params);

A única coisa aqui é notar que LayoutParamsdeve ser importado para o pacote seguinte android.widget.RelativeLayout.LayoutParams, ou então haverá um erro.

Janith
fonte
7

Tente isto

 LayoutParams params = new LayoutParams(
            LayoutParams.WRAP_CONTENT,      
            LayoutParams.WRAP_CONTENT
    );
    params.setMargins(left, top, right, bottom);
    yourbutton.setLayoutParams(params);
Karan Bhalodiya
fonte
7
 MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
 layoutParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
Ginni
fonte
2
“Embora esse código possa responder à pergunta, é melhor incluir a explicação do código aqui.
X168 #
4

Tente o seguinte:

MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
params.width = 250;
params.leftMargin = 50;
params.topMargin = 50;
Makvin
fonte
3
/*
 * invalid margin
 */
private void invalidMarginBottom() {
    RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) frameLayoutContent.getLayoutParams();
    lp.setMargins(0, 0, 0, 0);
    frameLayoutContent.setLayoutParams(lp);
}

você deve ter conhecimento do tipo do viewGroup da exibição. No código acima, por exemplo, quero alterar a margem do frameLayout e o grupo de exibição do frameLayout é um RelativeLayout,, portanto, você deve se esconder em (RelativeLayout.LayoutParams)

Francis Shi
fonte
0

Aqui está uma solução de linha única:

((LinearLayout.LayoutParams) yourLinearLayout.getLayoutParams()).marginToAdd = ((int)(Resources.getSystem().getDisplayMetrics().density * yourDPValue));
Stappo
fonte