Wie kann ich die Größe einer benutzerdefinierten Ansicht programmgesteuert ändern?


164

Ich codiere eine benutzerdefinierte Ansicht, die von RelativeLayout erweitert wurde, und möchte die Größe programmgesteuert ändern. Wie kann ich das tun?

Die benutzerdefinierte Ansichtsklasse ist ungefähr so:

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

Antworten:


253

Android löst eine Ausnahme aus, wenn Sie die Höhe oder Breite einer Ansicht nicht übergeben. Verwenden Sie anstelle eines neuen LayoutParams-Objekts das ursprüngliche, damit alle anderen festgelegten Parameter beibehalten werden. Beachten Sie, dass der von getLayoutParams zurückgegebene Typ von LayoutParams der des übergeordneten Layouts ist und nicht die Ansicht , deren Größe Sie ändern.

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

2
Wie @HerbertD erwähnt, wird dabei auch ein Fehler angezeigt, es sei denn, ich verwende LinearLayout.LayoutParams, obwohl es sich um ein RelativeLayout handelt, dessen Größe ich ändere.
Martin Belcher - AtWrk

6
@Eigo Gemäß der Android-Dokumentation werden die LayoutParams an die übergeordnete Ansicht übergeben, da dies die Ansicht ist, die für das Layout verantwortlich ist.
sstn

1
Ob der in-Wert in einen dp-Wert konvertiert werden soll oder ob er funktionieren würde.
Dory

Dies ist auch vorzuziehen, da dadurch vermieden wird, dass ein neues LayoutParams-Objekt unnötig instanziiert wird
Stephen Kidson,

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

Problem gelöst!

HINWEIS: Verwenden Sie unbedingt die übergeordneten Layouts LayoutParams. Meins ist LinearLayout.LayoutParams!


3
Wut. Warum würden Sie nicht verwendenRelativeLayout.LayoutParams?
nmr

1
Das hat bei mir nicht funktioniert, ich habe eine Klassenbesetzungsausnahme dafür bekommen.
Tapan Thaker

4
@Tapan Thanker Verwenden Sie die LayoutParams des übergeordneten Layouts. Und mein übergeordnetes Layout ist LinearLayout.
Herbert

10
Ich schrieb eine allgemeinere Version davon: 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
Dadurch werden alle anderen Parameter auf die Standardwerte zurückgesetzt. @smisiewicz Antwort ist besser.
Fran Marzoa

66

Das funktioniert bei mir:

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

7
Dies ist viel besser als die anderen Antworten, da für diesen Code der genaue Typ der übergeordneten ViewGroup nicht bekannt sein muss.
Bart Burg

1
Wissen Sie, was der Unterschied zwischen dem Aufruf von requestLayout () und dem Aufruf von setLayoutParams (params) ist?
VoghDev

2
setLayoutParams (params) enthält requestLayout ().
IllusionJJ

44

Nehmen wir an, Sie wollten die Größe der Ansicht in geräteunabhängigen Pixeln ( dp ) ändern : -

Sie müssen eine Methode namens verwenden applyDimension, die Mitglied der Klasse ist TypedValue, um von Pixeln in dps zu konvertieren. Wenn ich also die Höhe auf 150 dp einstellen möchte (sagen wir), dann könnte ich das tun:

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

wobei der Ausdruck: getResources().getDisplayMetrics()die Bildschirmdichte / Auflösung erhält


6
Anstatt Ihre Dimension hart zu codieren, können Sie diese auch für die Höhe in Pixel verwenden:float pixels = context.getResources().getDimensionPixelSize(R.dimen.card_height);
Francois Dermu

Diese Antwort ist als richtige Antwort besser geeignet!. Vielen Dank
Yunus Kulyyev


6

versuchen Sie es mit diesem:

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

Entschuldigung, ich habe nicht alle Fragen gestellt, seit Sie sie beantwortet haben. Das ist die ganze Frage. Vielen Dank!
Herbert

6

Hier ist eine allgemeinere Version der obigen Lösung von @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, du hast meinen Tag buchstäblich gerettet :)
Qasim

5

Ich habe diese Methode verwendet, um die Breite der benutzerdefinierten Ansicht zu erhöhen

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

Ich habe es auf diese Weise gelöst. Ich habe im Grunde eine einfache Ansicht in der XML-Datei.

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

2
haha, sehr naiv, aber gut funktionierend, ich empfehle jedoch, setLayoutParams () aufzurufen, um Änderungen ordnungsgemäß an mögliche verschachtelte untergeordnete Elemente weiterzugeben. Rufen Sie nach dem Aktualisieren von .width und .height view.setLayoutParams (view.getLayoutParams ()) auf
Geben Sie

@ Bhargav Rao könnten Sie mir zu diesem Thema helfen: https://stackoverflow.com/q/44259342/6596724
Tux-World

2

Wenn Sie nur two or three condition(sizes)dann haben, können Sie @Overide onMeasure wie verwenden

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

Und ändern Sie Ihre Größe für diese Bedingungen in der CustomView-Klasse ganz einfach.


1

Wenn Sie überschreiben onMeasure, vergessen Sie nicht, die neuen Größen zu aktualisieren

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

1

So habe ich das erreicht. In der Antwort von Sileria hat er / sie Folgendes getan:

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

Dies ist richtig, aber es wird erwartet, dass wir die Höhe angeben pixels, aber ich wollte dpdie Höhe angeben, also möchte ich hinzufügen:

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

So wird es aussehen:

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

0

Das habe ich getan:

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

Wenn es eine Ansichtsgruppe gibt, zu der diese Ansicht gehört, müssen Sie möglicherweise auch yourViewGroup.requestLayout () aufrufen, damit sie wirksam wird.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.