简体   繁体   中英

Check a list view item from adapter when long clicked

I have a listview for a note application set with my adapter. The list view component consists of some textviews and a checkbox which pops up delete icon when a listview item is long clicked. Am automatically making the checkboxes visible from the adapter when the delete icon becomes visible so that the user could select the items he wants to delete.

The problem is i want a single list item to be automatically checked when long clicked. How do i go about this? My logic does not work.

listcomponent.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_marginTop="6dp"
    android:layout_marginLeft="6dp"
    android:layout_marginRight="6dp"
    android:background="#F5F5F5"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <View
        android:id="@+id/verticallineview"
        android:layout_width="4dp"
        android:layout_height="match_parent"
        android:background="@color/toast_color"
        />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:weightSum="1"
        android:orientation="horizontal">
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">
        <TextView
            android:id="@+id/list_note_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=""
            android:padding="1dp"
            android:textStyle="bold"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textColor="@color/light_black" />

        <TextView
            android:id="@+id/list_note_date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="1dp"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textColor="@color/colorPrimary"
            android:text=""
            />

        <TextView
            android:id="@+id/list_note_content_preview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="1dp"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:text=""
            android:textColor="@color/light_black"
            />
    </LinearLayout>
        <CheckBox
            android:id="@+id/checkbox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="0.2"
            android:layout_marginEnd="5dp"
            android:theme="@style/checkBoxStyle"
            android:visibility="gone"
            android:gravity="center"
            android:layout_gravity="center"
            android:layout_marginRight="5dp" />
    </LinearLayout>
</LinearLayout>

Adapter

   class NoteListAdapter extends ArrayAdapter<Note>{
private List<Note> objects;
private List<Note> originalList = new ArrayList<>();
boolean isLongPressed;
//    boolean isChecked;
boolean[] isChecked;
private boolean isItemsChecked;

NoteListAdapter(Context context, int resource, List<Note> objects) {
    super(context, resource, objects);
    this.objects = objects;
    this.originalList.addAll(objects);
    isLongPressed = false;
//        isChecked = false;
    isChecked = new boolean[objects.size()];
    for(int i=0; i<isChecked.length; i++) isChecked[i] = false;
}

@Override
public int getCount() {
    return objects.size();
}

@Nullable
@Override
public Note getItem(int position) {
    return objects.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_component, parent, false);
    }

    Note note = getItem(position);
    if (note != null) {
        TextView title = convertView.findViewById(R.id.list_note_title);
        TextView content = convertView.findViewById(R.id.list_note_content_preview);
        TextView date = convertView.findViewById(R.id.list_note_date);
        // setting checkbox logic on the adapter
        CheckBox checkBox = convertView.findViewById(R.id.checkbox);
// now i wanna toggle checked items from a checkbox on my header
  if (isItemsChecked) {
                checkBox.setChecked(true);
            } else {
                checkBox.setChecked(false);
            }
        if (isLongPressed) {
            checkBox.setVisibility(View.VISIBLE);
        } else {
            checkBox.setVisibility(View.GONE);
        }
        // also handle checks for all list view items
        checkBox.setChecked(isChecked[position]);
        checkBox.setTag(position);
        checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                CheckBox cb = (CheckBox) v;
                int checkedPosition = (int)cb.getTag();
                isChecked[checkedPosition] = cb.isChecked();
                notifyDataSetChanged();
            }
        });
    }
    return convertView;
}

void showCheckbox(int clickedPosition) {
    isLongPressed = true;
    for(int i=0; i<isChecked.length; i++) isChecked[i] = false;
    isChecked[clickedPosition] = true;
    notifyDataSetChanged();  // Required for update
}

void removeCheckbox() {
    isLongPressed = false;
    notifyDataSetChanged();  // Required for update
}

 void Check() {
      isItemsChecked = true;
        notifyDataSetChanged();  // Required for update
    }
    void Uncheck() {
        isItemsChecked = false;
        notifyDataSetChanged();  // Required for update
    }

NoteActivity.java

  private void listViewLongClick() {
            mListNotes.setLongClickable(true);
            mListNotes.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
                @Override
                public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
    // universal button controls all checked items
                 Checkbox  universalCheckBox = findViewById(R.id.check_all);
                universalCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
    na.Check();
} else {
    na.Uncheck();
}
                    }
                });
                    mDeleteButton = findViewById(R.id.delete_icon);
                   na.showCheckbox();
                    deleteButtonIn();
                    return true;
                }
            });
        }

The problem here is you have set the visibility of the checkBox from only one holder. Your logic is right but you haven't changed the visibility of checkBoxes from all the holders . You have to create a arrayList for holders and initialize them with null items.

private ArrayList<View> collectionOfViews = new ArrayList<>();
for (int i = 0; i < objects.size(); i++) {
   collectionOfViews.add(null);
}

