我是新来的。滚动ListView后,与我选择的项目处于“相同位置”的项目将自动选择。 (相同的位置是指屏幕中的位置,而不是数据库中的位置。)以前有这个问题,因为我是通过OnItemClickListener中ListView的索引选择项目的。尽管我以正确的方式做事,但我再次面临这个问题。
当我单击ListView中的项目时,我得到它的唯一ID,并基于此,我将该项目(数据库中此行的)的SELECTED值更改为0或1(取决于是否单击此项目) 。之后,我将backgrnd的颜色切换为灰色(或重新切换为白色)。这是在CursorAdapter中处理的,它区分了SELECTED属性。
这是我的代码。
MainActivity.kt中的OnCreate
val dbHelper = DBHelper(this)
val db = dbHelper.writableDatabase
val myCursor = db.rawQuery("SELECT * FROM ${ContractClass.FeedReaderContract.TABLE_NAME}", null)
val myAdapter = CursorAdapter(this, myCursor)
myListView.adapter = myAdapter
myListView.setOnItemClickListener { _, view, _, _ ->
val text = view.txtName.text
val select = "${ContractClass.FeedReaderContract.COLUMN_NAME_ENWORD} MATCH ?"
val selectCursor = db.query(
ContractClass.FeedReaderContract.TABLE_NAME, // The table to query
null, // The array of columns to return (pass null to get all)
select, // The columns for the WHERE clause
arrayOf("$text"), // The values for the WHERE clause
null, // don't group the rows
null, // don't filter by row groups
null // The sort order
)
with(selectCursor) {
while (moveToNext()) {
val itemSel = getInt(getColumnIndexOrThrow(ContractClass.FeedReaderContract.COLUMN_NAME_SELECTED))
if (itemSel == 1){
val values = ContentValues().apply {
put(ContractClass.FeedReaderContract.COLUMN_NAME_SELECTED, 0)
}
val count = db.update(
ContractClass.FeedReaderContract.TABLE_NAME, values, select, arrayOf("$text"))
}else{
val values = ContentValues().apply {
put(ContractClass.FeedReaderContract.COLUMN_NAME_SELECTED, 1)
}
val count = db.update(
ContractClass.FeedReaderContract.TABLE_NAME, values, select, arrayOf("$text"))
}
}
}
}
CursorAdapter.kt
class CursorAdapter(context: Context, cursor: Cursor) : CursorAdapter(context, cursor, 0) {
// The newView method is used to inflate a new view and return it,
// you don't bind any data to the view at this point.
override fun newView(context: Context, cursor: Cursor, parent: ViewGroup): View {
if (cursor.getInt(cursor.getColumnIndexOrThrow(ContractClass.FeedReaderContract.COLUMN_NAME_SELECTED)) == 0){
return LayoutInflater.from(context).inflate(R.layout.row_list_row, parent, false)
}else{
return LayoutInflater.from(context).inflate(R.layout.user_list_row_selected, parent, false)
}
}
// The bindView method is used to bind all data to a given view
// such as setting the text on a TextView.
override fun bindView(view: View, context: Context, cursor: Cursor) {
// Find fields to populate in inflated template
val tvBody = view.findViewById<View>(R.id.txtName) as TextView
val tvPriority = view.findViewById<View>(R.id.txtComment) as TextView
val tvPriority2 = view.findViewById<View>(R.id.txtThird) as TextView
val tvPriority3 = view.findViewById<View>(R.id.txtThi) as TextView
// Extract properties from cursor
val body = cursor.getString(cursor.getColumnIndexOrThrow(ContractClass.FeedReaderContract.COLUMN_NAME_ENWORD))
val priority = cursor.getString(cursor.getColumnIndexOrThrow(ContractClass.FeedReaderContract.COLUMN_NAME_DEFN))
val priority2 = cursor.getInt(cursor.getColumnIndexOrThrow(ContractClass.FeedReaderContract._id))
val priority3 = cursor.getInt(cursor.getColumnIndexOrThrow(ContractClass.FeedReaderContract.COLUMN_NAME_SELECTED))
// Populate fields with extracted properties
tvBody.text = body
tvPriority.text = priority.toString()
tvPriority2.text = priority2.toString()
tvPriority3.text = priority3.toString()
}
}
数据库表创建
private val SQL_CREATE_ENTRIES =
"CREATE VIRTUAL TABLE ${ContractClass.FeedReaderContract.TABLE_NAME} USING fts4(" +
"${ContractClass.FeedReaderContract._id}," +
"${ContractClass.FeedReaderContract.COLUMN_NAME_ENWORD} TEXT," +
"${ContractClass.FeedReaderContract.COLUMN_NAME_DEFN} TEXT," +
"${ContractClass.FeedReaderContract.COLUMN_NAME_SELECTED} INTEGER)"
我在这里找到了类似的帖子:List view with simple cursor adapter items checked are un-checked during scroll 但我认为,他们建议我已经做过的事情。
感谢您的帮助。
答案 0 :(得分:1)
对基础数据进行更改/更新后,您似乎没有更改ListView的Cursor。
请尝试在对基础数据进行更改之后,通过
更新ListView的Cursor。swapCursor(myCursor)
(或notiftDatasetChanged()
方法)这里相当于您的App,但使用Java而不是Kotlin(没有运气转换,因为我很少使用Kotlin)。
我相信这可以满足您的需求。就是
如果选择一个选定的(灰色)行,则包含该单词的那些行将被取消选择,并变为白色,而选定的列值又变回0
请注意,我没有创建FTS表,而是模仿了FTS,而是使用LIKE而不是MATCH。
如果选择它们,将切换背景为灰色,否则为白色。例如最初是:-
如果单击了猫(第二行),则所有其他猫行也将按照以下方式进行切换和变灰:-
以此类推。
public class MainActivity extends AppCompatActivity {
DBHelper dbhelper;
ListView myListView;
MyCursorAdapter myAdapter;
Cursor mCursor;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myListView = this.findViewById(R.id.myListView);
dbhelper = new DBHelper(this);
addSomeTestingData();
manageListView();
}
private void manageListView() {
mCursor = dbhelper.getAllRows();
if (myAdapter == null) {
myAdapter = new MyCursorAdapter(this,mCursor);
myListView.setAdapter(myAdapter);
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
dbhelper.updateSelected(mCursor.getString(mCursor.getColumnIndex(ContractClass.FeedReaderContract.COLUMN_NAME_ENWORD)));
manageListView();
}
});
} else {
myAdapter.swapCursor(mCursor);
}
}
private void addSomeTestingData() {
if (DatabaseUtils.queryNumEntries(dbhelper.getWritableDatabase(),ContractClass.FeedReaderContract.TABLENAME) > 1) return;
for (int i=0; i < 10; i++) {
dbhelper.addRow("Apple", "Thing that falls from trees");
dbhelper.addRow("Cat", "Something that is furry and sits on mats");
dbhelper.addRow("Bear", "Something that is furry that eats honey but doesn't ssit on a mat");
dbhelper.addRow("Dog", "Something is furry and friendly");
dbhelper.addRow("Echida", "An upside down hedgehog");
dbhelper.addRow("Ferret", "Something that is furry and found up trouser legs");
dbhelper.addRow("Giraffe", "Something that has 5 legs one pointing up");
dbhelper.addRow("Hippo", "An animal that loves mud and water but not humans");
dbhelper.addRow("Ibis", "A white feathered flying thing");
dbhelper.addRow("Jaguar", "A car or a large black cat");
dbhelper.addRow("Kangaroo", "A marsupial that boxes, skips and has a puch for shopping trips");
dbhelper.addRow("Lizard", "A rock dweller");
dbhelper.addRow("Mammoth", "A big hairy elephant now extinct");
dbhelper.addRow("Nuthatch", "A small bird that does not customise nuts so they have hatches.");
dbhelper.addRow("Ostrich", "A l argefast running bird that does not fly");
dbhelper.addRow("Panther", "A skinny pink cat that walks on only two of it's four lehs");
dbhelper.addRow("Queen", "A female rule of a country");
dbhelper.addRow("Rhinocerous", "A Hippo like animal that has a name that is hard to spell");
dbhelper.addRow("Tiger", "A live verion of Winnie the Pooh's friend Tigger");
dbhelper.addRow("Stork", "A skinny ostrich that flies and delivers children through Dream World.");
}
}
}
问题的症结在于 manageListView 方法。
public class DBHelper extends SQLiteOpenHelper {
public DBHelper(@Nullable Context context) {
super(context, ContractClass.DBNAME,null,ContractClass.DBVERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(ContractClass.FeedReaderContract.CRTSQL);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public Cursor getAllRows() {
SQLiteDatabase db = this.getWritableDatabase();
return db.query(ContractClass.FeedReaderContract.TABLENAME,null,null,null,null,null,null);
}
public void updateSelected(String selected) {
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL("UPDATE "
+ ContractClass.FeedReaderContract.TABLENAME
+ " SET " + ContractClass.FeedReaderContract.COLUMN_NAME_SELECTED
+ "= CASE " + ContractClass.FeedReaderContract.COLUMN_NAME_SELECTED +
" WHEN 1 THEN 0 ELSE 1 END " +
" WHERE " + ContractClass.FeedReaderContract.COLUMN_NAME_ENWORD + " LIKE ?",
new String[]{selected}
);
}
public long addRow(String enWord, String definition) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(ContractClass.FeedReaderContract.COLUMN_NAME_ENWORD,enWord);
cv.put(ContractClass.FeedReaderContract.COLUMN_NAME_DEFN,definition);
return db.insert(ContractClass.FeedReaderContract.TABLENAME,null,cv);
}
}
public class MyCursorAdapter extends CursorAdapter {
public MyCursorAdapter(Context context, Cursor c) {
super(context, c, false);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.row_list_row,parent,false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
if (cursor.getInt(cursor.getColumnIndex(ContractClass.FeedReaderContract.COLUMN_NAME_SELECTED)) < 1) {
view.setBackgroundColor(0xFFF9F9F9);
} else {
view.setBackgroundColor(0xFFD9D9D9);
}
TextView tvBody = view.findViewById(R.id.txtName);
TextView tvPriority = view.findViewById(R.id.txtComment);
TextView tvPriority2 = view.findViewById(R.id.txtThird);
TextView tvPriority3 = view.findViewById(R.id.txtThi);
tvBody.setText(cursor.getString(cursor.getColumnIndex(ContractClass.FeedReaderContract.COLUMN_NAME_ENWORD)));
tvPriority.setText(cursor.getString(cursor.getColumnIndex(ContractClass.FeedReaderContract.COLUMN_NAME_DEFN)));
tvPriority2.setText(cursor.getString(cursor.getColumnIndex(ContractClass.FeedReaderContract._id)));
tvPriority3.setText(cursor.getString(cursor.getColumnIndex(ContractClass.FeedReaderContract.COLUMN_NAME_SELECTED)));
}
}
答案 1 :(得分:0)
如果要使用多种不同的视图类型,则需要覆盖getItemViewType(position)
。如果不这样做,那么适配器将无法知道是否以View
的正确类型传递了convertView
实例,因此您将获得回收不良的视图。
对于CursorAdapter
来说,这似乎并不简单(我没有任何经验)。我认为正确的方法应该是这样的:
override fun getItemViewType(position: Int): Int {
cursor.moveToPosition(position)
val columnIndex = cursor.getColumnIndexOrThrow(ContractClass.FeedReaderContract.COLUMN_NAME_SELECTED)
return when (cursor.getInt(columnIndex)) {
0 -> 0
else -> 1
}
}
我还认为您应该更改newView()
以利用这些类型。保留您的应该正常工作,但是它将重复代码。
override fun newView(context: Context, cursor: Cursor, parent: ViewGroup): View {
val layoutId = when (val type = getItemViewType(cursor.position)) {
0 -> R.layout.row_list_row
1 -> R.layout.user_list_row_selected
else -> throw IllegalStateException("unexpected viewType: $type")
}
return LayoutInflater.from(context).inflate(layoutId, parent, false)
}