我编写了以下类来创建包含自定义列表行的列表视图。我为项目使用 Android支持库v4 ,并使用ActionBarSherlock库为旧设备集成操作栏。
public class CustomListActivity extends SherlockFragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(R.style.Sherlock___Theme_DarkActionBar);
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_list);
}
}
...
public class ListFragment extends SherlockListFragment implements LoaderCallbacks<Cursor> {
private Activity mActivity;
private CursorAdapter mAdapter;
// Query parameter as members ...
private String mFromColumns;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setEmptyText("No data to display");
mActivity = getActivity();
// Query parameters are stored in members here ...
mFromColumns = { "_id", "name" };
mAdapter = new CustomCursorAdapter(mActivity, null, 0);
setListAdapter(mAdapter);
getLoaderManager().initLoader(0, null, this);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle extras) {
return new CursorLoader(mActivity, mUri, mFromColumns, mSelection, mSelectionArgs, sortOrder);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
mAdapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
}
...
public class CustomCursorAdapter extends CursorAdapter {
private LayoutInflater mInflater;
public CustomCursorAdapter(Context context, Cursor cursor, int flags) {
super(context, cursor, flags);
mInflater = LayoutInflater.from(context);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView listItem = (TextView)view.findViewById(R.id.name);
// TextView listItem = (TextView)view.findViewById(android.R.id.text1);
String text = cursor.getString(cursor.getColumnIndex("name"));
listItem.setText(text);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(R.layout.list_item, parent, false);
// return mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
}
}
当我使用框架提供的列表项和布局(CustomCursorAdapter
中的未注释行)时,列表视图成功加载并显示数据行。但是,当我交换行以使用我的自定义布局和列表项时,findViewById
会返回null
。这是xml文件。
fragment_list.xml
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.example.app.fragment.ListFragment"
android:id="@+id/list_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</fragment>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="@+id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
我很确定,问题是我如何链接xml文件或它们是如何构建的。我希望你能看到错误。实际上,我不明白list_item.xml
如何用作列表视图的行布局。我设置为fragment_list.xml
的唯一参考是setContentView(R.layout.fragment_list);
。此xml文件不包含任何容器元素,例如<ListView android:id="@android:id/list" />
(我在其他设置中看到过)。
此外:
我想知道是否仍然建议在CursorAdapter
中使用 ViewHolder 模式,或者是否已经内置此行为。我在其他示例中多次看到它,但是那些继承自BaseAdapter
或SimpleCursorAdapter
。
经验教训:
当我尝试解决问题时,我在某些时候对XML文件进行了正确的设置。但是另一件事阻碍了我把事情弄得一团糟。以下是您需要注意的事项
如果要在行布局中显示多个信息,请务必在fromColumn
的{{1}}参数中包含关联的列名称。否则,您将遇到异常:
CursorLoader
fromColumns中的每个列名...
java.lang.IllegalStateException: get field slot from row 0 col -1 failed
...与你要求光标的内容有关。 <{1}}列必须使用游标作为迭代器。
String[] fromColumns = { "_id", "name", "comments" }
答案 0 :(得分:2)
您的代码适用于我(在我更改行注释时)。唯一的事情是:我已将公共空构造函数添加到ListFragment
。
仍然建议ViewHolder
使用CursorAdapter
模式。
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
if (holder == null) {
holder = new ViewHolder();
holder.name = (TextView) view.findViewById(R.id.name);
view.setTag(holder);
}
String text = cursor.getString(cursor.getColumnIndex("name"));
holder.name.setText(text);
}
private static class ViewHolder {
TextView name;
}