Jak programowo zmienić rozmiar widoku niestandardowego?


164

Koduję widok niestandardowy rozszerzony z RelativeLayout i chcę programowo zmienić jego rozmiar. Jak mogę to zrobić?

klasa widoku niestandardowego jest podobna do:

public ActiveSlideView(Context context, AttributeSet attr){
        super(context, attr);
        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if(inflater != null){       
            inflater.inflate(R.layout.active_slide, this);
        }

Odpowiedzi:


253

Android zgłasza wyjątek, jeśli nie uda się przekazać wysokości lub szerokości widoku. Zamiast tworzyć nowy obiekt LayoutParams, użyj oryginalnego, aby zachować wszystkie inne ustawione parametry. Zwróć uwagę, że typ LayoutParams zwracany przez getLayoutParams jest typem układu nadrzędnego , a nie widoku, którego rozmiar zmieniasz.

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) someLayout.getLayoutParams();
params.height = 130;
someLayout.setLayoutParams(params);

2
Jak wspomina @HerbertD, otrzymuję również błąd, robiąc to, chyba że używam LinearLayout.LayoutParams, nawet jeśli jest to RelativeLayout, którego rozmiar zmieniam.
Martin Belcher - AtWrk

6
@Eigo Zgodnie z dokumentacją Androida, LayoutParams są przekazywane do widoku nadrzędnego, ponieważ jest to widok odpowiedzialny za układ.
sstn

1
Czy wartość in powinna zostać przekonwertowana na wartość dp, czy zadziała.
Dory

Jest to również zalecane, ponieważ pozwala uniknąć niepotrzebnego tworzenia wystąpienia nowego obiektu LayoutParams
Stephen Kidson

129
this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, theSizeIWant));

Problem rozwiązany!

UWAGA: Upewnij się, że używasz układu nadrzędnego LayoutParams. Mój jest LinearLayout.LayoutParams!


3
Wut. Dlaczego nie używałbyśRelativeLayout.LayoutParams?
NMR,

1
To nie zadziałało dla mnie, mam za to wyjątek klasy.
Tapan Thaker,

4
@Tapan Thanker Użyj LayoutParams układu nadrzędnego. A układ My Parent to LinearLayout.
herbertD

10
Napisałem bardziej ogólną wersję tego: private void resizeView(View view, int newWidth, int newHeight) { try { Constructor<? extends LayoutParams> ctor = view.getLayoutParams().getClass().getDeclaredConstructor(int.class, int.class); view.setLayoutParams(ctor.newInstance(newWidth, newHeight)); } catch (Exception e) { e.printStackTrace(); } }
atroutt

2
Spowoduje to zresetowanie wszystkich pozostałych parametrów do wartości domyślnych. @smisiewicz odpowiedź jest lepsza.
Fran Marzoa,

66

To działa dla mnie:

ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = customHeight;
layout.requestLayout();

7
Jest to znacznie lepsze niż inne odpowiedzi, ponieważ ten kod nie wymaga znajomości dokładnego typu nadrzędnej grupy ViewGroup.
Bart Burg

1
Czy wiesz, jaka jest różnica między wywołaniem requestLayout () a wywołaniem setLayoutParams (params)?
voghDev

2
setLayoutParams (params) zawiera requestLayout ().
illusionJJ

44

Powiedzmy, że chcesz zmienić rozmiar widoku w pikselach niezależnych od urządzenia ( dp ): -

Musisz użyć metody o nazwie applyDimension, która jest członkiem klasy TypedValuedo konwersji z pikseli na dps. Więc jeśli chcę ustawić wysokość na 150 dp (powiedzmy) - wtedy mógłbym to zrobić:

float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150, getResources().getDisplayMetrics());
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) someLayout.getLayoutParams();
params.height = (int) pixels;
someLayout.setLayoutParams(params);

gdzie wyrażenie: getResources().getDisplayMetrics()pobiera gęstość / rozdzielczość ekranu


6
Zamiast na float pixels = context.getResources().getDimensionPixelSize(R.dimen.card_height);
stałe

ta odpowiedź jest bardziej odpowiednia jako poprawna odpowiedź !. Dzięki
Yunus Kulyyev


6

spróbuj tego:

...
View view = inflater.inflate(R.layout.active_slide, this);
view.setMinimumWidth(200);

Przepraszam, że nie opublikowałem wszystkich pytań, odkąd na nie odpowiedziałeś. To jest całe pytanie. Dzięki!
herbertD

6

Oto bardziej ogólna wersja powyższego rozwiązania z @herbertD:

private void resizeView(View view, int newWidth, int newHeight) { 
    try { 
        Constructor<? extends LayoutParams> ctor = view.getLayoutParams().getClass().getDeclaredConstructor(int.class, int.class); 
        view.setLayoutParams(ctor.newInstance(newWidth, newHeight));   
    } catch (Exception e) { 
        e.printStackTrace(); 
    }
}

@atroutt, dosłownie uratowałeś mi dzień :)
Qasim

5

W ten sposób zwiększyłem szerokość widoku niestandardowego

customDrawingView.post(new Runnable() {
                            @Override
                            public void run() {
                                View view_instance = customDrawingView;
                                android.view.ViewGroup.LayoutParams params = view_instance
                                        .getLayoutParams();
                                int newLayoutWidth = customDrawingView
                                        .getWidth()
                                        + customDrawingView.getWidth();
                                params.width = newLayoutWidth;
                                view_instance.setLayoutParams(params);
                                screenWidthBackup = params.width;
                            }
                        });

4

Rozwiązałem to w ten sposób… Mam w zasadzie prosty widok wewnątrz pliku xml.

 View viewname = findViewById(R.id.prod_extra);
             prodExtra.getLayoutParams().height=64;

2
haha, bardzo naiwny, ale dobrze działający sposób, jednak polecam wywołanie metody setLayoutParams () w celu poprawnego propagowania zmiany do ewentualnych zagnieżdżonych dzieci, więc po zaktualizowaniu .width i .height wywołaj view.setLayoutParams (view.getLayoutParams ()) to też jest dowód zawsze typu
comeGetSome

@Bhargav Rao, czy możesz mi pomóc w tym temacie: https://stackoverflow.com/q/44259342/6596724
tux-world

2

Jeśli masz tylko two or three condition(sizes), możesz użyć @Overide onMeasure jak

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
{
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

I łatwo zmień swój rozmiar dla tych warunków w klasie CustomView.


1

jeśli zastępujesz onMeasure, nie zapomnij zaktualizować nowych rozmiarów

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setMeasuredDimension(newWidth, newHeight);
}

1

W ten sposób to osiągnąłem. W odpowiedzi Sileria wykonał następujące czynności:

ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = customHeight;
layout.requestLayout();

To prawda, ale oczekuje, że podamy wysokość pixels, ale chciałem podać wysokość, dpktórą chcę, więc dodałem:

public int convertDpToPixelInt(float dp, Context context) {
    return (int) (dp * (((float) context.getResources().getDisplayMetrics().densityDpi) / 160.0f));
}

Więc będzie to wyglądać tak:

ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = convertDpToPixelInt(50, getContext());
layout.requestLayout();

0

Oto co zrobiłem:

View myView;  
myView.getLayoutParams().height = 32;  
myView.getLayoutParams().width = 32;

Jeśli istnieje grupa widoków, do której należy ten widok, może być konieczne wywołanie metody yourViewGroup.requestLayout (), aby odniosła skutek.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.