Custom layout with checkbox in listView: When I delete a line if it was checked(checkBox = true) the next line gets the check

五迷三道 提交于 2020-01-26 04:25:33

问题


When I delete a line if it was checked(checkBox = true) the next line gets the check.

I have few lines, second line checked third NOT checked. I delete second line, and then the third(which is now the second) becomes checked... I dont want it to be checked after delete.

I delete in Activity code in onContextItemSelected().

Adapter Code:

public class TodoAdapter2 extends ArrayAdapter<TodoTask>{

    Context context;
    int layoutResourceId;
    ArrayList<TodoTask> data = null;

    public TodoAdapter2(Context context, int layoutResourceId, ArrayList<TodoTask> data) {
        super(context, layoutResourceId, data);
        this.layoutResourceId = layoutResourceId;
        this.context = context;
        this.data = data;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View localView = convertView;
        todoHolder tempholder = new todoHolder();

        if(localView == null)
        {
            LayoutInflater inflater = ((Activity)context).getLayoutInflater();
            localView = inflater.inflate(layoutResourceId, parent, false);
            tempholder.task = (TextView) localView.findViewById(R.id.txtTodoTitle);
            tempholder.date = (TextView) localView.findViewById(R.id.txtTodoDueDate);
            tempholder.status = (CheckBox) localView.findViewById(R.id.toDoChecked);
            localView.setTag(tempholder);
        }
        else
        {
            tempholder = (todoHolder) localView.getTag();
        }
        final todoHolder holder = tempholder;

        final TodoTask currentTask = data.get(position);
        final CheckBox status = (CheckBox) holder.status;
        status.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            changeColorOnCheckBox(holder, status, currentTask);
          }
        });
        if(!holder.status.isChecked()){
          if(isOverdue(currentTask)){
            holder.task.setTextColor(Color.RED);
            holder.date.setTextColor(Color.RED);
        }
        else{
          holder.task.setTextColor(Color.BLACK);
          holder.date.setTextColor(Color.BLACK);
        }
      }

      holder.task.setText(currentTask.getTask());
      holder.date.setText(currentTask.toStringDate());
      return localView;
    }

    private static boolean isOverdue(TodoTask task){
      int currentDay = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
      int currentMonth = Calendar.getInstance().get(Calendar.MONTH)+1;
      int currentYear = Calendar.getInstance().get(Calendar.YEAR);
      if(task.getYear() < currentYear || task.getMonth() < currentMonth || task.getDay() < currentDay)
        return true;
      return false;
    }

    private static void changeColorOnCheckBox(todoHolder holder, CheckBox cb, TodoTask newTask){
      if (cb.isChecked()) {
        holder.task.setTextColor(Color.GREEN);
        holder.date.setTextColor(Color.GREEN);
      }
      else{
        if(isOverdue(newTask)){
          holder.task.setTextColor(Color.RED);
          holder.date.setTextColor(Color.RED);
        }
        else{
          holder.task.setTextColor(Color.BLACK);
          holder.date.setTextColor(Color.BLACK);
        }
      }
    }

    class todoHolder{
      CheckBox status;
      TextView task;
      TextView date;
    }
}

Activity code:

public class TodoListManagerActivity extends Activity {
    private ArrayList<TodoTask> tasks;
    private ListView list;
    TodoAdapter2 ad;
    final int BROWSER_ACTIVATION_REQUEST = 2; // request code

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        tasks = new ArrayList<TodoTask>();
        setContentView(R.layout.activity_todo_list_manager);
        list = (ListView) findViewById(R.id.lstTodoItems);
        ad = new TodoAdapter2(this, R.layout.todoline_layout, tasks);
        list.setAdapter(ad);
        registerForContextMenu(list);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        //Inflate the menu. this adds items to the action bar if it is present.
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.todo_list_manager_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //What happens when we click the menu.
        super.onOptionsItemSelected(item);
        if(item.getItemId() == R.id.menuItemAdd){
            Intent intent = new Intent(this, AddNewTodoItemActivity.class); 
            startActivityForResult(intent, BROWSER_ACTIVATION_REQUEST);
        }
        if(item.getItemId() == R.id.menuAbout){
            Toast.makeText(getApplicationContext(), "Made by Andrey Dobrikov", Toast.LENGTH_SHORT).show();
        }
        if(item.getItemId() == R.id.exitMenu){
            finish();
        }
        return true;
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
            ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
        int pos = info.position;
        TodoTask curTask = tasks.get(pos);
        String title = curTask.getTask();
        menu.setHeaderTitle(title); //set title for delete menu.

