ฉันจะใส่ ListView ลงใน ScrollView โดยไม่ยุบได้อย่างไร


351

ฉันค้นหาวิธีแก้ไขปัญหานี้แล้วและคำตอบเดียวที่ฉันสามารถหาได้คือ " อย่าใส่ ListView ลงใน ScrollView " ฉันยังไม่เห็นคำอธิบายที่แท้จริงว่าทำไมถึงเป็นเช่นนั้น เหตุผลเดียวที่ฉันสามารถค้นหาได้คือ Google ไม่คิดว่าคุณควรจะทำเช่นนั้น ฉันก็ทำเช่นนั้น

ดังนั้นคำถามคือคุณจะวาง ListView ลงใน ScrollView โดยไม่ยุบลงไปจนถึงความสูงขั้นต่ำได้อย่างไร


11
เนื่องจากเมื่ออุปกรณ์ใช้หน้าจอสัมผัสจึงไม่มีวิธีที่ดีในการแยกความแตกต่างระหว่างคอนเทนเนอร์แบบเลื่อนซ้อนสองจุด มันทำงานบนเดสก์ท็อปแบบดั้งเดิมที่คุณใช้แถบเลื่อนเพื่อเลื่อนคอนเทนเนอร์
Romain Guy

57
แน่นอนว่ามี หากพวกเขาสัมผัสข้างในด้านในเลื่อนที่ ถ้าด้านในใหญ่เกินไปนั่นเป็นการออกแบบ UI ที่ไม่ดี ไม่ได้หมายความว่ามันเป็นความคิดที่ไม่ดีโดยทั่วไป
DougW

5
เพิ่งสะดุดกับสิ่งนี้สำหรับแอปแท็บเล็ตของฉัน ในขณะที่ดูเหมือนว่าจะไม่ได้แย่ไปกว่าสมาร์ทโฟน แต่มันก็น่ากลัวบนแท็บเล็ตที่คุณสามารถตัดสินใจได้อย่างง่ายดายว่าผู้ใช้ต้องการเลื่อน ScrollView ด้านนอกหรือด้านใน @DougW: การออกแบบที่น่ากลัวฉันเห็นด้วย
แมงกะพรุน

4
@Romain - นี่เป็นโพสต์ที่ค่อนข้างเก่าดังนั้นฉันสงสัยว่าความกังวลที่นี่ได้รับการแก้ไขแล้วหรือยังไม่มีวิธีที่ดีในการใช้ ListView ภายใน ScrollView (หรือทางเลือกที่ไม่เกี่ยวข้องกับการเข้ารหัสด้วยตนเอง นิพจน์ทั้งหมดของ ListView ให้เป็น LinearLayout)?
จิม

3
@ Jim: "หรืออีกทางเลือกหนึ่งที่ไม่เกี่ยวข้องกับการเข้ารหัสด้วยตนเอง nicities ทั้งหมดของ ListView ลง LinearLayout" - ListViewใส่ทุกอย่างที่อยู่ภายใน ListViewสามารถมีสไตล์แถวได้หลายแบบรวมถึงแถวที่ไม่สามารถเลือกได้
CommonsWare

คำตอบ:


196

การใช้ที่จะทำให้มันไม่เลื่อนที่มีราคาแพงมากและไปกับวัตถุประสงค์ทั้งListView ListViewคุณไม่ควรทำเช่นนี้ เพียงใช้LinearLayoutแทน


69
แหล่งที่มาจะเป็นฉันตั้งแต่ฉันได้รับผิดชอบ ListView สำหรับ 2 หรือ 3 ปีที่ผ่านมา :) ListView ทำงานพิเศษมากมายเพื่อเพิ่มประสิทธิภาพการใช้อะแดปเตอร์ การพยายามหลีกเลี่ยงปัญหานี้จะทำให้ ListView ทำงานเป็นจำนวนมากซึ่ง LinearLayout จะไม่ต้องทำ ฉันจะไม่เข้าไปดูรายละเอียดเพราะที่นี่มีพื้นที่ไม่เพียงพอที่จะอธิบายการใช้งาน ListView สิ่งนี้จะไม่แก้ไขวิธีที่ ListView ทำงานเกี่ยวกับกิจกรรมการแตะ นอกจากนี้ยังไม่มีการรับประกันว่าหากแฮ็คของคุณใช้งานได้ในวันนี้มันจะยังคงใช้งานได้ในอนาคต การใช้ LinearLayout อาจไม่ได้ผลมากนัก
Romain Guy

7
นั่นเป็นคำตอบที่สมเหตุสมผล ถ้าฉันสามารถแบ่งปันความคิดเห็นได้ฉันมีประสบการณ์ iPhone ที่สำคัญกว่ามากและฉันสามารถบอกคุณได้ว่าเอกสารของ Apple นั้นเขียนได้ดีกว่าในแง่ของคุณลักษณะด้านประสิทธิภาพและการใช้เคส (หรือรูปแบบต่อต้าน) เช่นนี้ โดยรวมแล้วเอกสาร Android มีการกระจายมากขึ้นและมุ่งเน้นน้อย ฉันเข้าใจว่ามีเหตุผลบางอย่างที่อยู่เบื้องหลัง แต่ก็เป็นการสนทนาที่ยาวนานดังนั้นหากคุณรู้สึกว่าถูกบังคับให้แชทเกี่ยวกับเรื่องนี้โปรดแจ้งให้เราทราบ
DougW

6
คุณสามารถเขียนวิธีสแตติกที่สร้าง LinearLayout จากอะแดปเตอร์ได้อย่างง่ายดาย
Romain Guy

125
นี่ไม่ใช่คำตอบสำหรับHow can I put a ListView into a ScrollView without it collapsing?... คุณสามารถบอกได้ว่าคุณไม่ควรทำ แต่ให้คำตอบว่าจะทำอย่างไรนั่นคือคำตอบที่ดี คุณรู้ว่า ListView มีคุณสมบัติเจ๋ง ๆ นอกเหนือจากการเลื่อนคุณสมบัติที่ LinearLayout ไม่มี
Jorge Fuentes González