This is my getView() from the adapter. Also to store checkStatus from all the boxes add a element checkStatus in your Note object.

if (note != null) {
        final TextView textView = convertView.findViewById(R.id.textView);
        final CheckBox checkBox = convertView.findViewById(R.id.checkBox);              
        checkBox.setChecked(note.getCheckStatus());
        textView.setText(note.getTextView());
        convertView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (checkBox.getVisibility() != View.GONE) {
                    note.changeCheckStatus();
                    checkBox.setChecked(note.getCheckStatus());
                }
            }
        });
        checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                note.changeCheckStatus();
                checkBox.setChecked(note.getCheckStatus());
            }
        });
        //setting holder in your array
        collectionOfViews.set(position, convertView);
        convertView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                note.changeCheckStatus();
                checkBox.setChecked(note.getCheckStatus());
                return true;
            }
        });
        checkBoxStatus();
        checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                checkBoxStatus();
            }
        });
}

The visibility of the checkBox is handled from checkBoxStatus()

void checkBoxStatus(){
    int count = 0;
    for (Note noteCheck : mData) {
        if (!noteCheck.getCheckStatus()) {
            count++;
        }
    }
    if (count == mData.size()) {
        for (View view : collectionOfViews) {
            if (view != null) {
                CheckBox checkBoxInside = view.findViewById(R.id.checkBox);
                checkBoxInside.setVisibility(View.GONE);
            }
        }
    }else{
        for (View view : collectionOfViews) {
            if (view != null) {
                CheckBox checkBoxInside = view.findViewById(R.id.checkBox);
                checkBoxInside.setVisibility(View.VISIBLE);
            }
        }
    }
    notifyDataSetChanged();
}

Read this article this may help you. I got this idea of storing views in array from here.

I hope this helps.

Try the code below:

Adapter:

class NoteListAdapter extends ArrayAdapter<Note>{
private List<Note> objects;
private List<Note> originalList = new ArrayList<>();
boolean isLongPressed;
//    boolean isChecked;
boolean[] isChecked;

NoteListAdapter(Context context, int resource, List<Note> objects) {
    super(context, resource, objects);
    this.objects = objects;
    this.originalList.addAll(objects);
    isLongPressed = false;
//        isChecked = false;
    isChecked = new boolean[objects.size()];
    for(int i=0; i<isChecked.length; i++) isChecked[i] = false;
}

@Override
public int getCount() {
    return objects.size();
}

@Nullable
@Override
public Note getItem(int position) {
    return objects.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_component, parent, false);
    }

    Note note = getItem(position);
    if (note != null) {
        TextView title = convertView.findViewById(R.id.list_note_title);
        TextView content = convertView.findViewById(R.id.list_note_content_preview);
        TextView date = convertView.findViewById(R.id.list_note_date);
        // setting checkbox logic on the adapter
        CheckBox checkBox = convertView.findViewById(R.id.checkbox);
        // now i wanna toggle checked items from a checkbox on my header
 //  if (isItemsChecked) {
 //           checkBox.setChecked(true);
 //       } else {
 //           checkBox.setChecked(false);
 //       }
        if (isLongPressed) {
            checkBox.setVisibility(View.VISIBLE);
        } else {
            checkBox.setVisibility(View.GONE);
        }
        // also handle checks for all list view items
        checkBox.setChecked(isChecked[position]);
        checkBox.setTag(position);
        checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                CheckBox cb = (CheckBox) v;
                int checkedPosition = (int)cb.getTag();
                isChecked[checkedPosition] = cb.isChecked();
                notifyDataSetChanged();
            }
        });
    }
    return convertView;
}

void showCheckbox(int clickedPosition) {
    isLongPressed = true;
    for(int i=0; i<isChecked.length; i++) isChecked[i] = false;
    isChecked[clickedPosition] = true;
    notifyDataSetChanged();  // Required for update
}

void removeCheckbox() {
    isLongPressed = false;
    notifyDataSetChanged();  // Required for update
}

void checkboxAllChange(boolean state) {
    isLongPressed = true;
    for(int i=0; i<isChecked.length; i++) isChecked[i] = state;
    notifyDataSetChanged();  // Required for update
}

//    void Check() {
//        isChecked = true;
//        notifyDataSetChanged();  // Required for update
//    }
//    void Uncheck() {
//        isChecked = false;
//        notifyDataSetChanged();  // Required for update
//    }

}

In Activity:

    mListNotes.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            deleteButtonIn();
            na.showCheckBox(position);
            return true;
        }
    });
    Checkbox  universalCheckBox = findViewById(R.id.check_all);
    universalCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            na.checkboxAllChange(buttonView.isChecked());
        }
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM