Nicht scrollbare ListView in ScrollView

70

Ich versuche ein Layout wie folgt zu erstellen:

Das Problem ist, dass ich nicht möchte ListViews, dass das scrollbar ist. Ich möchte, dass sie so hoch sind, wie sie müssen, und dass der gesamte Bildschirm scrollbar ist. Wenn ich die Höhe des ListViewto einstelle wrap_content, funktioniert das nicht. Die einzige Möglichkeit, es zum Laufen zu bringen, besteht darin, eine bestimmte Höhe festzulegen - aber ich weiß nicht, wie viele Elemente sich in der befinden werden ListView.

Ich weiß, dass ich nicht ListViewhineinstecken sollteScrollView - aber ich möchte nicht, dass das ListViewBild scrollbar ist, nur um alle Elemente anzuzeigen.

Vielleicht gibt es einen besseren Weg, damit es funktioniert?

Dennis
quelle

Antworten:

155

Sie erstellen eine benutzerdefinierte Listenansicht, die nicht scrollbar ist

public class NonScrollListView extends ListView {

    public NonScrollListView(Context context) {
        super(context);
    }
    public NonScrollListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public NonScrollListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
                    Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
            ViewGroup.LayoutParams params = getLayoutParams();
            params.height = getMeasuredHeight();    
    }
}

In Ihrer Layout-Ressourcendatei

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fadingEdgeLength="0dp"
    android:fillViewport="true"
    android:overScrollMode="never"
    android:scrollbars="none" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <!-- com.Example Changed with your Package name -->

        <com.Example.NonScrollListView
            android:id="@+id/lv_nonscroll_list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
        </com.Example.NonScrollListView>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/lv_nonscroll_list" >

            <!-- Your another layout in scroll view -->

        </RelativeLayout>
    </RelativeLayout>

</ScrollView>

In der Java-Datei

Erstellen Sie ein Objekt Ihrer customListview anstelle von ListView wie folgt:
NonScrollListView non_scroll_list = (NonScrollListView) findViewById (R.id.lv_nonscroll_list);

Dedaniya HirenKumar
quelle
2
Wenn Sie dies in eine vorhandene Codebasis tauschen, muss wahrscheinlich nur das XML geändert werden, nachdem die neue Klasse hinzugefügt wurde. Die meisten vorhandenen Referenzen, auf die die Instanz übertragen wird, (ListView)sollten weiterhin einwandfrei funktionieren.
Rymo
1
@ DEV bitte geben Sie detailliert an, welche Art von Layout Sie benötigen
Dedaniya HirenKumar
3
@Dedaniyahirenkumar, wenn Android zeigt ein Layout der NonScrollListViewdie Eltern ScrollViewan die Spitze der gescrollt wird NonScrollListView, anstatt der Spitze der ScrollView. (Der Benutzer muss bis zu den ScrollViewInhalten scrollen , die vor dem stehen NonScrollListView.) Dies geschieht für EXACTLYund AT_MOSTMessmodi und für jede ganzzahlige Höhe, die ammakeMeasureSpec()
12.
4
@Dedaniyahirenkumar, Wenn jedoch der Messmodus auf geschaltet wird UNSPECIFIED, ScrollViewbleibt der Elternteil bei Bildlauf Y = Null (das erwartete Verhalten). Offensichtlich zeigt der NonScrollListViewin diesem Fall jedoch nicht den gesamten Inhalt an.
Kdbanman
1
Das ist es, wonach ich suche. Vielen Dank, Mr.Dedaniya Hiren. Es funktioniert wie ein Zauber :)
Kishan Soni
10

Es ist überhaupt nicht erforderlich, ein listviewzu verwenden.

Wenn Sie wirklich darüber nachdenken, listviewkann a LinearLayoutin Ihrem Fall durch a ersetzt werden. Das Adapterwäre das gleiche, aber anstatt den Adapter mit Ihrem zu verbinden listview, rufen Sie einfach die getViewFunktion des Adapters in einer for-Schleife für Ihre Daten auf und fügen Sie die abgerufenen Ansichten Ihrer Vertikalen hinzu linearlayout.

Dieser Ansatz wird jedoch nur empfohlen, wenn Ihre Liste eine kleine Anzahl von Elementen enthält und Ihre Anzeigedarstellung dieser Elemente nicht speicherintensiv ist.

