Begrenzen Sie die Höhe von ListView unter Android

92

Ich möchte einen Button unter a anzeigen ListView. Problem ist, wenn die ListViewerweitert wird (Elemente hinzugefügt ...), wird die Schaltfläche aus dem Bildschirm gedrückt.

Ich habe es LinearLayoutmit Gewichten versucht (wie in Android vorgeschlagen: Warum gibt es kein maxHeight für eine Ansicht? ), Aber entweder habe ich die Gewichte falsch verstanden oder es hat einfach nicht funktioniert.

Außerdem habe ich irgendwo den Hinweis gefunden, a zu verwenden RelativeLayout. Das ListViewwürde dann über der Schaltfläche mit dem android:layout_aboveParameter eingestellt.

Das Problem dabei ist, dass ich nicht weiß, wie ich den Knopf danach positionieren soll. In dem Beispiel, das ich gefunden habe, wurde die Ansicht unter dem ListViewangepasst android:layout_alignParentBottom, aber ich möchte nicht, dass meine Schaltfläche am unteren Bildschirmrand haftet.

Irgendwelche Ideen außer der Verwendung der setHeight-Methode und der Berechnung des benötigten Platzes?


Edit: Ich habe viele nützliche Antworten bekommen.

  • Die Lösung von bigstone & user639183 hat fast perfekt funktioniert. Ich musste jedoch einen zusätzlichen Abstand / Rand am unteren Rand der Schaltfläche hinzufügen, da dieser immer noch halb aus dem Bildschirm herausgeschoben wurde (aber dann gestoppt wurde).

  • Die Antwort von Adinia mit dem relativen Layout ist nur dann in Ordnung, wenn die Schaltfläche am unteren Bildschirmrand befestigt werden soll. Es ist nicht das, was ich beabsichtigt habe, könnte aber dennoch für andere nützlich sein.

  • Die Lösung von AngeloS war die, die ich am Ende gewählt habe, da sie nur die gewünschten Effekte erzeugt hat. Ich habe jedoch zwei geringfügige Änderungen an LinearLayoutder Schaltfläche vorgenommen:

    • Da ich keine absoluten Werte in meinem Layout haben wollte, wechselte ich android:layout_height="45px"zu wrap_content, was auch gut funktioniert.

    • Zweitens, da ich wollte, dass die Schaltfläche horizontal zentriert wird, was nur von vertikal unterstützt wird LinearLayout, habe ich android: orientierung = "horizontal" in "vertikal" geändert.

    AngeloS erklärte in seinem ersten Beitrag auch, dass er nicht sicher sei, ob der android:layout_weight="0.1"Parameter in der LinearLayoutUmgebung ListViewirgendeine Wirkung habe; Ich habe es gerade versucht und es tut es tatsächlich! Ohne wird die Taste wieder aus dem Bildschirm gedrückt.

Qualle
quelle
Auf diese Weise wächst das innere relative Layout länger als der Bildschirm. Ein Schritt könnte das Hinzufügen sein android:layout_alignParentBottom="true". Möchten Sie jedoch klarstellen, dass die Schaltfläche am unteren Rand der ListView angezeigt wird, wenn nur wenige Elemente vorhanden sind? Wenn ja, sehen Sie, was Rich sagt.
Bigstones
Ja, das will ich.
Quallen
Jahre später haben wir jetzt dank ConstraintLayout maximale Höhe: stackoverflow.com/questions/42694355/…
user1506104

Antworten:

55

Ich hatte genau dieses Problem und um es zu lösen, habe ich zwei separate erstellt LinearLayouts, um das ListViewbzw. Buttonunterzubringen. Von dort stecke ich beide in einen anderen Linear Layoutund setze den Container android:orientationauf vertical. Ich habe auch das Gewicht des der eingestellt , LinearLayoutdass die untergebracht ListViewzu , 0.1aber ich weiß nicht , ob das einen Effekt hat. Von dort aus können Sie die Höhe des unteren Containers (mit Ihrer Schaltfläche) auf die gewünschte Höhe einstellen.

EDIT das ist was ich meine:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="0.1"
    android:orientation="horizontal">

    <ListView
        android:id="@+id/ListView01"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:dividerHeight="2px"></ListView>
</LinearLayout>

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="45px"
    android:background="@drawable/drawable"
    android:orientation="horizontal">

    <Button
        android:id="@+id/moreButton"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentRight="true"
        android:background="@drawable/btn_more2"
        android:paddingRight="20px" />

