带自定义适配器的Android ListView仅显示最后一项

时间:2017-03-26 05:03:23

标签: android listview custom-adapter

我使用ListView来显示来自JSON的一些数据。 JSON有3个对象。我正在使用自定义适配器进行列表视图。

这是列表视图的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/doc_signing"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <ListView android:id="@+id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:dividerHeight="1.5dp" />
    <TextView android:id="@+id/android:empty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="22sp"
        android:text="@string/no_docs_to_sign"/>
</LinearLayout>

这是列表视图行的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/doc_list_row"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/doc_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:textSize="22sp" >
    </TextView>
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <TextView
            android:id="@+id/doc_id"
            android:layout_weight="0.50"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:paddingBottom="2dp"
            android:paddingLeft="5dp"
            android:paddingRight="3dp"
            android:textSize="16sp" >
        </TextView>
        <TextView
            android:id="@+id/doc_date"
            android:layout_weight="0.50"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:paddingBottom="2dp"
            android:paddingLeft="3dp"
            android:paddingRight="3dp"
            android:textSize="16sp" >
        </TextView>
    </LinearLayout>
</LinearLayout>

读取JSON并设置适配器的代码在这里

ArrayList<DocInfo> docInfo = new ArrayList<DocInfo>();
try {
    JSONArray jArray = new JSONArray(readData());
    for (int i = 0; i < jArray.length(); i++) {
        JSONObject jObject = jArray.getJSONObject(i);
        Log.i("Object" + i, jObject.toString());
        docInfo.add(new DocInfo(Long.valueOf(jObject.getString("doc_id")), jObject.getString("doc_name"), jObject.getString("doc_file_name"), jObject.getString("doc_date")));
    }
} catch (Exception e) {
}
CustomAdapter adapter = new CustomAdapter(this, R.layout.doc_list, docInfo);
setListAdapter(adapter);

自定义适配器

public class CustomAdapter extends ArrayAdapter<DocInfo> {
    private List<DocInfo> entries;
    private Activity activity;

    public CustomAdapter(Activity a, int textViewResourceId, ArrayList<DocInfo> entries) {
        super(a, textViewResourceId, entries);
        this.entries = entries;
        this.activity = a;
    }

    public static class ViewHolder{
        public TextView tv_doc_name;
        public TextView tv_doc_id;
        public TextView tv_doc_date;
    }

    @Override
    public int getCount(){
          return entries!=null ? entries.size() : 0;
    }

    @Override
    public DocInfo getItem(int index) {
        return entries.get(index);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            LayoutInflater vi = LayoutInflater.from(activity);
            convertView = vi.inflate(R.layout.doc_list, (ViewGroup) activity.findViewById(R.id.doc_list_row));
            holder = new ViewHolder();
            holder.tv_doc_name = (TextView) convertView.findViewById(R.id.doc_name);
            holder.tv_doc_id = (TextView) convertView.findViewById(R.id.doc_id);
            holder.tv_doc_date = (TextView) convertView.findViewById(R.id.doc_date);
            convertView.setTag(holder);
        }
        else
            holder=(ViewHolder) convertView.getTag();

        final DocInfo custom = entries.get(position);
        if (custom != null) {
            holder.tv_doc_name.setText(custom.get_doc_name());
            holder.tv_doc_id.setText(String.valueOf(custom.get_doc_id()));
            holder.tv_doc_date.setText(custom.get_doc_date());
        }
        Log.i("Custom" + position, custom.get_doc_name() + String.valueOf(custom.get_doc_id()) + custom.get_doc_date());
        return convertView;
    }
}

用于测试的JSON

[
    {
        "doc_name": "Home Loan Agreement",
        "doc_file_name": "home_loan_agreement.pdf",
        "doc_id": "6781",
        "doc_date": "11-Mar-2017"
    },
    {
        "doc_name": "Personal Loan Agreement",
        "doc_file_name": "personal_loan_agreement.pdf",
        "doc_id": "2517",
        "doc_date": "19-Mar-2017"
    },
    {
        "doc_name": "Insurance Policy Proposal",
        "doc_file_name": "policy_proposal.pdf",
        "doc_id": "1291",
        "doc_date": "24-Mar-2017"
    }
]

最后,输出只显示页面底部列表视图中JSON的最后一个对象 checking it is a V2 API instance

调试时,我看到JSON已被正确读取,并且数组列表中存在所有3个对象。为3个对象调用自定义适配器的GetView方法,并且正在形成并正确返回视图。长时间尝试不同的东西,但无法弄清楚前两个项目在屏幕上没有出现的原因。

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:2)

您错误地夸大了列表项布局。

convertView = vi.inflate(R.layout.doc_list, (ViewGroup) activity.findViewById(R.id.doc_list_row));

在特定的inflate()重载中,第二个参数是ViewGroup,膨胀后View被充气后添加getView()。第一次运行activity.findViewById(R.id.doc_list_row)方法时,null将返回doc_list_row,因为View View尚未在层次结构中存在,因此在ListView之后,膨胀的return会像正常一样被添加到getView()。然而,下次doc_list_row运行时,第一个列表项中会有View View,因此第二个项目View和任何膨胀的项目之后,添加到第一个项目中,在其原始LinearLayout的原始子inflate()下方堆叠。

此外,View方法返回通货膨胀和(可选)添加的结果的根ViewGroup。如果null参数为View,则没有任何内容可以添加膨胀的布局,并返回刚刚膨胀的布局的根ViewGroup。如果null参数不是ViewGroup,那么getView()将作为根返回,因为它现在是顶级父级。创建第一个列表项后,View方法将重复返回相同的第一个项ListView,并且ViewGroup parent在布局与其内部逻辑协调时出现问题,这就是为什么您看到的一件商品并未与顶部对齐。

扩充列表项的正确方法是将inflate()参数作为false调用中的第二个参数传递,并将parent作为第三个参数传递,以指示充气布局不应添加到ListView,因为它最终会在return之后添加到convertView = vi.inflate(R.layout.doc_list, parent, false);

layout_height

如果只是为了安全起见,您可能还想在LinearLayout布局doc_list中制作根wrap_content的{​​{1}}。 ListView应该足够聪明,可以覆盖它并将其换行,但最好不要引入任何可能存在问题的内容。

答案 1 :(得分:0)

替换为此代码:

 <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/doc_signing"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical">
        <ListView android:id="@+id/android:list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:dividerHeight="1.5dp" />
        <TextView android:id="@+id/android:empty"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="22sp"
            android:text="@string/no_docs_to_sign"/>
    </LinearLayout>

您已将listview高度保持为fill_parent。这可能会给您带来问题。将高度更改为wrap_content

答案 2 :(得分:0)

列表视图行项xml存在问题,而不是父布局高度fill_parent使它们像这样包装

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/doc_list_row"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/doc_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:textSize="22sp" >
    </TextView>
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <TextView
            android:id="@+id/doc_id"
            android:layout_weight="0.50"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:paddingBottom="2dp"
            android:paddingLeft="5dp"
            android:paddingRight="3dp"
            android:textSize="16sp" >
        </TextView>
        <TextView
            android:id="@+id/doc_date"
            android:layout_weight="0.50"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:paddingBottom="2dp"
            android:paddingLeft="3dp"
            android:paddingRight="3dp"
            android:textSize="16sp" >
        </TextView>
    </LinearLayout>
</LinearLayout>