        MenuInflater inflater = getMenuInflater();
        if(firstWordCall(title) != -1){
            inflater.inflate(R.menu.context_delete_call, menu);
            MenuItem mi =(MenuItem) menu.findItem(R.id.menuItemCall);
            mi.setTitle(title);
        }
        else{
            inflater.inflate(R.menu.context_delete, menu);
        }
    }

    private int firstWordCall(String title) {
        String[] split = title.split(" ",2);
        String firstWord = split[0].toLowerCase();
        if(firstWord.equals("call")){
            String rest = split[1];
            rest = rest.replaceAll("\\s","");
            if(rest.startsWith("-")) return -1;
            rest = rest.replaceAll("-", "");
            if(rest.matches("^[0-9]+")){
                return Integer.parseInt(rest);
            }
        }
        return -1;
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
        int id = info.position;
        if(item.getItemId() == R.id.menuItemDelete){
            String itemToDelete = tasks.get(id).getTask();
            tasks.remove(id);
            ad.notifyDataSetChanged();
            Toast.makeText(getApplicationContext(), "Item: [" + itemToDelete + "] was successfully deleted!", Toast.LENGTH_SHORT).show();
        }
        if(item.getItemId() == R.id.menuItemCall){
            Intent callIntent = new Intent(Intent.ACTION_CALL);
            callIntent.setData(Uri.parse("tel:" + tasks.get(id).getNumber()));
            startActivity(callIntent);
        }
        return super.onContextItemSelected(item);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent input) {
        // if the results is coming from BROWSER_ACTIVATION_REQUEST 
        String newTask;
        int number = -1;

        if (requestCode == BROWSER_ACTIVATION_REQUEST) {

            // check the result code set by the activity
            if (resultCode == RESULT_OK) {
                if(input.hasExtra("Task") && input.getExtras().getString("Task") != null){
                    newTask = input.getExtras().getString("Task");
                    int day = input.getExtras().getInt("Day");
                    int month = input.getExtras().getInt("Month");
                    int year = input.getExtras().getInt("Year");
                    if(newTask.toLowerCase().contains("call")){
                        number = firstWordCall(newTask);
                    }
                    TodoTask todoLine = new TodoTask(day, month, year, newTask, number);
                    newTask += day;
                    newTask += month;
                    newTask += year;
                    tasks.add(todoLine);
                    ad.notifyDataSetChanged();
                }
            }
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
    }
}

回答1:


At first, uncheck the CheckBox then perform the deletion of the row item.




回答2:


UPDATE:

Mainly I think this problems is just a regular programming problem, not specific to Android. The idea is to use SharedPreferences and to save state. OR you save it in TodoTask and get state from there. It's up to you.

What you need is a way to identify each checkbox. In your scenario I would take an id from your TodoTask. Create one if you don't have one, attach it to the TodoTask object. This you would do on your TodoTask list creation. When you loop through TodoTask list in getView, you can just get

String anIdForThisCheckbox = data.get(position).getId()

since each TodoTask has a corresponding checkbox.

In your getView()

...
final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
boolean isChecked = pref.getBoolean(anIdForThisCheckbox,  false);
cb.setChecked(isChecked );
 ...

in your onClickListener:

cb.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        Editor editor = pref.edit();

        if (cb.isChecked()) {//Selected
            editor.putBoolean(anIdForThisCheckbox, true);//save state 

        } else {
            editor.putBoolean(anIdForThisCheckbox, false);
        }
    }
    editor.apply/commit
});
...

OLD: I think @hamid-shatu gave a good answer. Another solution would be to save away checkbox state as soon as user checks/unchecks and read status of that checkbox when you fetch it from holder. More work but if your chekbox state should survive orientation change or if you want to restore state after app has been killed, this is the way to go.




回答3:


1) first you need to create one class to fill listView and the element of the class should be whatever you want to display in list item and declare one integer ,than generate getter and setter method for it LIKE:

public class Demo{

  int state;

  public int getState() {

    return state;
  }

  public void setState(int state) {

    this.state = state;
  }

}

2) And then you need to fill List View with Array List of class ArrayList<Demo> ,and just maintain click when you uncheck check-box than you have to setState value to 0 by calling setter method and when you check the check-box then setState value to 1 by Calling the same setter method and call notifyDatasetChanged() method in your Adapter, And Main thing you have to do this all code in your adapter...

3) So, now when you will want to delete any list-item from list-view the procedure will be LIKE: First you will get position when you click on list-item, than you have to get class form arraylist for that position and Remove it from ArrayList , and again call notifyDatasetChanged() method in Adapter.




回答4:


After some more investigation i found the problem:

In my adapter code: This code need to be changed:

final TodoTask currentTask = data.get(position);
final CheckBox status = (CheckBox) holder.status;
status.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
    changeColorOnCheckBox(holder, status, currentTask);
  }
});

To this code:

final TodoTask currentTask = data.get(position);
final CheckBox status = (CheckBox) holder.status;

status.setChecked(currentTask.isChecked());
status.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
        changeColorOnCheckBox(holder, status, currentTask);
    if(status.isChecked()){
        Log.w("----------", "CheckboxT");
    currentTask.setChecked(true);
    }
    else{
        Log.w("----------", "CheckboxF");
    currentTask.setChecked(false);
    }
    }
});

This will update the actual line's check box that is being pressed.

Big thanks for all who was trying to help! Very appreciated!



来源:https://stackoverflow.com/questions/22472913/custom-layout-with-checkbox-in-listview-when-i-delete-a-line-if-it-was-checked

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!