</LinearLayout>

Mit der obigen Lösung wird die Schaltfläche am unteren Bildschirmrand repariert.


Ändern Sie die Höhe von ListView01in, damit die Schaltfläche am Ende der Liste angezeigt wird wrap_content:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="0.1"
    android:orientation="horizontal">

    <ListView
        android:id="@+id/ListView01"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:dividerHeight="2px"></ListView>
</LinearLayout>

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="45px"
    android:background="@drawable/drawable"
    android:orientation="horizontal">

    <Button
        android:id="@+id/moreButton"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentRight="true"
        android:background="@drawable/btn_more2"
        android:paddingRight="20px" />
</LinearLayout>

AngeloS
quelle
Ich sehe es als etwas Ähnliches wie <divTags in HTML. Es ist nur ein Wrapper und diese Lösung funktioniert definitiv.
AngeloS
Und in Bezug auf den Overhead ist es nicht viel anders als das, was Sie mit den relativen Layouts machen. Im Moment haben Sie einen Outter-Wrapper und Sie verschachteln einen anderen. Ich schlage vor, Sie verschachteln nur noch einen und teilen die Listenansicht auf und die Schaltfläche in zwei Container, wodurch ein Stapeleffekt im vertikalen linearen Layout erzeugt wird. Ich kann nicht genug betonen, dass dies eine funktionierende Lösung ist.
AngeloS
1
JA! das funktioniert! Es ist wichtig zu beachten, dass der einzige Unterschied zwischen Ihrer ersten und zweiten Lösung darin besteht, dass das lineare Layout wrack_content benötigt. Daher habe ich einen Anfangstyp eingerichtet: imgur.com/c9L1Z . Für alle anderen, die dies finden: Die Gewichtung ist wichtig, kann aber jeden Wert annehmen.
Sam
2
Es ist nicht nötig, alle Ansichten so zu verpacken - sehen Sie sich die Lösung
Richard Le Mesurier
Muss für das Tastenlayout 45px oder ein genauer Wert eingegeben werden? Ich muss stattdessen wrap_content setzen
Mario Velasco
65

Ich habe dieses Problem im Code gelöst und die Höhe der Listenansicht nur festgelegt, wenn mehr als 5 Elemente enthalten sind:

if(adapter.getCount() > 5){
        View item = adapter.getView(0, null, listView);
        item.measure(0, 0);         
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, (int) (5.5 * item.getMeasuredHeight()));
        listView.setLayoutParams(params);
}

Beachten Sie, dass ich die maximale Höhe auf das 5,5-fache der Höhe eines einzelnen Elements festgelegt habe, damit der Benutzer sicher weiß, dass ein gewisser Bildlauf erforderlich ist! :) :)

shaylh
quelle
1
Gute Antwort. Mit diesem Code erkenne ich die Höhe meines Artikels und kann jetzt die Größe meiner Liste festlegen, um anzuzeigen, wie viele Itens ich möchte. Vielen Dank.
Derzu
3
Dies ist die beste Antwort. Warum 50 Zeilen verschachteltes XML schreiben, wenn Sie das Problem mit 5 Codezeilen lösen können?
Greg Ennis
Vielen Dank, dass Sie @shaylh. Hat perfekt funktioniert.
Anju
Obwohl ich die XML-Lösungen gut aufgeräumt habe, habe ich diese Idee in meinem Endprodukt verwendet.
Richard Le Mesurier
1
@ JayR es ist nie zu spät zu kommentieren
Manza
21

Bei Ihrer letzten Bearbeitung müssen Sie lediglich android:layout_above="@+id/butt1"Ihren ListView-Code hinzufügen .

Und um Ihnen (und allen hier, die zuvor eine Antwort versucht haben) zu zeigen, dass Sie wirklich nicht mehr als eine verwenden müssen RelativeLayout, finden Sie hier Ihren korrigierten Code :

   <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/bkg">
    <TextView
        android:id="@+id/textView1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="TextView1"
        android:layout_alignParentTop="true">
    </TextView>
    <TextView
        android:id="@+id/textView2"
        android:layout_below="@+id/textView1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="TextView2"
        android:layout_centerHorizontal="true">
    </TextView>
    <Button
        android:id="@+id/butt1"
        android:text="string/string3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true">
    </Button>
    <ListView
        android:id="@+id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="2dip"
        android:layout_marginBottom="2dip"
        android:drawSelectorOnTop="false"
        android:visibility="visible"
        android:layout_below="@+id/textView2"
        android:layout_above="@+id/butt1" />
    </RelativeLayout>