44
ถ้าคุณมีพื้นที่ที่มี ListView + มุมมองอื่นและคุณต้องการให้ทุกอย่างเลื่อนเป็นหนึ่ง ดูเหมือนว่าจะเป็นกรณีการใช้งานที่เหมาะสมสำหรับการวาง ListView ภายใน ScrollView การแทนที่ ListView ด้วย LinearLayout ไม่ใช่วิธีแก้ปัญหาเพราะคุณจะไม่สามารถใช้อะแดปเตอร์ได้
Barry Fruitman

262

นี่คือทางออกของฉัน ฉันค่อนข้างใหม่สำหรับแพลตฟอร์ม Android และฉันแน่ใจว่านี่ค่อนข้างแฮ็คโดยเฉพาะอย่างยิ่งในส่วนที่เกี่ยวกับการโทร. การวัดโดยตรงและการตั้งค่าLayoutParams.heightคุณสมบัติโดยตรง แต่ก็ใช้งานได้

สิ่งที่คุณต้องทำคือโทรออกUtility.setListViewHeightBasedOnChildren(yourListView)และมันจะถูกปรับขนาดเพื่อรองรับความสูงของรายการ

public class Utility {
    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) {
            // pre-condition
            return;
        }

        int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();

        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            if (listItem instanceof ViewGroup) {
                listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
             }

             listItem.measure(0, 0);
             totalHeight += listItem.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
    }
}

66
คุณเพิ่งสร้าง LinearLayout ที่มีราคาแพงมาก :)
Romain Guy

82
ยกเว้น a LinearLayoutไม่มีนิพจน์ที่เป็นธรรมชาติทั้งหมดListView- ไม่มีตัวแบ่งมุมมองส่วนหัว / ส่วนท้ายตัวเลือกรายการที่ตรงกับสีธีมของโทรศัพท์ UI ฯลฯ จริงๆแล้วไม่มีเหตุผลที่คุณไม่สามารถเลื่อน ที่บรรจุด้านในจนกระทั่งถึงจุดสิ้นสุดจากนั้นให้หยุดการดักเหตุการณ์แบบสัมผัสเพื่อให้ภาชนะด้านนอกเลื่อน เบราว์เซอร์เดสก์ท็อปทุกตัวทำสิ่งนี้เมื่อคุณใช้ล้อเลื่อน Android สามารถจัดการกับการเลื่อนแบบซ้อนหากคุณนำทางผ่านแทร็กบอลดังนั้นทำไมไม่ลองสัมผัส
Neil Traft

29
listItem.measure(0,0)จะโยน NPE หาก listItem เป็นอินสแตนซ์ของ ViewGroup ฉันเพิ่มต่อไปนี้ก่อนlistItem.measure:if (listItem instanceof ViewGroup) listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
Siklab.ph

4
แก้ไขสำหรับรายการมุมมองที่มีการเติมนอกเหนือจาก 0:int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
พอล

8
น่าเสียดายที่วิธีการนี้มีข้อบกพร่องเล็กน้อยเมื่อListViewสามารถมีรายการของความสูงของตัวแปรได้ การเรียกเพื่อgetMeasuredHeight()ส่งกลับความสูงขั้นต่ำที่กำหนดเป้าหมายซึ่งตรงข้ามกับความสูงจริง ฉันลองใช้getHeight()แทน แต่จะได้ผลลัพธ์เป็น 0 มีใครบ้างที่เข้าใจวิธีการเข้าถึงนี้หรือไม่
Matt Huggins

89

งานนี้จะแน่นอน ............
คุณต้องเพียงแทนที่ของคุณ<ScrollView ></ScrollView>ในรูปแบบไฟล์ XML กับเรื่องนี้Custom ScrollViewเช่น <com.tmd.utils.VerticalScrollview > </com.tmd.utils.VerticalScrollview >

package com.tmd.utils;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ScrollView;

public class VerticalScrollview extends ScrollView{

    public VerticalScrollview(Context context) {
        super(context);
    }

