Programowo ustaw marginesy w LinearLayout

266

Próbuję użyć Java ( nie XML ) do utworzenia LinearLayout z przyciskami wypełniającymi ekran i posiadającymi marginesy. Oto kod, który działa bez marginesów:

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

Więc to działa dobrze, ale jak, u licha, dajesz marginesy przyciskom, żeby między nimi była przestrzeń? Próbowałem użyć LinearLayout.MarginLayoutParams, ale to nie ma weightczłonka, więc nie jest dobrze. I to nie działa, jeśli przekażesz go również lpdo jego konstruktora.

Czy to jest niemożliwe? Ponieważ na pewno wygląda i nie byłoby to pierwsze zadanie układu Androida, które można wykonać tylko w języku XML.

Timmmm
źródło
1
developer.android.com/reference/android/view/… , int, int, int) Zamiast layoutParams.setMargins (30, 20, 30, 0); wkładasz layoutParams.setMargins (30dp, 20dp, 30dp, 0dp);
DarthestVader
3
setMargins przyjmuje int jako argumenty. Możesz podać tylko „dp” używając atrybutów xml
jyavenard

Odpowiedzi:

496

Oto mały kod, aby to zrobić:

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
źródło
6
dzięki za dokładny przykładowy kod - o wiele bardziej korzystny niż same opisy
Someone Somewhere
25
Wygląda na to, że parametry marginesów są ustawione w pikselach. W jakiś sposób ustawić je w DPS?
Artem Russakovskii
30
@ArtemRussakovskii Podobnie jak większość funkcji w Androidzie, pobierają piksele. Sugeruję globalną funkcję narzędziową, która konwertuje spadki na px. To właśnie zrobiłem we wszystkich moich aplikacjach. Android API jest do bani.
mxcl
7
@ MaxHowell Właśnie to skończyłem. To niesamowite, że czasami brakuje takich podstawowych rzeczy.
Artem Russakovskii
5
@ArtemRussakovskii - użyj TypedValue.applyDimension (...) do konwersji DIP na PX. Zobacz stackoverflow.com/questions/2238883/…
Gautam
64

Więc to działa dobrze, ale jak, u licha, dajesz marginesy przyciskom, żeby między nimi była przestrzeń?

Dzwonisz setMargins()na LinearLayout.LayoutParamsobiekcie.

Próbowałem użyć LinearLayout.MarginLayoutParams, ale to nie ma członka wagi, więc nie jest dobrze.

LinearLayout.LayoutParamsjest podklasą LinearLayout.MarginLayoutParams, jak wskazano w dokumentacji .

Czy to jest niemożliwe?

Nie.

nie byłoby to pierwsze zadanie układu Androida, które można wykonać tylko w języku XML

Zapraszamy do przedstawienia dowodu tego roszczenia.

Osobiście nie jestem świadomy niczego, co można osiągnąć tylko za pomocą XML, a nie metod Java w SDK. W rzeczywistości z definicji wszystko musi być wykonalne przez Javę (choć niekoniecznie metodami dostępnymi w SDK), ponieważ XML nie jest kodem wykonywalnym. Ale jeśli coś wiesz, zwróć na to uwagę, ponieważ jest to błąd w zestawie SDK, który kiedyś powinien zostać naprawiony.

CommonsWare
źródło
2
Ha, ok, teraz rozumiem. Trochę się zagubiłem w układzie układu, co jest dość skomplikowane. Nie wydaje mi się, żeby i tak ustawiać szerokość / wysokość układu w czasie wykonywania.
Timmmm,
2
I nie ma sposobu, aby ustawić styl: stackoverflow.com/questions/2016249/…
Timmmm
1
Nie miałem problemu z ustawieniem szerokości i wysokości w czasie wykonywania przez LayoutPararms. Mówię o stylach ... tak, cóż, jest powód, dla którego ich nie używam. :-)
CommonsWare
6
Chcę wiedzieć, dlaczego taka PITA programowo generuje interfejs użytkownika
ktoś gdzieś
3
Wieki zajęło mi uświadomienie sobie, że tak naprawdę kilka dni temu zaimportowałem niewłaściwy LayoutParams, który nie obsługiwał Margins ... Czytając te odpowiedzi, postanowiłem usunąć import. Istnieje ponad 10 opcji D: Poszedłem do linearLayout.LayoutParams. Pracuje.
Doomsknight
31

Aby dodać marginesy bezpośrednio do pozycji (niektóre pozycje umożliwiają bezpośrednią edycję marginesów), możesz:

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

... działa to bez konieczności znajomości / edycji otaczającego układu. Zwróć uwagę na sprawdzenie „instanceof” na wypadek, gdybyś spróbował uruchomić to z czymś, co nie obsługuje marginesów.

Adam
źródło
2
Właśnie tego szukam.
djdance
21

Ze względu na różnice w gęstości pikseli ekranu urządzenia dobrze jest zawsze używać DIPjednostki, aby programowo ustawić margines. Jak poniżej

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

Mam nadzieję, że to pomoże.

Rupesh Yadav
źródło
10

Marginesy ustawiłem bezpośrednio przy użyciu poniższego kodu

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

Jedyną rzeczą jest tutaj, aby zauważyć, że LayoutParamsnależy zaimportować kolejny pakiet android.widget.RelativeLayout.LayoutParams, w przeciwnym razie wystąpi błąd.

Janith
źródło
7

Spróbuj tego

 LayoutParams params = new LayoutParams(
            LayoutParams.WRAP_CONTENT,      
            LayoutParams.WRAP_CONTENT
    );
    params.setMargins(left, top, right, bottom);
    yourbutton.setLayoutParams(params);
Karan Bhalodiya
źródło
7
 MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
 layoutParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
Ginni
źródło
2
„Chociaż ten kod może odpowiedzieć na pytanie, lepiej dołączyć wyjaśnienie kodu tutaj.
xenteros,
4

Spróbuj tego:

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

powinieneś być typem widoku viewGroup. W powyższym kodzie, na przykład, chcę zmienić margines frameLayout, a grupa widoków frameLayout jest RelativeLayout , więc musisz się ukryć przed (RelativeLayout.LayoutParams)

Francis Shi
źródło
0

Oto rozwiązanie jednoliniowe:

((LinearLayout.LayoutParams) yourLinearLayout.getLayoutParams()).marginToAdd = ((int)(Resources.getSystem().getDisplayMetrics().density * yourDPValue));
Stappo
źródło