und das Ergebnis unter Verwendung einer zufälligen Liste:
Geben Sie hier die Bildbeschreibung ein

Adinia
quelle
1
Vielen Dank für Ihre Hilfe, aber die Schaltfläche am unteren Bildschirmrand zu befestigen, war einfach nicht das, was ich beabsichtigt hatte. Es soll sich am Ende der ListView befinden.
Quallen
In der Tat scheint diesmal LinearLayouts die einzige Lösung für das zu sein, was Sie wollen. Ich habe verschiedene Kombinationen mit RelativeLayouts ausprobiert und keine hat wirklich funktioniert :( ... Aber ich bin froh, dass Sie Ihre Antwort gefunden haben.
Adinia
1
Danke dir! Es ist perfekt!
Guicara
6

Stellen Sie LinearLayoutmit die Höhe Ihres ListViewund Buttonauf ein wrap_contentund fügen Sie ein Gewicht = 1 hinzu ListView. Dies sollte funktionieren, wie Sie möchten.
Und ja, setzen Sie layout_gravitydas Buttonaufbottom

ernazm
quelle
6

Es wurde ein Weg gefunden, dies ohne verschachtelte Container zu tun, inspiriert von der Lösung von AngeloS.

Ich habe eine LinearLayoutmit vertikaler Ausrichtung verwendet, die eine ListViewund eine Schaltfläche hat. Ich stelle das android:layout_weight="0.1"für die ListView.

Es schafft es, dass der Button immer am Ende der Liste bleibt. Und die Schaltfläche wird nicht vom Bildschirm gedrückt, wenn die Liste wächst.

<ListView
    android:id="@+id/notes_list"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="0.1"        
    />

<Button
    android:id="@+id/create_note_btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"        
    android:onClick="onCreateButtonClicked"
    android:text="@string/create_notes"
    />
Funkeln
quelle
2
Nein, habe es einfach versucht und die Schaltfläche bleibt am unteren Rand des Bildschirms, sie bleibt nicht am unteren Rand der Liste. :(
Adinia
@Adinia Das funktioniert zumindest unter 4.4.3 perfekt. Gute Lösung, Sparkle, sollte mehr Stimmen haben.
Richard Le Mesurier
Humm ... haben Sie vielleicht noch andere Einstellungen in Ihrem Layout? Ich habe gerade erneut auf einem Nexus 4 mit 4.4.3 getestet, und die Schaltfläche bleibt am unteren Rand des Layouts, nicht der Liste, sie bleibt nicht bei der Liste.
Adinia
2
@Richard Le Mesurier In der Tat android:layout_height="wrap_content" funktioniert das LinearLayout wie in Ihrer Lösung perfekt, und zwar nicht nur in 4.4.3, sondern auch, da Sparkle es nicht erwähnt hat, habe ich es match_parentzuvor versucht .
Adinia
Ich arbeite auch an Pie. +1
Zubair Younas
5

RelativeLayout ist eine Lösung, wenn Sie nicht möchten, dass die Schaltfläche zu nahe am unteren Rand bleibt, können Sie Ränder hinzufügen (das Auffüllen einer Schaltfläche würde sie beschädigen, da sie einen 9-Patch-Hintergrund verwendet und eine eigene Auffüllung festlegt).

Es wäre dasselbe, wenn Sie a verwenden würden LinearLayout: Der Weg, um das zu erreichen, was Sie wollen, besteht darin, das ListViewauf eine Größe = 0 und ein Gewicht = 1 und für die Schaltfläche height = wrap_content und weight = 0 zu setzen. (Wenn Sie beide auf wrap_content setzen, wie user639183 sagte, wird die Höhe nicht begrenzt ListView.)

Bigstones
quelle
Ja, es wird die ListViewHöhe des
ernazm
@ user639183 habe es gerade versucht, du hast recht Es tut mir leid, da war ich mir so sicher.
Bigstones
Ich habe das Gewicht wie vorgeschlagen geändert (vorher hatte ich ListView-Gewicht = 2 und Tastengewicht = 1, frage mich, warum dies nicht funktioniert hat?) Der Effekt ist sehr interessant: Die Taste wird jetzt nur noch halb aus dem Bildschirm gedrückt. Eigentlich kann ich es dahin bringen, wo ich es will, indem ich etwas "android: layout_marginBottom" hinzufüge. Ich könnte jedoch auch den Maxims-Ansatz ausprobieren und prüfen, ob dies auch funktioniert.
Quallen
@jellyfish: Ich weiß nicht, meine Gewissheiten wurden von @ user639183 zerstört. Die Idee ist, dass die beiden Ansichten die gesamte Höhe teilen. Die Anzahl der Aktien, die sie erhalten, ergibt sich aus ihrem Gewicht, also 1: 0 -> alles für den ersten (2: 1 würde dem zweiten 1/3 Platz geben). Ich dachte, dass das Setzen von wrap_content in einer Bildlaufansicht so hoch wie der Inhalt sein würde. Haben Sie jedoch das äußere Layout auf fill_parent gesetzt?
Bigstones
Es ist wirklich seltsam, dass ein verschachteltes RelativeLayout (wie von Maxim vorgeschlagen) nicht funktioniert. Ich könnte es einfach oben posten, da ich das Gefühl habe, dass ich gerade etwas verpasst habe ...
Quallen
2

Sie können diese Funktion wahrscheinlich mit verschachtelten Containern ausführen. Möglicherweise müssen Sie den Button in einen zweiten (inneren) Container einwickeln, damit er mehr Platz beansprucht, und den Button einfach oben am inneren Container ausrichten.

Möglich so etwas:

RelativeLayout

-- Listenansicht

- RelativeLayout

---- Taste

Wenn Sie die verschiedenen Ausrichtungsoptionen für die beiden Container verwenden, sollten Sie in der Lage sein, dies zum Laufen zu bringen.

Reich
quelle
Ich denke, die Verwendung eines relativen Layouts ist die beste Lösung, aber ich kann wirklich nicht verstehen, warum Sie verschachtelte Container verwenden würden, wenn Sie nur so etwas wie android:layout_marginTop="30dip" für die Schaltfläche verwenden können, wenn Sie beispielsweise mehr Platz zwischen der Liste und der Schaltfläche wünschen.
Adinia
In der Frage sagte der OP, dass, wenn er die Position der Schaltfläche relativ zur ListView strikt vornimmt, diese vom Bildschirm verschwindet, sobald die ListView groß genug wird. In solchen Fällen muss man mit verschachtelten Containern knifflig werden
Rich
2

Dies ist der sauberste Weg, dies zu tun:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
  <ListView
      android:id="@+id/ListView01"
      android:layout_width="fill_parent"
      android:layout_height="0dp"
      android:layout_weight="1"
      android:dividerHeight="2px">
  </ListView>
  <FrameLayout
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:background="@drawable/drawable"
      >
    <Button android:background="@drawable/btn_more2"
        android:id="@+id/moreButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:paddingRight="20px"
        />    
  </LinearLayout>
</LinearLayout>

Es ähnelt der Lösung von Angelos, aber Sie benötigen kein lineares Layout, das die ListView einschließt. Sie können auch ein FrameLayout verwenden, das im Vergleich zu einem LinearLayout leichter ist, um die Schaltfläche einzuschließen.

user2994360
quelle
2

Die Idee wird in den sehr guten Lösungen umrissen von:

Beide scheinen zumindest in Version 4.4.3 perfekt zu funktionieren.

Ich musste noch einige Zeit damit verbringen, Testcode zu schreiben, um ihn zu überprüfen und jede Methode zu bestätigen. Unten finden Sie den eigenständigen, minimalen Testcode, der erforderlich ist.


Das Layout basiert auf der Lösung von Sparkle, da es weniger verschachtelte Layouts enthält. Wurde auch aktualisiert, um die aktuellen LINT-Prüfungen widerzuspiegeln.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:context="MainActivity" >

    <ListView
        android:id="@+id/listview"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <Button
        android:id="@+id/btn"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Grow List"
        tools:ignore="HardcodedText" />

</LinearLayout>

In der Aktivität wird der Boilerplate-Code bereitgestellt, um die Lösung selbst zu testen.

public class MainActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ListView listview = (ListView)findViewById(R.id.listview);
        final ArrayAdapter<String> adapter = 
                new ArrayAdapter<String>(this,
                                         android.R.layout.simple_list_item_1,
                                         new ArrayList<String>());
        adapter.setNotifyOnChange(true);
        listview.setAdapter(adapter);

        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener()
        {

            @Override
            public void onClick(View v)
            {
                int count = adapter.getCount();
                adapter.add(String.valueOf(count));
                listview.setSelection(count);
            }
        });
    }
}

