我正在开发一个非常简单的列表应用程序,用于将项目保存到SQLite DB,并使用它的内容填充ListView。
这可以使用SimpleCursorAdapter完成,我喜欢这样:
mySQLiteAdapter.openToRead();
cursor = mySQLiteAdapter.queueAll();
String[] from = new String[]{mySQLiteAdapter.getKeyContent()};
int[] to = new int[]{R.id.normal};
cursorAdapter = new SimpleCursorAdapter(this, R.layout.row, cursor, from, to, 0);
listView.setAdapter(cursorAdapter);
mySQLiteAdapter.close();
现在我想实现通过点击或长按来删除行中文本的功能,或者将行更改为不同的布局(也可能会对文本产生影响)
首先,我只需为列表视图设置onClickListener,并更改绘制标记以触发文本。这可以正常工作,直到列表中有足够的项目来滚动视图,或者直到重新加载活动。在后者中,罢工已经消失(因为没有任何东西是持久性的),并且在前者中其他行被打击,而预期的行则没有。然后滚动时会发生变化。有关我自己的类似情况,请参阅Custom ListView adapter, strange ImageView behavior。
由此我发现我需要使用自定义适配器来做我想要的。所以我创建了一个CustomCursorAdapter,它扩展了SimpleCursorAdapter并覆盖了一些方法,试图用背景颜色来膨胀单独的布局。我没有太多运气。
这是我到目前为止所做的:
// Creating a new instance of the custom adapter and assigning it to the listview
mySQLiteAdapter.openToRead();
cursor = mySQLiteAdapter.queueAll();
String[] from = new String[]{mySQLiteAdapter.getKeyContent()};
int[] to = new int[]{R.id.normal};
cursorAdapter = new CustomCursorAdapter(this, R.layout.row, cursor, from, to, 0);
listView.setAdapter(cursorAdapter);
mySQLiteAdapter.close();
和
// CustomCursorAdapter class
private class MyCursorAdapter extends SimpleCursorAdapter {
private LayoutInflater inflater;
public MyCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
super(context, layout, c, from, to, flags);
inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get reference to the row
View view = super.getView(position, convertView, parent);
//View view;
if (getItemViewType(position) == 0) {
view = inflater.inflate(R.layout.row, null);
}
else {
view = inflater.inflate(R.layout.rowstrike, null);
}
return view;
}
@Override
public int getItemViewType(int position) {
int row;
if (cursor.getInt(cursor.getColumnIndex(mySQLiteAdapter.getKeyStrike())) == 1) {
Log.d("DEBUG", "Row " + position + " is STRIKED");
row = 1;
}
else {
Log.d("DEBUG", "Row " + position + " is normal");
row = 0;
}
return row;
}
}
CustomCursorAdapter的实现可以正常工作并显示正确的行数。通过查询db来确定行是否应包含striked文本的逻辑是正确的,但返回的膨胀视图是完全空白的。我认为这可能与我的XML文件的排列方式以及我传递给适配器的方式有关,但到目前为止,我所有的测试和修补试图让这个工作都失败了。
以下是布局的XML文件
// activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<EditText
android:layout_width="fill_parent"
android:layout_height="35dp"
android:id="@+id/editText"
android:hint="Press here to add an item"
android:maxLines="1"
android:imeOptions="actionDone"
android:inputType="textAutoCorrect"/>
<ListView
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:id="@+id/listView"
android:layout_below="@id/editText"/>
</RelativeLayout>
// row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp" >
<TextView
android:id="@+id/normal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"/>
</RelativeLayout>
//rowstrike.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp" >
<TextView
android:id="@+id/striked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#F05"/>
</RelativeLayout>
我一直在搜索这些日子和日子,每次都越来越近但似乎什么都没有用,或者解释对于像我这样的人来说并不适合初学者。
我发现的最接近的帖子是我 ListView view recycling with CustomAdapter
但是我认为我需要更多的代码片段,因为我必须在我的应用中的其他地方做错了什么? 提到覆盖getViewTypeCount方法,但我不确定如何做到这一点......
还有 How would I use a different row layout in custom CursorAdapter based on Cursor data? 但是我不太确定从这篇文章到哪里去......
编辑:基于Luksprogs帖子的解决方案。
mySQLiteAdapter.openToRead();
cursor = mySQLiteAdapter.queueAll();
String[] from = new String[]{mySQLiteAdapter.getKeyContent()};
int[] to = new int[]{R.id.normal};
cursorAdapter = new SimpleCursorAdapter(this, R.layout.row, cursor, from, to, 0);
cursorAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (view.getId() == R.id.normal) {
TextView tv = (TextView)view.findViewById(R.id.normal);
if (cursor.getInt(cursor.getColumnIndex(mySQLiteAdapter.getKeyStrike())) == 1) {
tv.setPaintFlags(tv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}
else {
tv.setPaintFlags(tv.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
}
}
return false;
}
});
listView.setAdapter(cursorAdapter);
mySQLiteAdapter.close();
我有一个OnItemClickListener,如下所示,以打击和取消打击行
private ListView.OnItemClickListener listViewOnItemClickListener
=new ListView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final int rowID = cursor.getInt(cursor.getColumnIndex(mySQLiteAdapter.getKeyID()));
mySQLiteAdapter.openToWrite();
if (cursor.getInt(cursor.getColumnIndex(mySQLiteAdapter.getKeyStrike())) == 0) {
mySQLiteAdapter.setKeyStrike(rowID, 1);
}
else {
mySQLiteAdapter.setKeyStrike(rowID, 0);
}
cursor = mySQLiteAdapter.queueAll();
cursorAdapter.swapCursor(cursor);
mySQLiteAdapter.close();
};
答案 0 :(得分:0)
但是返回的膨胀视图完全是空白的。
作为旁注,您不应该覆盖基于Cursor的适配器的getView()方法,因为这种类型的适配器实现了getView()来分隔构建行布局并使用两个单独的方法绑定数据{ {1}}和newView()
。应该重写这两种方法。另外,SimpleCursorAdapter是为基本场景设计的类,如果你需要实现(真的)不同的行类型,那么扩展CursorAdapter将是一种更好的方法。
您获得空白行布局,因为您不会对它们进行任何数据绑定。在getView()方法中,您可以:
bindView()
将返回正确构建的行布局(通过SimpleCursorAdapter类实现),仅丢弃该视图并根据行类型(if-else代码片段)膨胀新行布局)。您不会将任何数据绑定到这些视图,因此您只返回膨胀的布局,该布局将为空白。
如果你的两行只是一个删除线文本不同,那么你不应该使用两种行类型(当行的结构不同时,应该使用不同的行类型)。您可以通过ViewBinder实现您想要的内容:
View view = super.getView(position, convertView, parent);
如果你想要
我想实现能够删除文本的能力 点击或长按
然后你需要记住某个地方的行状态,以便你可以用它来恢复它。