     public VerticalScrollview(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public VerticalScrollview(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final int action = ev.getAction();
        switch (action)
        {
            case MotionEvent.ACTION_DOWN:
                    Log.i("VerticalScrollview", "onInterceptTouchEvent: DOWN super false" );
                    super.onTouchEvent(ev);
                    break;

            case MotionEvent.ACTION_MOVE:
                    return false; // redirect MotionEvents to ourself

            case MotionEvent.ACTION_CANCEL:
                    Log.i("VerticalScrollview", "onInterceptTouchEvent: CANCEL super false" );
                    super.onTouchEvent(ev);
                    break;

            case MotionEvent.ACTION_UP:
                    Log.i("VerticalScrollview", "onInterceptTouchEvent: UP super false" );
                    return false;

            default: Log.i("VerticalScrollview", "onInterceptTouchEvent: " + action ); break;
        }

        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        super.onTouchEvent(ev);
        Log.i("VerticalScrollview", "onTouchEvent. action: " + ev.getAction() );
         return true;
    }
}

4
นี่เป็นสิ่งที่ดีมาก นอกจากนี้ยังทำให้สามารถใส่ Google Maps Fragment ไว้ใน ScrollView และยังใช้งานการซูมเข้า / ออกได้ ขอบคุณ
แมกนัส Johansson

มีใครสังเกตเห็นข้อเสียใด ๆ กับวิธีการนี้หรือไม่? มันง่ายมากฉันกลัว: o
Marija Milosevic

1
ทางออกที่ดีควรเป็นคำตอบที่ได้รับการยอมรับ +1! ฉันได้ผสมกับคำตอบด้านล่าง (จาก djunod) และใช้งานได้ดี!
tanou

1
นี่คือการแก้ไขเดียวที่ทำให้การเลื่อนและคลิกบนเด็ก ๆ ทำงานพร้อมกันสำหรับฉัน ขอบคุณมาก
pellyadolfo

25

insted ของการวางListViewภายในScrollViewเราสามารถใช้เป็นListView ScrollViewสิ่งที่จะต้องมีในสามารถใส่ภายในListView ListViewรูปแบบอื่น ๆ อยู่ด้านบนและด้านล่างของที่สามารถใส่ได้โดยการเพิ่มรูปแบบไปยังส่วนหัวและส่วนท้ายของListView ListViewดังนั้นทั้งหมดListViewจะให้ประสบการณ์การเลื่อน


3
นี่คือคำตอบที่หรูหราและเหมาะสมที่สุด สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการนี้ให้ดูคำตอบนี้: stackoverflow.com/a/20475821/1221537
adamdport

21

มีมากมายสถานการณ์ที่ทำให้รู้สึกว่ามี ListView ใน ScrollView

นี่คือรหัสตามข้อเสนอแนะของ DougW ... ทำงานเป็นส่วน ๆ ใช้หน่วยความจำน้อยกว่า

public static void setListViewHeightBasedOnChildren(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null) {
        return;
    }
    int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
    int totalHeight = 0;
    View view = null;
    for (int i = 0; i < listAdapter.getCount(); i++) {
        view = listAdapter.getView(i, view, listView);
        if (i == 0) {
            view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, LayoutParams.WRAP_CONTENT));
        }
        view.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
        totalHeight += view.getMeasuredHeight();
    }
    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    listView.setLayoutParams(params);
    listView.requestLayout();
}

เรียก setListViewHeightBasedOnChildren (listview) ในแต่ละ listview แบบฝัง


มันจะไม่ทำงานเมื่อลิสต์รายการมีขนาดผันแปรเช่นบาง textview ที่ขยายข้ามหลายบรรทัด ทางออกใด ๆ
Khobaib

ตรวจสอบความคิดเห็นของฉันที่นี่ - มันให้ทางออกที่สมบูรณ์แบบ - stackoverflow.com/a/23315696/1433187
Khobaib

ทำงานกับฉันด้วย API 19 แต่ไม่ใช่กับ API 23: ที่นี่เพิ่มพื้นที่สีขาวด้านล่าง listView
Lucker10

17

ListView จริง ๆ แล้วสามารถวัดตัวเองให้สูงพอที่จะแสดงรายการทั้งหมด แต่ไม่ได้ทำเมื่อคุณระบุ wrap_content (MeasureSpec.UNSPECIFIED) มันจะทำเช่นนี้เมื่อให้ความสูงกับ MeasureSpec.AT_MOST ด้วยความรู้นี้คุณสามารถสร้างคลาสย่อยที่ง่ายมากในการแก้ปัญหานี้ซึ่งทำงานได้ดีกว่าวิธีแก้ปัญหาใด ๆ ที่โพสต์ข้างต้น คุณยังควรใช้ wrap_content กับคลาสย่อยนี้

public class ListViewForEmbeddingInScrollView extends ListView {
    public ListViewForEmbeddingInScrollView(Context context) {
        super(context);
    }

    public ListViewForEmbeddingInScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ListViewForEmbeddingInScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 4, MeasureSpec.AT_MOST));
    }
}

การจัดการ heightMeasureSpec ให้เป็น AT_MOST ที่มีขนาดใหญ่มาก (Integer.MAX_VALUE >> 4) ทำให้ ListView วัดลูกทั้งหมดของมันจนถึงความสูงที่กำหนด (ใหญ่มาก) และตั้งค่าความสูงตามนั้น

สิ่งนี้ทำงานได้ดีกว่าโซลูชันอื่น ๆ ด้วยเหตุผลบางประการ:

  1. มันวัดทุกอย่างถูกต้อง (padding, dividers)
  2. มันวัด ListView ในระหว่างการวัดผ่าน
  3. เนื่องจาก # 2 มันจัดการการเปลี่ยนแปลงความกว้างหรือจำนวนรายการอย่างถูกต้องโดยไม่ต้องมีรหัสเพิ่มเติมใด ๆ

ในข้อเสียคุณสามารถยืนยันว่าการทำเช่นนี้ขึ้นอยู่กับพฤติกรรมที่ไม่มีเอกสารใน SDK ซึ่งสามารถเปลี่ยนแปลงได้ ในอีกทางหนึ่งคุณอาจโต้แย้งว่านี่เป็นวิธีที่ wrap_content ควรทำงานกับ ListView และพฤติกรรมของ wrap_content ปัจจุบันเสีย

หากคุณกังวลว่าพฤติกรรมนี้อาจเปลี่ยนแปลงได้ในอนาคตคุณควรคัดลอกฟังก์ชัน onMeasure และฟังก์ชั่นที่เกี่ยวข้องออกจาก ListView.java และลงในคลาสย่อยของคุณเอง

โดยวิธีการที่ฉันเชื่อว่านี่เป็นวิธีที่ถูกต้องสมบูรณ์แบบเมื่อคุณทำงานกับรายการจำนวนน้อย อาจไม่มีประสิทธิภาพเมื่อเปรียบเทียบกับ LinearLayout แต่เมื่อจำนวนรายการมีขนาดเล็กการใช้ LinearLayout เป็นการเพิ่มประสิทธิภาพที่ไม่จำเป็นดังนั้นจึงมีความซับซ้อนที่ไม่จำเป็น


ทำงานร่วมกับรายการความสูงที่ผันแปรได้ใน listview!
Denny

@Jason Y Integer.MAX_VALUE >> 4 หมายถึงอะไร ?? 4 คืออะไร
KJEjava48

