我正在使用 ListView 显示一些来自 JSON 的数据。 JSON 有 3 个对象。我正在为 ListView 使用自定义适配器。
这是 ListView 的布局
<?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>
这是 ListView 行的布局
<?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"
}
]
最后,输出只显示页面底部 ListView 中JSON的最后一个对象
调试时,我看到 JSON 已被正确读取,并且所有 3 个对象都存在于数组列表中。为 3 个对象调用了自定义适配器的 GetView 方法, View 正在形成并正确返回。尝试了很长时间不同的东西,但无法弄清楚前两项为什么没有出现在屏幕上。
任何帮助将不胜感激。
最佳答案
您错误地扩充了列表项布局。
convertView = vi.inflate(R.layout.doc_list, (ViewGroup) activity.findViewById(R.id.doc_list_row));
在那个特定的 inflate()
重载中,第二个参数是 ViewGroup
,在膨胀后将膨胀的 View
添加到该 ViewGroup
中。 getView()
方法第一次运行时,activity.findViewById(R.id.doc_list_row)
将返回 null
,因为 doc_list_row
View
还不存在于层次结构中,因此膨胀的 View
将像往常一样被添加到 ListView
中, 返回
之后。然而,下一次 getView()
运行时,第一个列表项中有一个 doc_list_row
View
,所以第二个项目的 View
以及之后膨胀的任何对象,都被添加到第一个项目中,在其垂直 LinearLayout
中堆叠在其原始子 View
之下。
此外,inflate()
方法返回膨胀和(可选)添加的任何结果的根 View
。如果 ViewGroup
参数为 null
,则没有要添加膨胀布局的内容,它返回刚刚膨胀布局的根 View
。如果 ViewGroup
参数不是 null
,那么 ViewGroup
将作为根返回,因为它现在是顶级父级。创建第一个列表项后,getView()
方法重复返回相同的第一个项目 View
,并且 ListView
在协调布局具有自己的内部逻辑,这就是为什么您看到的一项没有与顶部对齐。
膨胀列表项的正确方法是将 ViewGroup parent
参数作为 inflate()
调用中的第二个参数传递,并且 false
作为第三个参数,表示膨胀布局不应添加到那里的 parent
,因为它最终将被添加到 之后的
。ListView
返回
convertView = vi.inflate(R.layout.doc_list, parent, false);
您可能还想在 doc_list
布局 wrap_content
中制作根 LinearLayout
的 layout_height
,如果只是为了安全起见。 ListView
应该足够聪明,可以覆盖它并将其包装起来,但最好不要引入任何可能有问题的东西。
关于带有自定义适配器的 Android ListView 仅显示最后一项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43025216/