Sam
quelle
Ich benutze lineares Layout anstelle der Listenansicht, es funktioniert, aber Elemente, die keinen Platz haben, werden nicht gesehen! Ich benutze lineares Layout in Eltern
Hossein
LinearLayoutist kein fairer Ersatz für den ListViewFall, dass Sie die Güte dahinter nutzen möchten AbsListView.CHOICE_MODE_MULTIPLE_MODAL- um eine Neuerfindung des Rades zu vermeiden, NonScrollListView
lesen
Ich denke, dass das Ersetzen von ListView durch LinearLayout logisch erscheint, aber Sie verlieren auch die Recyclingfähigkeit, die einer ListView innewohnt. Versuchen Sie, ein LinearLayout zu haben, und laden Sie es dynamisch auf, indem Sie viele Ansichten darin aufblasen.
Müllsammler
2

Der beste Weg, dies zu tun (im Jahr 2017), ist die Verwendung von a RecyclerViewmit a NestedScrollView.

Keine Hacks erforderlich und es funktioniert sofort so, wie Sie es möchten.

Anthony Chuinard
quelle
1
Das ist zwar eine gute Lösung, aber ich glaube nicht, dass es das ist, was das OP wollteThe problem is that I don't want the ListViews to be scrollable
Dan
0

Nun, es gibt einen coolen Android-Typ namens Mark Murphy alias CommonsWare, der eine sehr nützliche Komponente namens CWAC Merge Adapter erstellt hat , mit der Sie tun können, was Sie brauchen. Sie müssen die Ansichten dynamisch und nicht aus XML hinzufügen. Aber angesichts Ihrer einfachen Benutzeroberfläche sollte das kein Problem sein. Ich verwende es für solche Fälle, in denen ich keine Ahnung habe, welche Art von Daten ich scrollen soll.

Wenn Sie wollen , dass es nicht verwenden (aus Gründen , die Lizenzierung vielleicht), können Sie ein einzelnes Listview haben es (anstelle dieser zwei aufeinander folgenden Listenansichten) und überschreiben getItemViewsCount, getItemViewTypeund getViewum über das Layout zu geben. Wenn Sie android listview different rowsbei Google suchen, finden Sie nützliche Informationen. Zum Beispiel dieser Link oder dieser .

Ich würde mich jedoch für einen Merge-Adapter entscheiden.

Gunar
quelle
Vielen Dank. Das Problem ist, dass ich möchte, dass ImageView und TextView scrollbar sind. Wenn ich nach unten scrolle, werden sie nach oben verschoben und die Elemente in der ListView werden angezeigt.
Dennis
Verwenden Sie dann den Zusammenführungsadapter und fügen Sie dort ImageView und TextView hinzu. Selbst mit mehreren Listentypen können Sie dasselbe tun, indem Sie den Ansichtstyp für ImageView und TextView auf 1 und 2 setzen. Für den Rest der Typen könnten Sie 3 und 4 haben.
gunar
0

Ich habe eine einfache Lösung, wenn es möglich ist, die Höhe / Breite Ihres Elements zu berechnen ... Sie müssen nur ein übergeordnetes lineares Layout von ListView erstellen und dann die übergeordnete Höhe von Java aus festlegen.

Geben Sie hier die Bildbeschreibung ein

Angenommen, Sie müssen diese Ansicht entwerfen ... Jetzt wird die Größe des übergeordneten Layouts aus Java definiert ...

final LinearLayout parent=(LinearLayout)findViewById(R.id.parent);
final ListView  listview=(ListView)findViewById(R.id.listview);
parent.setLayoutParams(new LinearLayout.LayoutParams(parent.getLayoutParams().width, dpToPx( number_of_item_in_list * per_item_size_in_dp )));
//number_of_item_in_list is list side ~ listArray.size();
//per_item_size_in_dp = calculate item size in dp. Ex: 80dp

public static int dpToPx(int dp)
{
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}

das ist alles :)

Shohan Ahmed Sijan
quelle
0

Wählen Sie die ListView aus, für die Sie einen Bildlauf durchführen möchten, und fügen Sie anschließend die Methode 'setOnTouchListener' hinzu, damit das System den Bildlauf automatisch in die ListView einfügt

final ListView listview = (ListView) findViewById(R.id.list);


    listview.setOnTouchListener(new ListView.OnTouchListener()
    {
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            int action = event.getAction();
            switch (action)
            {
                case MotionEvent.ACTION_DOWN:
                    // Disallow ScrollView to intercept touch events.
                    v.getParent().requestDisallowInterceptTouchEvent(true);
                    break;

                case MotionEvent.ACTION_UP:
                    // Allow ScrollView to intercept touch events.
                    v.getParent().requestDisallowInterceptTouchEvent(false);
                    break;
            }

            // Handle ListView touch events.
            v.onTouchEvent(event);
            return true;
        }
    });
    listview.setClickable(true);

Ich hoffe das funktioniert bei dir

Houssem Cherif
quelle