@Jason Y สำหรับฉันมันใช้งานได้หลังจากเปลี่ยน Integer.MAX_VALUE >> 2 เป็น Integer.MAX_VALUE >> 21 เท่านั้น ทำไมถึงเป็นเช่นนั้น? นอกจากนี้ยังใช้งานได้กับ ScrollView ไม่ใช่กับ NestedScrollView
KJEjava48

13

มีการตั้งค่าในตัวสำหรับมัน บน ScrollView:

android:fillViewport="true"

ในชวา

mScrollView.setFillViewport(true);

Romain Guy อธิบายในเชิงลึกที่นี่: http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/


2
นั่นใช้ได้กับ LinearLayout ในขณะที่เขาสาธิต มันไม่ทำงานสำหรับ ListView ตามวันที่โพสต์นั้นฉันจินตนาการว่าเขาเขียนเพื่อให้เป็นตัวอย่างของทางเลือกของเขา แต่สิ่งนี้ไม่ตอบคำถาม
DougW

นี่เป็นวิธีแก้ปัญหาอย่างรวดเร็ว

10

คุณสร้าง ListView แบบกำหนดเองซึ่งไม่สามารถเลื่อนได้

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

ในไฟล์ทรัพยากรเค้าโครงของคุณ

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

ในไฟล์ Java

สร้างวัตถุของ customListview ของคุณแทน ListView เช่น: NonScrollListView non_scroll_list = (NonScrollListView) findViewById (R.id.lv_nonscroll_list);


8

เราไม่สามารถใช้การเลื่อนแบบสอง simulteniuosly เราจะได้ความยาวทั้งหมดของ ListView และขยาย listview ด้วยความสูงทั้งหมดจากนั้นเราสามารถเพิ่ม ListView ใน ScrollView โดยตรงหรือใช้ LinearLayout เนื่องจาก ScrollView มีลูกหนึ่งคนโดยตรง คัดลอก setListViewHeightBasedOnChildren (lv) วิธีการในรหัสของคุณและขยาย listview แล้วคุณสามารถใช้ listview ภายใน scrollview \ layout xml file

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
 <ScrollView

        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
         android:background="#1D1D1D"
        android:orientation="vertical"
        android:scrollbars="none" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="#1D1D1D"
            android:orientation="vertical" >

            <TextView
                android:layout_width="fill_parent"
                android:layout_height="40dip"
                android:background="#333"
                android:gravity="center_vertical"
                android:paddingLeft="8dip"
                android:text="First ListView"
                android:textColor="#C7C7C7"
                android:textSize="20sp" />

            <ListView
                android:id="@+id/first_listview"
                android:layout_width="260dp"
                android:layout_height="wrap_content"
                android:divider="#00000000"
               android:listSelector="#ff0000"
                android:scrollbars="none" />

               <TextView
                android:layout_width="fill_parent"
                android:layout_height="40dip"
                android:background="#333"
                android:gravity="center_vertical"
                android:paddingLeft="8dip"
                android:text="Second ListView"
                android:textColor="#C7C7C7"
                android:textSize="20sp" />

            <ListView
                android:id="@+id/secondList"
                android:layout_width="260dp"
                android:layout_height="wrap_content"
                android:divider="#00000000"
                android:listSelector="#ffcc00"
                android:scrollbars="none" />
  </LinearLayout>
  </ScrollView>

   </LinearLayout>

วิธีการ onCreate ในชั้นเรียนกิจกรรม:

 import java.util.ArrayList;
  import android.app.Activity;
 import android.os.Bundle;
 import android.view.Menu;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.ListAdapter;
  import android.widget.ListView;

   public class MainActivity extends Activity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.listview_inside_scrollview);
    ListView list_first=(ListView) findViewById(R.id.first_listview);
    ListView list_second=(ListView) findViewById(R.id.secondList);
    ArrayList<String> list=new ArrayList<String>();
    for(int x=0;x<30;x++)
    {
        list.add("Item "+x);
    }

       ArrayAdapter<String> adapter=new ArrayAdapter<String>(getApplicationContext(), 
          android.R.layout.simple_list_item_1,list);               
      list_first.setAdapter(adapter);

     setListViewHeightBasedOnChildren(list_first);

      list_second.setAdapter(adapter);

    setListViewHeightBasedOnChildren(list_second);
   }



   public static void setListViewHeightBasedOnChildren(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null) {
        // pre-condition
        return;
    }

    int totalHeight = 0;
    for (int i = 0; i < listAdapter.getCount(); i++) {
        View listItem = listAdapter.getView(i, null, listView);
        listItem.measure(0, 0);
        totalHeight += listItem.getMeasuredHeight();
    }

    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight
            + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    listView.setLayoutParams(params);
      }

ดีแก้ไข! มันทำงานได้ตามต้องการ ขอบคุณ ในกรณีของฉันฉันมีมุมมองทั้งกลุ่มก่อนรายการและวิธีแก้ปัญหาที่สมบูรณ์แบบคือมีการเลื่อนแนวตั้งเพียงครั้งเดียวในมุมมอง
Proverbio

4

นี่คือการรวมกันของคำตอบโดย DougW, Good Guy Greg และ Paul ฉันพบว่ามันจำเป็นทั้งหมดเมื่อพยายามใช้สิ่งนี้กับอะแดปเตอร์ listview ที่กำหนดเองและรายการที่ไม่ได้มาตรฐานมิฉะนั้น listview จะทำให้แอปพลิเคชันชนกัน

public void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) {
            return;
        }

        int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            if (listItem instanceof ViewGroup)
                listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
            listItem.measure(0, 0);
            totalHeight += listItem.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
    }

จะเรียกวิธีนี้ได้ที่ไหน
Dhrupal

หลังจากสร้าง listview และตั้งค่าอะแดปเตอร์
รถเข็นที่ถูกยกเลิก