Fühlen Sie sich frei, hinzuzufügen oder zu verbessern, da dies "Community-Wiki" ist.

Richard Le Mesurier
quelle
1

Versuchen Sie, RelativeLayout mit der Schaltfläche unten zu verwenden. Stellen Sie die Höhe des Layouts auf "wrap_content" ein. Ich habe es nicht versucht. Nur eine Idee

Maxime
quelle
Ich dachte wirklich, dass dies funktionieren sollte, aber es scheint, dass es nicht funktioniert. Das Layout füllt den gesamten verbleibenden Raum aus, als ob die Höhe auf match_parent gesetzt wäre. Macht aber keinen Sinn.
Quallen
1

Fügen android:layout_weight="1"Sie in LinearLayout einfach ListView hinzu

DawnYu
quelle
0

Folgendes hat bei mir funktioniert ...

 if(adapter.getCount() > 3){
                    View item = adapter.getView(0, null, impDateListView);
                    item.measure(0, 0);         
                    LayoutParams params = impDateListView.getLayoutParams();
                    params.width = LayoutParams.MATCH_PARENT;
                    params.height = 3 * item.getMeasuredHeight();
                    impDateListView.setLayoutParams(params);


                }

Hinweis: Die params.width = ... muss auch festgelegt werden ...

Das obige Beispiel ist, wenn Sie TableRow und ListView in TableRow verwenden ...

