Android - 复选框在列表视图中每 10 次重复一次

Posted

技术标签:

【中文标题】Android - 复选框在列表视图中每 10 次重复一次【英文标题】:Android - Checkbox repeating every 10th in a listview 【发布时间】:2015-12-22 01:25:43 【问题描述】:

您好,我一直在尝试使用自定义适配器创建一个列表视图,以在其中放置两个文本视图和一个复选框。列表视图工作正常,但复选框开始每 10 个重复一次,因此如果您选中第一个复选框,则第 10 个复选框也会选中,依此类推。我对此进行了研究,但找不到一个可以很好解释的具体答案,我可以理解我必须做些什么来修复它。那么如何修复复选框以使其不重复?

act_view_items_view.xml

<RelativeLayout
    android:layout_
    android:layout_
    xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView
        android:layout_
        android:layout_
        android:text="New Text"
        android:id="@+id/workout_items_textView"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:textSize="20dp"
        android:gravity="center_vertical"
        android:layout_toStartOf="@+id/workout_items_textView2"
        android:layout_toLeftOf="@+id/workout_items_textView2"
        android:textIsSelectable="false"
        android: />

    <TextView
        android:layout_
        android:layout_
        android:text="New Text"
        android:id="@+id/workout_items_textView2"
        android:textSize="20dp"
        android:gravity="center_vertical"
        android:layout_toLeftOf="@+id/workout_items_CheckBox"
        android:layout_alignParentTop="true"
        android:/>

    <CheckBox
        android:layout_
        android:layout_
        android:id="@+id/workout_items_CheckBox"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:
        android:layout_alignBottom="@+id/workout_items_textView2"
        android:focusable="false"/>

</RelativeLayout>

view_items.java

public class view_items extends ListActivity 
    private ListAdapter listAdapter;
    private ListAdapter listAdapter2;
    private TaskDBHelper helper;
    private TextView taskTextView;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.act_view_items);

        updateUI2();


    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        switch (item.getItemId()) 
            case R.id.action_add_task:
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("Add a Workout");
                builder.setMessage("Enter the name of the workout");
                final EditText inputField = new EditText(this);
                builder.setView(inputField);
                builder.setPositiveButton("Next", new DialogInterface.OnClickListener() 

                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) 

                        AlertDialog.Builder builder2 = new AlertDialog.Builder(view_items.this);
                        builder2.setTitle("Add a Workout");
                        builder2.setMessage("Enter the reps for the workout");
                        final EditText inputField2 = new EditText(view_items.this);
                        builder2.setView(inputField2);
                        builder2.setPositiveButton("Next", new DialogInterface.OnClickListener() 


                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) 
                                String task = inputField.getText().toString();
                                String reps = inputField2.getText().toString();
                                String workoutID = TaskContract.UNSTABLE_WORKOUT_ID;

                                helper = new TaskDBHelper(view_items.this);
                                SQLiteDatabase db = helper.getWritableDatabase();
                                ContentValues values = new ContentValues();

                                values.clear();
                                values.put(TaskContract.Columns.TASK, task);
                                values.put(TaskContract.Columns.REPS, reps);
                                values.put(TaskContract.Columns.WORKOUT_ID, workoutID);

                                db.insertWithOnConflict(TaskContract.TABLE, null, values, SQLiteDatabase.CONFLICT_IGNORE);
                                updateUI2();
                            


                        );
                        builder2.setNegativeButton("Cancel", null);

                        builder2.create().show();

                    


                );

                builder.setNegativeButton("Cancel",null);

                builder.create().show();
                return true;

            default:
                return false;
        
    


    public void updateUI2()

        // TodoDatabaseHandler is a SQLiteOpenHelper class connecting to SQLite
        TaskDBHelper handler = new TaskDBHelper(this);
        // Get access to the underlying writeable database
        SQLiteDatabase db = handler.getWritableDatabase();
        // Query for items from the database and get a cursor back
        String sql2 = String.format("SELECT  * FROM workout_items WHERE %s = '%s'",
                TaskContract.Columns.WORKOUT_ID,
                TaskContract.UNSTABLE_WORKOUT_ID);


        Cursor todoCursor = db.rawQuery(sql2, null);

        // Find ListView to populate
        setContentView(R.layout.act_view_items);
        ListView lvItems = (ListView) findViewById(android.R.id.list);
        // Setup cursor adapter using cursor from last step
        view_items_CursorAdapter todoAdapter = new view_items_CursorAdapter(this, todoCursor, 0);
        // Attach cursor adapter to the ListView
        lvItems.setAdapter(todoAdapter);




    

    public void onDoneButtonClick(View view) 
        View v = (View) view.getParent();
        TextView taskTextView = (TextView) v.findViewById(R.id.taskTextView);
        String task = taskTextView.getText().toString();

        String sql = String.format("DELETE FROM %s WHERE %s = '%s'",
                TaskContract.TABLE,
                TaskContract.Columns.TASK,
                task);


        helper = new TaskDBHelper(view_items.this);
        SQLiteDatabase sqlDB = helper.getWritableDatabase();
        sqlDB.execSQL(sql);
        updateUI2();
    