สิ่งนี้ช้าเกินไปสำหรับรายการที่มีความยาว
cakan

@cakan มันถูกเขียนขึ้น 2 ปีก่อนหน้านี้เพื่อให้สามารถใช้ส่วนประกอบ UI บางอย่างร่วมกันซึ่งไม่ได้หมายถึงการรวมกัน คุณกำลังเพิ่มค่าใช้จ่ายที่ไม่จำเป็นใน Android ที่ทันสมัยดังนั้นจึงคาดว่ารายการจะช้าลงเมื่อมันใหญ่ขึ้น
รถเข็นที่ถูกทิ้งร้าง

3

คุณไม่ควรใส่ ListView ใน ScrollView เนื่องจาก ListView นั้นเป็นเป็น ScrollView ดังนั้นจะเหมือนกับใส่ ScrollView ใน ScrollView

คุณพยายามทำอะไรให้สำเร็จ


4
ฉันพยายามทำให้ ListView ภายใน ScrollView สำเร็จ ฉันไม่ต้องการให้ ListView ของฉันสามารถเลื่อนได้ แต่ไม่มีคุณสมบัติที่ง่ายในการตั้งค่า myListView.scrollEnabled = false;
DougW

ดังที่ Romain Guy กล่าวว่านี่ไม่ใช่จุดประสงค์ของ ListView ListView เป็นมุมมองที่ได้รับการปรับให้เหมาะสมสำหรับการแสดงรายการที่มีความยาวพร้อมตรรกะที่ซับซ้อนมากมายในการโหลดมุมมองที่ขี้เกียจ, ใช้มุมมองที่นำมาใช้ซ้ำและอื่น ๆ สิ่งนี้ไม่มีเหตุผลถ้าคุณกำลังบอก ListView หากคุณต้องการรายการจำนวนมากในคอลัมน์แนวตั้งให้ใช้ LinearLayout
Cheryl Simon

9
ปัญหาคือมีวิธีการแก้ปัญหาหลายประการที่ ListView ให้บริการรวมถึงโซลูชันที่คุณพูดถึง ฟังก์ชั่นส่วนใหญ่ที่ Adapters ทำให้ง่ายขึ้นนั้นเกี่ยวกับการจัดการและควบคุมข้อมูล IMO ควรจะเป็น ListView แบบง่ายและซับซ้อนกว่าที่จะนำรายการและสิ่งต่างๆกลับมาใช้ใหม่
DougW

2
เห็นด้วยอย่างแน่นอน โปรดทราบว่ามันเป็นเรื่องง่ายที่จะใช้อะแดปเตอร์ที่มีอยู่กับ LinearLayout แต่ฉันต้องการทุกสิ่งที่ดีที่ ListView ให้ไว้เช่นตัวหารและฉันไม่รู้สึกอยากนำไปใช้ด้วยตนเอง
Artem Russakovskii

1
@ArtemRussakovskii คุณช่วยอธิบายวิธีง่าย ๆ ในการเปลี่ยน ListView เป็น LinearLayout ด้วยอะแดปเตอร์ที่มีอยู่ได้หรือไม่?
happyhardik

3

ฉันแปลง @ DougW's Utilityเป็น C # (ใช้ใน Xamarin) รายการต่อไปนี้ใช้งานได้ดีสำหรับรายการที่มีความสูงคงที่ในรายการและจะดีมากหรืออย่างน้อยก็เป็นการเริ่มต้นที่ดีถ้ามีบางรายการที่ใหญ่กว่ารายการมาตรฐานเล็กน้อย

// You will need to put this Utility class into a code file including various
// libraries, I found that I needed at least System, Linq, Android.Views and 
// Android.Widget.
using System;
using System.Linq;
using Android.Views;
using Android.Widget;

namespace UtilityNamespace  // whatever you like, obviously!
{
    public class Utility
    {
        public static void setListViewHeightBasedOnChildren (ListView listView)
        {
            if (listView.Adapter == null) {
                // pre-condition
                return;
            }

            int totalHeight = listView.PaddingTop + listView.PaddingBottom;
            for (int i = 0; i < listView.Count; i++) {
                View listItem = listView.Adapter.GetView (i, null, listView);
                if (listItem.GetType () == typeof(ViewGroup)) {
                    listItem.LayoutParameters = new LinearLayout.LayoutParams (ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
                }
                listItem.Measure (0, 0);
                totalHeight += listItem.MeasuredHeight;
            }

            listView.LayoutParameters.Height = totalHeight + (listView.DividerHeight * (listView.Count - 1));
        }
    }
}

ขอบคุณ @DougW นี่ทำให้ฉันออกจากที่ จำกัด เมื่อฉันต้องทำงานกับรหัสของ OtherPeople :-)


คำถามหนึ่ง: คุณเรียกsetListViewHeightBasedOnChildren()วิธีการเมื่อใด เพราะมันใช้งานไม่ได้ตลอดเวลาสำหรับฉัน
Alexandre D.

@AlexandreD คุณเรียกใช้ Utility.setListViewHeightBasedOnChildren (yourListView) เมื่อคุณสร้างรายการของรายการ นั่นคือให้แน่ใจว่าคุณได้สร้างรายการของคุณก่อน! ฉันพบว่าฉันกำลังสร้างรายการและฉันยังแสดงรายการของฉันใน Console.WriteLine ... แต่อย่างใดรายการที่อยู่ในขอบเขตที่ไม่ถูกต้อง เมื่อฉันคิดออกและมั่นใจว่าฉันมีขอบเขตที่เหมาะสมสำหรับรายการของฉันนี้ทำงานเหมือนมีเสน่ห์
Phil Ryan

ความจริงก็คือรายการของฉันถูกสร้างขึ้นใน ViewModel ของฉัน ฉันจะรอได้อย่างไรว่ารายการของฉันจะถูกสร้างขึ้นในมุมมองของฉันก่อนที่จะเรียกไปที่ Utility.setListViewHeightBasedOnChildren (yourListView)?
Alexandre D.