Atul Dravid - White Pvt. GmbH.
quelle
0

Wrap-Inhalt in lineares Layout

in der Listenansicht hinzufügen: android: layout_weight = "1"

Stellen Sie in Ihrem Button eine feste Höhe ein

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical">

<ListView
    android:id="@+id/my_list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1">
</ListView>

 <Button
    android:text="Button"
    android:layout_width="match_parent"
    android:layout_height="50dp"/>

</LinearLayout>
Toma
quelle
0

Wenn Sie möchten, dass der Inhalt unter der Listenansicht nach unten verschoben wird, wenn Elemente zur Liste hinzugefügt werden, versuchen Sie diese Lösung:

Fügen Sie am unteren Rand der Listenansicht einen positiven Abstand und am oberen Rand der "Fußzeile" einen negativen Abstand hinzu. Dies funktioniert in einem linearen Layout oder einem relativen Layout.

<ListView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="50dp"/>

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="-50dp"/>
Jenny Pushkarskaya
quelle
-1

Da es kein MaxHeight-Attribut gibt, ist es am besten, entweder die Höhe der ListView auf einen festgelegten Wert festzulegen oder zu verwenden wrap_content.

Chris Cashwell
quelle
-2

Ich habe dieses Problem gelöst, indem ich die ListView in eine ScrollView eingefügt habe. Lint hat es nicht gefallen, aber wenn ich ein minHeight hinzufüge und das fillViewport auf true setze, habe ich ein schönes Ergebnis.

    <ScrollView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="1dp"
        android:layout_marginRight="1dp"
        android:minHeight="100dp"
        android:fillViewport="true"
        android:fadeScrollbars="false"
        android:paddingTop="2dp" 
        android:orientation="vertical"
        android:scrollbarAlwaysDrawVerticalTrack="true" >

        <ListView
            android:id="@+id/workoutAElistRoutines"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="fill_vertical"
            android:background="@drawable/dialog_inner_border_tan"
            android:choiceMode="singleChoice"
            android:orientation="vertical"
            android:paddingLeft="3dp"
            android:paddingRight="3dp" >

        </ListView>
    </ScrollView>        
Jon
quelle
Ich habe diesen Ansatz ausprobiert, obwohl er die Größe der Listenansicht begrenzt, lässt er mich nicht durch die Listenansicht scrollen, was umständlich ist. Weißt du, warum?
Eduardo
7
NIEMALS eine ListView in eine ScrollView einfügen!
Jenzz
Ja, fügen Sie niemals eine ListView in eine ScrollView ein. Aber mit diesem "Hack" ist es möglich ... stackoverflow.com/a/14577399/1255990
Leonardo Cardoso