how to checkbox without button and if the user does not check something is going return null.
How I called data from the check box
I called the data from the adapter with using a statement.
is send the data to interface with layout position
I called all layout data in my loop
I converted string to double to get sum all value is checked.
This is my task with using the button. I called this from the adapter.
I declared checkbox in my adapter:
holder.setItemCheckBox(new CheckboxListener() {
#Override
public void respond(View v, int position) {
CheckBox chk = (CheckBox) v;
double checkedSum = 0;
//Check if checked or not
if(chk.isChecked()){
checkdata.add(catalogDatabases.get(position));
}else if(!chk.isChecked()){
checkdata.remove(catalogDatabases.get(position));
}
}
});
This is my interface :
public interface CheckboxListener {
void respond (View v, int position);
}
Related
I am trying to implement a list of files that can be selected from the RecyclerView Adapter class. While I understand it is not a good idea, I feel if I am able to accomplish this from within said class, it would be really helpful in the future.
My list item (Each individual item view for the RecyclerView) has the following structure:
|--------|----------------|
| ICON | DATA |
|--------|----------------|
Problem:
When a file is selected (by touching the icon portion of a file item), I change the background of that item to another color to denote that it has been selected.
However, when I scroll down to about 25 items later, another file has the same background color even though it's not selected (it does not show up in Log.d as being selected, nor was it in the test ArrayList that was used to store selected files).
It seems as though the item is only retaining the background change of the previous occupant.
Solution attempts:
Previously, only the variables related to each list item were declared in the RecyclerView ViewHolder class and all changes were made in the onBindViewHolder method. Now, all changes to be made have been moved to the ViewHolder class inside a method called bind. There was no change in behavior.
If I set the default background image during the very first step in onBindViewHolder, the behavior changes such that the items do not retain changes of previous occupants. However, on scrolling back, the background change for the target item reverts to the default background image.
Code:
public class RVA extends RecyclerView.Adapter<RVA.RVH>
{
private LayoutInflater inf;
private ArrayList<File> items;
// The var below is used to track the no. of selected items
// globally within the RVA class.
private int numberOfSelectedItems = 0;
public RVA(ArrayList<File> _items)
{
items = _items;
}
#Override
public RVA.RVH onCreateViewHolder(ViewGroup parent, int viewType)
{
inf = LayoutInflater.from(parent.getContext());
return new RVH(inf, parent);
}
#Override
public void onBindViewHolder(RVA.RVH holder, int position)
{
File listItem = items.get(position);
// 'binding' each file element to a respective host container.
holder.bind(listItem);
}
#Override
public int getItemCount()
{
return items.size();
}
#Override
public long getItemId(int position)
{
return position;
}
// The ViewHolder class.
// Initially it was just declared as class.
// There was no change observed after the 'final' modifier was added.
final class RVH extends RecyclerView.ViewHolder
{
private Context context;
private LinearLayout itemSelector;
private ImageView itemIcon;
private TextView itemName;
private TextView itemSize;
public RVH(LayoutInflater inf, ViewGroup parent)
{
super(inf.inflate(R.layout.list_item, parent, false));
context = parent.getContext();
// This is the SECOND outermost LinearLayout of each file item View.
// It was previously the parent Layout, but there was no difference due to change.
itemSelector = itemView.findViewById(R.id.item_selector);
// This is the icon ImageView.
itemIcon = itemView.findViewById(R.id.item_icon);
// These are the data TextViews.
itemName = itemView.findViewById(R.id.item_id);
itemSize = itemView.findViewById(R.id.item_size);
}
// The 'bind' method that registers changes.
public void bind(File fileItem)
{
String listItemName = fileItem.getName();
itemName.setText(listItemName);
//---- These are just changes to the icons depending on type. Works fine.
if(fileItem.isDirectory())
{
itemIcon.setImageResource(R.drawable.directory_icon);
itemSize.setText("Directory");
}
else
{
itemSize.setText(fileItem.length() + " B");
if(listItemName.endsWith(".jpg") || listItemName.endsWith(".jpeg") || listItemName.endsWith(".png") || listItemName.endsWith(".gif"))
{
Glide.with(context).load(fileItem).centerCrop().into(itemIcon);
}
else
{
itemIcon.setImageResource(R.drawable.file_icon);
}
}
//---- END
//---- This is the code which handles opening files according to type. Works fine.
itemSelector.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if(numberOfSelectedItems == 0)
{
if(!itemSize.getText().toString().endsWith(" B"))
{
Intent loadListItemIntent = new Intent(context, DirectoryViewActivity.class);
loadListItemIntent.putExtra("ITEMPATH", fileItem.getPath());
context.startActivity(loadListItemIntent);
}
else
{
if(itemName.getText().toString().endsWith(".jpg") || itemName.getText().toString().endsWith(".jpeg") || itemName.getText().toString().endsWith(".png") || itemName.getText().toString().endsWith(".gif"))
{
Glide.with(context).load(fileItem).centerCrop().into(itemIcon);
Intent loadListItemIntent = new Intent(context, ImageActivity.class);
loadListItemIntent.putExtra("ITEMPATH", fileItem.getPath());
context.startActivity(loadListItemIntent);
}
else
{
Toast.makeText(context, "File needs proper application.", Toast.LENGTH_SHORT).show();
}
}
}
}
});
//---- END
//---- !!! THIS SECTION is where the problem manifests.
itemIcon.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if(itemIcon.getTag().toString().equals("not_selected"))
{
// Incrementing based on selection.
++numberOfSelectedItems;
// Using a tag to identify/ denote whether item is selected.
itemIcon.setTag("selected");
// Changing the background & disabling file opening while in selection mode.
itemSelector.setBackgroundResource(R.drawable.list_item_selected);
itemSelector.setClickable(false);
itemSelector.setLongClickable(false);
// I use this odd method to send a message to the host Activity
// that we have entered selection mode & that the Activity should
// display some option buttons on the Action Bar.
if(context instanceof DirectoryViewActivity)
{
((DirectoryViewActivity)context).addSelectedItem(fileItem);
if(numberOfSelectedItems == 1)
{
((DirectoryViewActivity)context).setSelectionMode();
}
}
}
else
{
// Decrementing based on deselection.
--numberOfSelectedItems;
// Overwiting the tag to identify/ denote item is now unselected.
itemIcon.setTag("not_selected");
// Background changed back to default & file opening re-enabled.
itemSelector.setClickable(true);
itemSelector.setLongClickable(true);
itemSelector.setBackgroundResource(R.drawable.list_item_background);
// I use this method to send a message to the host Activity
// that we have exited selection mode & that the Activity should
// remove related option buttons from the Action Bar.
if(context instanceof DirectoryViewActivity)
{
((DirectoryViewActivity)context).removeSelectedItem(fileItem);
if(numberOfSelectedItems == 0)
{
((DirectoryViewActivity)context).voidSelectionMode();
}
}
}
}
});
}
}
}
This is because RecyclerView does not create views for all of your items in the list it create enough ViewHolder to fill up the screen and few more and when you scroll the old ViewHolder are bind to some other data in the adapter that is when the onBindViewHolder() is called , so basically what is happening here is you are setting the background of current ViewHolder on the screen and when you scroll the same ViewHolder in bind to the new data.
I think you have to check in the onBindViewHolder whether or not this is the item to which you want to set the background and then take the decision remove it if the item is not selected in the dataset set background if it is selected.
The code for the spinner is below, The spinners on my app tend to duplicate it's content sometimes for some weird reason. How do I prevent this from happening?:
Spinner spinnerG = (Spinner) findViewById(R.id.spGroup);
final ArrayAdapter<String> dataAdapterG = new ArrayAdapter<>
(this, R.layout.simple_spinner_item, groups);
dataAdapterG.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
spinnerG.setAdapter(dataAdapterG); //general basics //sets up the group spinner, filled with the groups list
spinnerG.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
selectedGroup = groups.get(position);
studentsToShow.clear();
for(int i = 0; i < studList.size(); i++){
if(studList.get(i).getGroup().equals(selectedGroup)){
Students a = new Students();
a.setFirstName(studList.get(i).getFirstName());
a.setLastName(studList.get(i).getLastName());
a.setStudentID(studList.get(i).getStudentID());
a.setGroup(studList.get(i).getGroup());
studentsToShow.add(a); //when a new group is chosen the list of students in the selected group needs to be updated
} //this re uses the code earlier to make a list of student in the selected group
}
updateSpS(); //updates the student spinner
}
public void onNothingSelected(AdapterView<?> parent){
}
});
The spinner will duplicate if you have put this oncreate event. Put the spinner population code on the onResume method.
From the snippet shared with the question, its hard to guess why OP would have duplicate value. An educated guess is his onItemSelected() is being called multiple times.
Spinner's (in my personal view, is one of the worst android widget) onItemSelected() can be called multiple times for different reasons, one of the thing I would recommend to try this way -
class SpinnerInteractionListener implements AdapterView.OnItemSelectedListener, View.OnTouchListener {
boolean userSelect = false;
#Override
public boolean onTouch(View v, MotionEvent event) {
userSelect = true;
return false;
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (userSelect) {
// Your selection handling code here
userSelect = false;
if(view!=null){
selectedGroup = groups.get(position);
studentsToShow.clear();
for(int i = 0; i < studList.size(); i++){
if(studList.get(i).getGroup().equals(selectedGroup)){
Students a = new Students();
a.setFirstName(studList.get(i).getFirstName());
a.setLastName(studList.get(i).getLastName());
a.setStudentID(studList.get(i).getStudentID());
a.setGroup(studList.get(i).getGroup());
studentsToShow.add(a); //when a new group is chosen the list of students in the selected group needs to be updated
} //this re uses the code earlier to make a list of student in the selected group
}
updateSpS(); //updates the student spinner
}
}
}
}
And then set -
SpinnerInteractionListener listener = new SpinnerInteractionListener();
spinnerG.setOnTouchListener(listener);
spinnerG.setOnItemSelectedListener(listener);
This at the same time takes care unwanted callbacks of onItemSelected() without user touch and if any previous leaked listeners.
The result of my code is that all the checkboxes are checked only after I scroll down past the checkboxes in the recyclerView - when I scroll back up, they are checked.
How can I have them checked as soon as I click the button?
In my activity I have:
private void publicButton() {
publicContacts.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//loop through the contacts
int count = PopulistoContactsAdapter.theContactsList.size();
for (int i = 0; i < count; i++) {
PopulistoContactsAdapter.theContactsList.get(i).setSelected(true);
}
}
});
}
And for the recyclerViewAdapter:
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
//bind the views into the ViewHolder
//selectPhoneContact is an instance of the SelectPhoneContact class.
//We will assign each row of the recyclerview to contain details of selectPhoneContact:
//The number of rows will match the number of phone contacts
final SelectPhoneContact selectPhoneContact = theContactsList.get(position);
//if the row is a matching contact
if (viewHolder.getItemViewType() == 1)
{
//in the title textbox in the row, put the corresponding name etc...
((MatchingContact) viewHolder).title.setText(selectPhoneContact.getName());
((MatchingContact) viewHolder).phone.setText(selectPhoneContact.getPhone());
//((MatchingContact) viewHolder).check.setText("Cheeckbox" + position);
((MatchingContact) viewHolder).check.setChecked(theContactsList.get(position).isSelected);
((MatchingContact) viewHolder).check.setTag(position);
((MatchingContact) viewHolder).check.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//pos is the row number that the clicked checkbox exists in
Integer pos = (Integer) ((MatchingContact) viewHolder).check.getTag();
Toast.makeText(context_type, theContactsList.get(pos).getPhone() + " clicked!", Toast.LENGTH_SHORT).show();
if (theContactsList.get(pos).getSelected()) {
theContactsList.get(pos).setSelected(false);
} else {
theContactsList.get(pos).setSelected(true);
}
}
});
}
}
The onClick in the Adapter works as planned for individual checkboxes; their state is preserved. It's just when I try to select all of them with the button in the activity that the problem arises.
The simplest answer by far is to simply call notifyDataSetChanged() on your adapter after you make all of your setSelected() calls.
From your code, I can't tell if PopulistoContactsAdapter is an adapter instance, or if PopulistoContactsAdapter.theContactsList is a static variable... you'll need an adapter instance to call notifyDataSetChanged(). If you only have a reference to the RecyclerView, you can call myRecyclerView.getAdapter().notifyDataSetChanged().
I have a RecyclerView with each element representing an event. I want to let the user select events by clicking it. Once selected, the event(s) and a report button will be colored:
UI before performing a click: click here.
UI After performing a click: click here.
It's pretty simple and allegedly works; I set an OnClickListener for each ViewHolder which is responsible for coloring the item, and when fired it's triggering another event in the owning activity named onOccurrenceSelected, which is responsible for changing the button's state.
However, when scrolling through the RecyclerView's items, other irrelevant items are colored like their OnClickListener was triggered (though it wasn't), and when scrolling back the selected event is colored as not selected. While this is happening, the only event that's supposed to color the items is not triggered.
Any explanation for such behavior? Thanks!
EDIT: Here are some relevant code from the adapter:
private List<Occurrence> mDataSet;
private Activity activity;
public <OccurrencesActivity extends OnOccurrenceSelectedListener> OccurrencesAdapter(OccurrencesActivity occurrencesActivity, List<Occurrence> occurrences) {
this.activity = (android.app.Activity) occurrencesActivity;
mDataSet = occurrences;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
Occurrence instance = mDataSet.get(position);
...
setOnClickListener(holder, instance);
}
private void setOnClickListener(final ViewHolder holder, final Occurrence occurrence) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!occurrence.isSelected()) {
holder.itemView.setBackgroundColor(App.getContext().getResources().getColor(R.color.turquoise));
holder.titleTextView.setTextColor(App.getContext().getResources().getColor(R.color.white));
holder.statusTextView.setTextColor(App.getContext().getResources().getColor(R.color.white));
holder.dateTextView.setTextColor(App.getContext().getResources().getColor(R.color.white));
holder.timeTextView.setTextColor(App.getContext().getResources().getColor(R.color.white));
} else {
holder.itemView.setBackgroundColor(App.getContext().getResources().getColor(R.color.white));
holder.titleTextView.setTextColor(App.getContext().getResources().getColor(R.color.turquoise));
holder.statusTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
holder.dateTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
holder.timeTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
}
occurrence.setSelected(!occurrence.isSelected());
((OnOccurrenceSelectedListener)activity).onOccurrenceSelected(mDataSet);
}
});
}
Recyclerview always resuse views while scrolling so you have to store selected positions into temporary arraylist and then keep condition check into onBindViewHolder that whether that particular position is already exists in arraylist or not? I updated your adaper. find the below changes with comment
private List<Occurrence> mDataSet;
private Activity activity;
//Added here temporary ArrayList
private ArrayList<String> mSelectedPosition = new ArrayList<String>;
public <OccurrencesActivity extends OnOccurrenceSelectedListener> OccurrencesAdapter(OccurrencesActivity occurrencesActivity, List<Occurrence> occurrences) {
this.activity = (android.app.Activity) occurrencesActivity;
mDataSet = occurrences;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
//Set ViewTag
holder.itemView.setTag(position);
//Check everyposition during view binding process
if(mSelectedPosition.contains(String.valueOf(position))){
holder.itemView.setBackgroundColor(App.getContext().getResources().getColor(R.color.white));
holder.titleTextView.setTextColor(App.getContext().getResources().getColor(R.color.turquoise));
holder.statusTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
holder.dateTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
holder.timeTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
}else{
holder.itemView.setBackgroundColor(App.getContext().getResources().getColor(R.color.white));
holder.titleTextView.setTextColor(App.getContext().getResources().getColor(R.color.turquoise));
holder.statusTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
holder.dateTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
holder.timeTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
}
Occurrence instance = mDataSet.get(position);
...
setOnClickListener(holder, instance);
}
private void setOnClickListener(final ViewHolder holder, final Occurrence occurrence) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Get Position
int position = (int) view.getTag();
//Remove SelectedPosition if Already there
if(mSelectedPosition.contains(position))
mSelectedPosition.remove(String.valueOf(position));
else
mSelectedPosition.add(String.valueOf(position));
notifyDataSetChanged();
//Not sure about this lines
occurrence.setSelected(!occurrence.isSelected());
((OnOccurrenceSelectedListener)activity).onOccurrenceSelected(mDataSet);
}
});
}
Its the default behaviour of recyclerview. it will recycle/reuse views which are not in use currently. If you want to save the state which is colored or not. Then save a parameter in your List<Object> per position. and as per position in onBindViewHolder method use that position to change the color.
Try by Setting Tag to your item in onBindViewHolder of Adapter
holder.yourItem.setTag(position);
And then Inside the onClickListener,Just save that position in shared Pref. if it's selected, whenever you set adapter then before setting values just check that is it selected or not based on shared Pref. and perform action for same.
public void onClick(View view) {
if (!occurrence.isSelected()) {
//save position in share pref.
}
}
I want to perform a click on a Spinner element automatically after my activity has been loaded completely.
I use this code to set up the spinner and adapter:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_read_data);
getActionBar().setDisplayHomeAsUpEnabled(true);
mSpinnerDay = (Spinner) mTable.findViewById(R.id.spieltag_choice);
mAdapterSpinnerDay = new ArrayAdapter<CharSequence>(this, R.layout.custom_spinner);
mAdapterSpinnerDay.setDropDownViewResource(R.layout.custom_spinner);
mSpinnerDay.setAdapter(mAdapterSpinnerDay);
}
private void setUpSpinnerListener(final IGameData data) {
mSpinnerDay.post(new Runnable() {
public void run() {
mSpinnerDay.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
for (GameDayData d : data.getGameDay()) {
if (d.getName().equals(adapterView.getSelectedItem().toString())) {
TableRow row = (TableRow) mTable.findViewById(R.id.row_punkte_tag);
TextView t = (TextView) row.findViewById(R.id.punkte_tag);
t.setText("Punkte: " + d.getScore());
TableRow row2 = (TableRow) mTable.findViewById(R.id.row_position_tag);
TextView t2 = (TextView) row2.findViewById(R.id.position_tag);
t2.setText("Position: " + d.getPosition());
return;
}
}
}
public void onNothingSelected(AdapterView<?> adapterView) {
return;
}
});
}
});
}
public void onTeamCheckReadComplete(IGameData data) {
for (GameDayData d : data.getGameDay()) {
mAdapterSpinnerDay.add(d.getName());
}
}
I try to perform the click with following code after I have set the adapter to the spinner:
mSpinnerDay.setSelection(0, true);
View view = (View) mSpinnerDay.getChildAt(0);
long id = mSpinnerDay.getAdapter().getItemId(0);
mSpinnerDay.performItemClick(view, 0, id);
But this does not work. Could somebody tell me how I can perfom a click on a spinner element automatically? When I select the spinner item over touch event in the application everything works fine.
Regards,
Sandro
Corrected Solution
As I understand it, you have a spinner with items A, B, C, and D. You want item A pre-selected. You also want the user to be able to select A, B, C, and D and perform an action based on that.
In the onCreate() method:
mSpinner.setAdapter(myAdapter);
mSpinner.setOnItemSelectedListener(this); // have the activity implement
// OnItemSelectedListener interface
doAction(0);
Then implement the onItemSelected action like so:
#Override
void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
doAction(position);
}
You must implement the doAction(int position) method to handle how to update your activity based on the position of the item in your adapter. Clear?
Read more about this item and how to use it here:
http://developer.android.com/reference/android/widget/AdapterView.OnItemSelectedListener.html
I dont think you are calling setUpSpinnerListener from the code that you have posted. Even if you are calling it, i dont think it is advantageous to post a runnable to setuplistener.
Move all the code in runnable to just after setAdapter