view_items_CursorAdapter.java

public class view_items_CursorAdapter extends CursorAdapter 

    public view_items_CursorAdapter(Context context, Cursor cursor, int flags) 
        super(context, cursor, 0);
    


    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) 
        return LayoutInflater.from(context).inflate(R.layout.act_view_items_view, parent, false);
    


    @Override
    public void bindView(View view, Context context, Cursor cursor) 


        TextView tvBody = (TextView) view.findViewById(R.id.workout_items_textView);
        TextView tvPriority = (TextView) view.findViewById(R.id.workout_items_textView2);

        String body = cursor.getString(cursor.getColumnIndexOrThrow("task"));
        int priority = cursor.getInt(cursor.getColumnIndexOrThrow("reps"));

        tvBody.setText(body);
        tvPriority.setText(String.valueOf(priority));
    




【问题讨论】:

我猜这是因为你的适配器回收了视图,这意味着它重用了一个已经渲染的视图。为了达到最佳效果,您还需要在 bindView 方法上设置复选框的选中状态,就像使用 TextViews 一样 我是否可以将复选框的状态保存到 sql 数据库中,然后像使用 textviews 一样在 bindview 方法上设置它们的状态,否则效率不高吗? 如果选中状态是您认为应该始终可用的状态,那么我不明白为什么不这样做。但您可能希望在应用关闭时将其清除,否则已选中状态将跨会话保持。 【参考方案1】:

试试这个。希望这能解决您的问题。

 public class view_items_CursorAdapter extends CursorAdapter 
 boolean[] checkbox;
 public view_items_CursorAdapter(Context context, Cursor cursor, int flags)      

    super(context, cursor, 0);
    checkbox = new boolean[cursor.getCount()];



@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) 
    return LayoutInflater.from(context).inflate(R.layout.act_view_items_view, parent, false);



@Override
public void bindView(View view, Context context, Cursor cursor) 

    final int position = cursor.getPosition();
    TextView tvBody = (TextView) view.findViewById(R.id.workout_items_textView);
    TextView tvPriority = (TextView) view.findViewById(R.id.workout_items_textView2);
    CheckBox tvCheck = (CheckBox) view.findViewById(R.id.checkbox1);

    String body = cursor.getString(cursor.getColumnIndexOrThrow("task"));
    int priority = cursor.getInt(cursor.getColumnIndexOrThrow("reps"));

    tvBody.setText(body);
    tvPriority.setText(String.valueOf(priority));
    tvCheck.setChecked(checkbox[position]);
    tvCheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() 

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) 
         checkbox[position] = isChecked;
       );

【讨论】:

它不会重复,但它会在您滚动列表视图后将复选框重置为未选中。 好的,所以我稍微修改了代码,现在它似乎可以正常工作了。感谢这个很好的例子,它让我更好地理解了整个方法。

以上是关于Android - 复选框在列表视图中每 10 次重复一次的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 中每 10 秒显示一次数据

在android编程中选中复选框时,使用警报框显示从给定的自定义列表视图中删除行的代码

在 Android Studio 中每 10 秒显示一次位置

Android如何使用复选框识别列表视图中的项目

Android:如何在列表视图中自动显示带有复选框的 Sqlite 数据库

Android:需要在自定义适配器列表视图中保存复选框状态