3

นี่เป็นสิ่งเดียวที่ทำงานให้ฉัน:

บน Lollipop เป็นต้นไปคุณสามารถใช้

yourtListView.setNestedScrollingEnabled(true);

การเปิดใช้งานหรือปิดใช้งานการเลื่อนแบบซ้อนสำหรับมุมมองนี้หากคุณต้องการความเข้ากันได้แบบย้อนหลังกับระบบปฏิบัติการรุ่นเก่าคุณจะต้องใช้ RecyclerView


สิ่งนี้ไม่มีผลต่อมุมมองรายการของฉันใน API 22 ใน DialogFragment ในกิจกรรม AppCompat พวกเขายังคงพังทลาย คำตอบของ @Phil Ryan ทำงานได้ดีกับการปรับเปลี่ยนเล็กน้อย
Hakan Çelik MK1

3

ก่อนที่มันเป็นไปไม่ได้ แต่ด้วยการเปิดตัว Appcompat ใหม่และการออกแบบห้องสมุดนี้สามารถทำได้

คุณต้องใช้ NestedScrollView https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html

ฉันไม่ทราบว่ามันจะทำงานร่วมกับ Listview หรือไม่ แต่ทำงานกับ RecyclerView

ตัวอย่างโค้ด:

<android.support.v4.widget.NestedScrollView 
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

</android.support.v4.widget.NestedScrollView>

เยี่ยมฉันไม่ได้ลองใช้ดังนั้นฉันไม่สามารถยืนยันได้ว่า ListView ภายในไม่ยุบ แต่ดูเหมือนว่าอาจเป็นเจตนา เสียใจอย่างสุดซึ้งที่จะไม่เห็น Romain Guy ในบันทึกการตำหนิ;)
DougW

1
สิ่งนี้ใช้ได้กับ recyclerView แต่ไม่ใช่ listView Thanx
IgniteCoders

2

เฮ้ฉันมีปัญหาที่คล้ายกัน ฉันต้องการแสดงมุมมองรายการที่ไม่ได้เลื่อนและฉันพบว่าการจัดการพารามิเตอร์ทำงาน แต่ไม่มีประสิทธิภาพและจะทำงานแตกต่างกันในอุปกรณ์ที่แตกต่างกัน .. ดังนั้นนี่คือชิ้นส่วนของรหัสกำหนดการซึ่งจริงๆแล้วมันมีประสิทธิภาพมาก .

db = new dbhelper(this);

 cursor = db.dbCursor();
int count = cursor.getCount();
if (count > 0)
{    
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.layoutId);
startManagingCursor(YOUR_CURSOR);

YOUR_ADAPTER(**or SimpleCursorAdapter **) adapter = new YOUR_ADAPTER(this,
    R.layout.itemLayout, cursor, arrayOrWhatever, R.id.textViewId,
    this.getApplication());

int i;
for (i = 0; i < count; i++){
  View listItem = adapter.getView(i,null,null);
  linearLayout.addView(listItem);
   }
}

หมายเหตุ: หากคุณใช้สิ่งนี้notifyDataSetChanged();จะไม่ทำงานตามที่ตั้งใจเพราะมุมมองจะไม่ถูกวาดใหม่ ทำเช่นนี้หากคุณต้องการแก้ไข

adapter.registerDataSetObserver(new DataSetObserver() {

            @Override
            public void onChanged() {
                super.onChanged();
                removeAndRedrawViews();

            }

        });

2

มีสองปัญหาเมื่อใช้ ListView ภายใน ScrollView

1- ListView จะต้องขยายจนสุดระดับความสูง ListView นี้แก้ไขสิ่งนี้:

public class ListViewExpanded extends ListView
{
    public ListViewExpanded(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        setDividerHeight(0);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST));
    }
}

ความสูงของตัวคั่นต้องเป็น 0 ใช้การขยายเป็นแถวแทน

2- ListView ใช้กิจกรรมการสัมผัสเพื่อให้ ScrollView ไม่สามารถเลื่อนได้ตามปกติ ScrollView นี้แก้ไขปัญหานี้:

public class ScrollViewInterceptor extends ScrollView
{
    float startY;

    public ScrollViewInterceptor(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e)
    {
        onTouchEvent(e);
        if (e.getAction() == MotionEvent.ACTION_DOWN) startY = e.getY();
        return (e.getAction() == MotionEvent.ACTION_MOVE) && (Math.abs(startY - e.getY()) > 50);
    }
}

นี่เป็นวิธีที่ดีที่สุดที่ฉันพบว่าทำเคล็ดลับ!


2

วิธีที่ฉันใช้คือเพื่อเพิ่มเนื้อหาทั้งหมดของ ScrollView (สิ่งที่ควรอยู่ด้านบนและใต้ listView) เป็น headerView และ footerView ใน ListView

ดังนั้นจึงใช้งานได้เช่นกันโปรแกรมแปลงสภาพจะถูกปรับแต่งว่าควรเป็นอย่างไร


1

ขอบคุณโค้ดของ Vinayที่นี่คือรหัสของฉันเมื่อคุณไม่สามารถมี listview ภายใน scrollview แต่คุณต้องการอะไรแบบนั้น

LayoutInflater li = LayoutInflater.from(this);

                RelativeLayout parent = (RelativeLayout) this.findViewById(R.id.relativeLayoutCliente);

                int recent = 0;

                for(Contatto contatto : contatti)
                {
                    View inflated_layout = li.inflate(R.layout.header_listview_contatti, layout, false);


                    inflated_layout.setId(contatto.getId());
                    ((TextView)inflated_layout.findViewById(R.id.textViewDescrizione)).setText(contatto.getDescrizione());
                    ((TextView)inflated_layout.findViewById(R.id.textViewIndirizzo)).setText(contatto.getIndirizzo());
                    ((TextView)inflated_layout.findViewById(R.id.textViewTelefono)).setText(contatto.getTelefono());
                    ((TextView)inflated_layout.findViewById(R.id.textViewMobile)).setText(contatto.getMobile());
                    ((TextView)inflated_layout.findViewById(R.id.textViewFax)).setText(contatto.getFax());
                    ((TextView)inflated_layout.findViewById(R.id.textViewEmail)).setText(contatto.getEmail());



                    RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);

                    if (recent == 0)
                    {
                        relativeParams.addRule(RelativeLayout.BELOW, R.id.headerListViewContatti);
                    }
                    else
                    {
                        relativeParams.addRule(RelativeLayout.BELOW, recent);
                    }
                    recent = inflated_layout.getId();

                    inflated_layout.setLayoutParams(relativeParams);
                    //inflated_layout.setLayoutParams( new RelativeLayout.LayoutParams(source));

                    parent.addView(inflated_layout);
                }

ญาติเลย์เอาต์อยู่ใน ScrollView เพื่อให้มันกลายเป็น scrollable :)


1

นี่คือการปรับเปลี่ยนเล็กน้อยในคำตอบของ@djunodที่ฉันต้องทำให้มันทำงานได้อย่างสมบูรณ์:

public static void setListViewHeightBasedOnChildren(ListView listView)
{
    ListAdapter listAdapter = listView.getAdapter();
    if(listAdapter == null) return;
    if(listAdapter.getCount() <= 1) return;

    int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
    int totalHeight = 0;
    View view = null;
    for(int i = 0; i < listAdapter.getCount(); i++)
    {
        view = listAdapter.getView(i, view, listView);
        view.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
        totalHeight += view.getMeasuredHeight();
    }
    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    listView.setLayoutParams(params);
    listView.requestLayout();
}

: สวัสดีคำตอบของคุณใช้เวลาส่วนใหญ่ แต่จะไม่ทำงานหาก listview มีมุมมองส่วนหัวและมุมมองเท้า คุณตรวจสอบได้ไหม
hguser

ฉันต้องการวิธีแก้ปัญหาเมื่อรายการ - รายการมีขนาดผันแปรคือบางมุมมองข้อความที่ขยายข้ามหลายบรรทัด ข้อเสนอแนะใด ๆ
Khobaib

1

ลองสิ่งนี้มันใช้งานได้สำหรับฉันฉันลืมที่ฉันพบมันที่ไหนสักแห่งในกองล้นฉันไม่ได้ที่นี่เพื่ออธิบายว่าทำไมมันไม่ทำงาน แต่นี่คือคำตอบ :)

    final ListView AturIsiPulsaDataIsiPulsa = (ListView) findViewById(R.id.listAturIsiPulsaDataIsiPulsa);
    AturIsiPulsaDataIsiPulsa.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;
        }
    });
    AturIsiPulsaDataIsiPulsa.setClickable(true);
    AturIsiPulsaDataIsiPulsa.setAdapter(AturIsiPulsaDataIsiPulsaAdapter);

แก้ไข! ในที่สุดฉันก็พบว่าฉันได้รับรหัสที่ไหน ที่นี่! : ListView ข้างใน ScrollView ไม่ได้เลื่อนบน Android


สิ่งนี้ครอบคลุมถึงวิธีการป้องกันการสูญเสียการทำงานร่วมกันของ scrollview แต่คำถามคือเกี่ยวกับการรักษาความสูงของ listview
รถเข็นที่ถูกยกเลิก

1

แม้ว่าsetListViewHeightBasedOnChildren () ที่แนะนำจะใช้วิธีการในกรณีส่วนใหญ่ในบางกรณีโดยเฉพาะอย่างยิ่งกับรายการจำนวนมากฉันสังเกตเห็นว่าองค์ประกอบสุดท้ายจะไม่แสดง ดังนั้นฉันจึงตัดสินใจเลียนแบบพฤติกรรมของListViewแบบธรรมดาเพื่อนำรหัสอะแดปเตอร์ใด ๆ กลับมาใช้ใหม่นี่เป็นทางเลือก ListView:

import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ListAdapter;

public class StretchedListView extends LinearLayout {

private final DataSetObserver dataSetObserver;
private ListAdapter adapter;
private OnItemClickListener onItemClickListener;

public StretchedListView(Context context, AttributeSet attrs) {
    super(context, attrs);
    setOrientation(LinearLayout.VERTICAL);
    this.dataSetObserver = new DataSetObserver() {
        @Override
        public void onChanged() {
            syncDataFromAdapter();
            super.onChanged();
        }

        @Override
        public void onInvalidated() {
            syncDataFromAdapter();
            super.onInvalidated();
        }
    };
}

public void setAdapter(ListAdapter adapter) {
    ensureDataSetObserverIsUnregistered();

    this.adapter = adapter;
    if (this.adapter != null) {
        this.adapter.registerDataSetObserver(dataSetObserver);
    }
    syncDataFromAdapter();
}

protected void ensureDataSetObserverIsUnregistered() {
    if (this.adapter != null) {
        this.adapter.unregisterDataSetObserver(dataSetObserver);
    }
}

public Object getItemAtPosition(int position) {
    return adapter != null ? adapter.getItem(position) : null;
}

public void setSelection(int i) {
    getChildAt(i).setSelected(true);
}

public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
    this.onItemClickListener = onItemClickListener;
}

public ListAdapter getAdapter() {
    return adapter;
}

public int getCount() {
    return adapter != null ? adapter.getCount() : 0;
}

