使用自定义适配器获取ListView的高度

时间:2015-01-28 10:33:05

标签: android listview android-listview scrollview android-scrollview

我在scrollView中有listView(是的,我知道这是不好的方法。最好使用页眉/页脚)。我知道scrollView和listView都有滚动,这会导致一些冲突。在这种情况下,我需要手动设置列表的高度。这就是问题,因为listView有自定义适配器。

布局:

<?xml version="1.0" encoding="utf-8"?>

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ScrollView01"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbars="none" >
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/fragment_lessons"
        android:background="#FAF9F9"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.cbsystematic.mobile.itvdn.LessonsFragment">

        <TextView
            android:id="@+id/course_title"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Описание курса: "
            android:textSize="16sp"
            android:textStyle="bold"
            android:textColor="#000000"/>

        <TextView
            android:id="@+id/course_description"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textSize="16sp"
            android:layout_below="@id/course_title"
            android:textColor="#000000"/>

        <TextView
            android:id="@+id/course_duration"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            android:textStyle="italic"
            android:layout_below="@id/course_description"
            android:textColor="#000000"/>

        <ListView android:id="@android:id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/course_duration"/>
        </RelativeLayout>
    </LinearLayout>
</ScrollView>

自定义列表适配器:

class LessonsItemAdapter extends ArrayAdapter<LessonData> {
private Activity myContext;
private ArrayList<LessonData> datas;

public LessonsItemAdapter(Context context, int textViewResourceId, ArrayList<LessonData> objects){
    super(context, textViewResourceId, objects);

    myContext = (Activity) context;
    datas = objects;
}

public View getView(int position, View convertView, ViewGroup parent){
    ViewHolder viewHolder;

    if(convertView == null) {
        LayoutInflater inflater = myContext.getLayoutInflater();
        convertView = inflater.inflate(R.layout.lessons_list_item, null);

        viewHolder = new ViewHolder();
        viewHolder.postNameView = (TextView) convertView.findViewById(R.id.lessons_name);
        viewHolder.postDurationView = (TextView) convertView.findViewById(R.id.lessons_duration);

        convertView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }

    //(position + 1) + ") " used to display 1) 2) 3) etc of lessons
    viewHolder.postNameView.setText((position + 1) + ") " + datas.get(position).getName());
    viewHolder.postDurationView.setText("Длительность: " + datas.get(position).getDuration().substring(0,8));

    return convertView;
}

static class ViewHolder{
    TextView postNameView;
    TextView postDurationView;
}
}

找高度的方法:

    public static void setListViewSize(AbsListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null)
        return;

    int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.UNSPECIFIED);
    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, AbsListView.LayoutParams.WRAP_CONTENT));

        view.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
        totalHeight += view.getMeasuredHeight();
    }
    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight + (listView.getMeasuredHeight() * (listAdapter.getCount() + 1));
    listView.setLayoutParams(params);
    listView.requestLayout();
}

这就是我如何设置列表的内容:

    mAdapter = new LessonsItemAdapter(getActivity(),
            R.layout.lessons_list_item, parserJson.getLessons(courseUrl).getLessonsArray());

    // Set the adapter
    mListView = (AbsListView) view.findViewById(android.R.id.list);
    ((AdapterView<ListAdapter>) mListView).setAdapter(mAdapter);

    // Set OnItemClickListener so we can be notified on item clicks
    mListView.setOnItemClickListener(this);
    ListHelper.setListViewSize(mListView);

结果就是这样:

enter image description here

整个视图都在滚动。但最后一项始终只显示一半。你看,字段持续时间(“Длительность”)没有显示。虽然列表的最后一项是隐晦的。

请帮我确定定义总高度的方法。 提前致谢。感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

使用这段代码。它将根据项目数重置listview的大小。

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

    int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(),
            MeasureSpec.UNSPECIFIED);
    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();
}

答案 1 :(得分:1)

布局文件中的ListView应该像

 <ListView android:id="@android:id/list"
            android:layout_width="match_parent"
             android:layout_height="wrap_content" 
            android:layout_below="@id/course_duration"/>

现在,在您的代码中,您希望根据子视图调整ListView的高度,放置以下方法。

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

通过将ListView传递给它来调用它

  setListViewHeightBasedOnChildren(list);

简单而强大的解决方案

答案 2 :(得分:0)

this blog

尝试下面的代码
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
{
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int newHeight = 0;
    final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    if (heightMode != MeasureSpec.EXACTLY) 
    {
        ListAdapter listAdapter = getAdapter();
        if (listAdapter != null && !listAdapter.isEmpty()) 
        {
            int listPosition = 0;
            for (listPosition = 0; listPosition < listAdapter.getCount()
                    && listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) 
            {
                View listItem = listAdapter.getView(listPosition, null, this);
                //now it will not throw a NPE if listItem is a ViewGroup instance
                if (listItem instanceof ViewGroup) 
                {
                    listItem.setLayoutParams(new LayoutParams(
                            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                }
                listItem.measure(widthMeasureSpec, heightMeasureSpec);
                newHeight += listItem.getMeasuredHeight();
            }
            newHeight += getDividerHeight() * listPosition;
        }
        if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) 
        {
            if (newHeight > heightSize) 
            {
                newHeight = heightSize;
            }
        }
    } 
    else 
    {
        newHeight = getMeasuredHeight();
    }
    setMeasuredDimension(getMeasuredWidth(), newHeight);
}