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

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);
smisiewicz
quelle
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!

herbertD
quelle
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();
Sileria
quelle
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

Danield
quelle
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);
zed_0xff
quelle
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
quelle
@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;
                            }
                        });
AkhilGite
quelle
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;
DazzleGifts Apps
quelle
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.

Xar-e-ahmer Khan
quelle
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);
}
XurajB
quelle
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();
Klasse a
quelle
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.

us_david
quelle