private void syncDataFromAdapter() {
    removeAllViews();
    if (adapter != null) {
        int count = adapter.getCount();
        for (int i = 0; i < count; i++) {
            View view = adapter.getView(i, null, this);
            boolean enabled = adapter.isEnabled(i);
            if (enabled) {
                final int position = i;
                final long id = adapter.getItemId(position);
                view.setOnClickListener(new View.OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        if (onItemClickListener != null) {
                            onItemClickListener.onItemClick(null, v, position, id);
                        }
                    }
                });
            }
            addView(view);

        }
    }
}
}

1

คำตอบทั้งหมดเหล่านี้ผิด !!! หากคุณพยายามใส่ listview ใน scroll view คุณควรคิดการออกแบบของคุณใหม่ คุณพยายามใส่ ScrollView ใน ScrollView การรบกวนรายการจะทำให้ประสิทธิภาพของรายการแย่ลง มันถูกออกแบบมาให้เป็นเช่นนี้โดย Android

หากคุณต้องการให้รายการอยู่ในการเลื่อนเดียวกับองค์ประกอบอื่น ๆ สิ่งที่คุณต้องทำคือเพิ่มรายการอื่น ๆ ลงในด้านบนของรายการโดยใช้คำสั่ง switch แบบง่ายในอะแดปเตอร์ของคุณ:

class MyAdapter extends ArrayAdapter{

    public MyAdapter(Context context, int resource, List objects) {
        super(context, resource, objects);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
         ViewItem viewType = getItem(position);

        switch(viewType.type){
            case TEXTVIEW:
                convertView = layouteInflater.inflate(R.layout.textView1, parent, false);

                break;
            case LISTITEM:
                convertView = layouteInflater.inflate(R.layout.listItem, parent, false);

                break;            }


        return convertView;
    }


}

อะแดปเตอร์รายการสามารถจัดการทุกอย่างได้เพราะมันจะแสดงสิ่งที่มองเห็นได้เท่านั้น


0

ปัญหาทั้งหมดนี้จะหายไปหาก LinearLayout มีเมธอด setAdapter เพราะเมื่อคุณบอกให้ใครบางคนใช้แทนวิธีอื่นจะไม่สำคัญ

หากคุณต้องการ ListView แบบเลื่อนภายในมุมมองการเลื่อนอื่นจะไม่ช่วย แต่อย่างน้อยก็จะทำให้คุณมีความคิด

คุณต้องสร้างอะแดปเตอร์ที่กำหนดเองเพื่อรวมเนื้อหาทั้งหมดที่คุณต้องการเลื่อนและตั้งค่าอะแดปเตอร์ของ ListView ให้เป็นแบบนั้น

ฉันไม่มีโค้ดตัวอย่างที่มีประโยชน์ แต่ถ้าคุณต้องการอะไร

<ListView/>

(other content)

<ListView/>

จากนั้นคุณต้องสร้างอะแดปเตอร์ที่แสดงถึงเนื้อหาทั้งหมด ListView / Adapters ฉลาดพอที่จะรองรับชนิดต่าง ๆ ได้เช่นกัน แต่คุณต้องเขียนอะแดปเตอร์ด้วยตัวเอง

API UI ของ Android นั้นไม่ได้มีความสมบูรณ์เท่ากับทุกสิ่งทุกอย่างในนั้นดังนั้นมันจึงไม่มีสิ่งที่เหมือนกันกับแพลตฟอร์มอื่น ๆ นอกจากนี้เมื่อคุณทำบางสิ่งบางอย่างบน Android คุณต้องอยู่ในความคิดของ Android (unix) ที่คุณคาดหวังว่าจะทำทุกสิ่งที่คุณอาจจะต้องประกอบการทำงานของชิ้นส่วนขนาดเล็กและเขียนรหัสของคุณเอง งาน.


0

เมื่อเราวางListViewภายในScrollViewสองปัญหาที่เกิดขึ้น หนึ่งคือการScrollViewวัดลูกของมันในโหมด UNSPECIFIED ดังนั้นListViewตั้งค่าความสูงของตัวเองเพื่อรองรับไอเท็มเดียวเท่านั้น (ฉันไม่รู้ว่าทำไม) และอีกอันนั้นScrollViewขัดขวางเหตุการณ์การสัมผัสดังนั้นListViewไม่เลื่อน

แต่เราสามารถวางไว้ListViewข้างในScrollViewด้วยวิธีแก้ปัญหาบางอย่าง โพสต์นี้โดยฉันอธิบายถึงวิธีแก้ปัญหา ด้วยวิธีแก้ปัญหานี้เรายังสามารถเก็บListViewคุณสมบัติการรีไซเคิลของไว้ได้เช่นกัน


0

แทนที่จะใส่ listview ไว้ใน Scrollview ให้วางเนื้อหาที่เหลือระหว่าง listview และการเปิด scrollview เป็นมุมมองแยกต่างหากและตั้งค่ามุมมองนั้นเป็นส่วนหัวของ listview ดังนั้นในที่สุดคุณก็จะได้เฉพาะมุมมองรายการที่มีค่าใช้จ่ายการเลื่อน



-1

นี่คือรหัสรุ่นของฉันที่คำนวณความสูงทั้งหมดของมุมมองรายการ อันนี้ใช้ได้สำหรับฉัน:

   public static void setListViewHeightBasedOnChildren(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null || listAdapter.getCount() < 2) {
        // pre-condition
        return;
    }

    int totalHeight = 0;
    int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(BCTDApp.getDisplaySize().width, View.MeasureSpec.AT_MOST);
    int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

    for (int i = 0; i < listAdapter.getCount(); i++) {
        View listItem = listAdapter.getView(i, null, listView);
        if (listItem instanceof ViewGroup) listItem.setLayoutParams(lp);
        listItem.measure(widthMeasureSpec, heightMeasureSpec);
        totalHeight += listItem.getMeasuredHeight();
    }

    totalHeight += listView.getPaddingTop() + listView.getPaddingBottom();
    totalHeight += (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight;
    listView.setLayoutParams(params);
    listView.requestLayout();
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.