问题
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;
}
});
}
回答1:
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());
}
});
回答2:
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.
来源:https://stackoverflow.com/questions/48664207/check-a-list-view-item-from-adapter-when-long-clicked