Android - How to read checked items when DialogFragment is called after create - android

I am using DialogFragment with multichoice checkboxes to allow the user to pick a number of options. I have a Hashmap to which selections are added or removed depending on whether on item is selected when it is clicked - see below. This works fine.
When the user re-opens the Fragment the state of the Dialog is preserved and the items that were previously checked are shown as expected - good so far. However I'd like to know how to read the state of these and add them to my HashMap so that they are returned along with any that are picked up by Listener class. I'm sure this is simple, but I can't find an example.
I've had a look through the API Reference but I can't find an obvious method that provides this.
Thanks in advance.
public class DialogSelectionClickHandler implements
DialogInterface.OnMultiChoiceClickListener {
public void onClick(DialogInterface dialog, int clicked,
boolean selected) {
if (selected) {
// write to a hashmap
groupSelectHash.put(groups[clicked].toString(), "");
}
else
{
// remove from hashmap
groupSelectHash.remove(groups[clicked].toString());
}
Log.i( "DialogTest", "groupSelectHash" + groupSelectHash.toString());
}
}

Related

Get all items from adapter (recyclerview) in Fragment

Hello I'm having an issue getting all of the items from my adapter in my fragment. To be more specific I am using a ScaleInAnimatorAdapter along with my Customer Adapter and when I attempt to get my checkbox items from the below posted code, within my Fragment, I only seem to get the visible items on screen.
private View.OnClickListener onAllClick = new View.OnClickListener() {
#Override public void onClick(View v) {
int count = listAdapter.getItemCount();
for (int i = 0; i < count; i++) {
View mChild = listTopics.getChildAt(i);
if( mChild != null ) {
Log.d(TAG,"getItemCount(): " + i );
CheckBox cBox = (CheckBox)mChild.findViewById(R.id.topic_chk);
cBox.setChecked(((CheckBox) v).isChecked());
Log.d(TAG,"isChecked" + cBox.getTag());
cBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(((CheckBox) v).isChecked()) {
checkboxAll.setChecked(false);
}
}
});
}
}
}
};
Essentially I am attempting to create a check all feature from the fragment, so that when this is clicked all of the checkbox items from the adapter are checked. I got that to work with the code I presented however the main issue is that I only get the items visible on the screen, so when I scroll to my other items they are not checked. Thus I am wondering if there is a better way or another way for me to get all of the items
Adapters are meant to bind underlying data stores to views; they generally shouldn't be used to store data themselves (except for having a copy of the data for view binding purposes) nor should they perform actions on data.
Instead, you should be modifying the underlying data, then updating the adapter through whatever mechanism you are already using. (Loaders, custom setters with notifyDataItemChanged, etc.).
Basically you can't. It'll be reusing the UI views.
You need to set a flag in all your data list objects, call notifyDataSetChanged() and onBindViewHolder check that flag and use it to check uncheck
if(listAdapter.getItem(position).getIsChecked())
viewHolder.checkBox.setChecked(true);
else
viewHolder.checkBox.setChecked(false);
Ok. Thank you all for those who have replied you helped me grasp something really basic and important that had alluded me.
I got it to work, so for anyone who might read this post, here is my solution:
Create necessary methods and field to update your data in a model (ie, private is_checked, set_checked(), is_checked(), etc)
In your adapter onBindViewHolder, you will set your holder checkbox to be associated to the data so something like:
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
obj.setSelected(buttonView.isChecked());
}
});
holder.checkBox.setChecked(obj.isSelected());
Then in your fragment or activity I just have a click listener on my main checkbox, and then when checked I loop through my data list, and using the model method I update my data and just simply use listAdapter.notifyDataSetChanged()
You are doing it wrongly.
You should update the adapter instead of updating the check box view.
What you can do , you can create a field in adapter data holder .
And whenever you change the selection,just update the field or multiple field and finally refresh the view.

ArrayList values changed without modification in android

I'm developing one Android Application.
I have one screen-A with show button. When user clicks on this show button, then I'm showing one dialog which contains Listview with checkboxes and two buttons submit , cancel.
editGroupUsersDialog = new Dialog(mcontext);
editGroupUsersDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
editGroupUsersDialog.setContentView(R.layout.edit_group_users_layout);
editGroupUsersDialog.setCanceledOnTouchOutside(true);
editGroupUsersDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
editGroupUsersDialog.show();
ArrayList<User> users = //got from the server;
Now I have taken one more static variable in the screnn-A and initialized with above users.
public static ArrayList<User> editUsers = users;
Now I have created adapter object and send the static users to the adapter.
ListView users_listview = (ListView)editGroupUsersDialog.findViewById(R.id.user_listView);
EditGroupUsersAdapter edit_group_users_adapter = new EditGroupUsersAdapter(
mcontext, edit_group_users);
users_listview.setAdapter(edit_group_users_adapter);
Now when the user check or uncheck any item in the dialog, then i'm setting the state of that item in the bean class User.
checkbox.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// add this line too for getting position of clicked
int pos = (Integer) v.getTag();
Log.v("Position is:", ""+pos);
Log.v("Befoer checkbox status is:", ""+GroupsAdapter.edit_group_users.get(position).isSelected());
if(!GroupsAdapter.edit_group_users.get(pos).isSelected()) {
//set the value to true in the user bean
GroupsAdapter.edit_group_users.get(pos).setSelected(true);
//checkbox.setChecked(true);
} else {
//set the value to false in the user bean
GroupsAdapter.edit_group_users.get(pos).setSelected(false);
//checkbox.setChecked(false);
}
}
});
Here i'm changing the state in static user variable only. i.e. GroupsAdapter.edit_group_users which is of type ArrayList
But the objects int non static variable users of type ArrayList is also changing.
I don't know what was the wrong I'm doing here.
The main purpose i'm taking another static variable of type **ArrayList is to store the modified User objects. But I don't want to change the original users which are available in users variable.
Please tell me how to solve my problem.
Thanks.
Both your static and non-static Arraylist are referencing to list of user.
Now say for some user A, you changes its state from X to Y. Then, this change will be reflected to both Arraylist because both Arraylist are pointing to same object, and you are changing the state of object.

ListView setSelection does not works for selecing simple list

I am making a single choice list inside a dialog.
I have completed all the basic functionalities like added a setonitemclicklistener but what i want is to set the first item of list by default, but when i use setSelection(1) it does not work:
i have done :
private void resetPosition(final ListView lv) {
lv.post(new Runnable() {
#Override
public void run() {
lv.setSelection(1);
}
});
}
and i am calling this function on button click which will start this dialog,
What is wrong with this code?
Documentation of setSelection() shows a line "If in touch mode, the item will not be selected but it will still be positioned appropriately" is this the fault?
If you need item selection, you should allow list items to be checked. You need to set the choice mode of the ListView to CHOICE_MODE_SINGLE using ListView.setChoiceMode(CHOICE_MODE_SINGLE).
Then you need to use ListView.setItemChecked(int position, boolean checked) method as ListView.setItemChecked(0, true) to set the first position as selected.
Also see: http://www.vogella.com/articles/AndroidListView/article.html#listviewselection

How to display a (modal) dialog at the very start of the app?

At the start of my Android app the user is required to choose from a list of alternatives. Here is why.
Let's assume I have a long list of items, and each item belongs to exactly one category. Each user is only interested in one specific category. Thus, when the app is started and the SharedPreferences don't contain any information about the selected category, a modal dialog should be displayed - here the user has to choose his or her category of interest. After having selected a category, only the items of that category are displayed.
So far, I tried to implement this behavior in the Activity's onCreate() method, which doesn't work obviously. The dialog is not shown or at least not long enough so that I could see it.
To be honest, I didn't expect the code to work by calling it from onCreate(). However, I was unable to find a suitable event handler in the Activity from where I could trigger the dialog.
Where should this dialog be triggered from in order to ensure the selection of a category (before any other data is loaded)?
Thanks in advance.
Here's the code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
setContentView(R.layout.activity_item_list);
...
ensureCategorySelected();
}
where the relevant method is
private void ensureCategorySelected() {
String chosenCategory = getCategoryFromSharedPreferences();
if (chosenCategory != null) {
final CharSequence[] items = getCategories();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Choose category");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
// handle the selection of the category
}
});
AlertDialog alert = builder.show();
}
}
You have a logic problem there. You want to show the dialog when there are still no preferences saved, and you are showing it when there are preferences saved. Change it to chosenCategory == null and it should work.
And why didn't you expect the code to work in onCreate()? I don't see a problem opening a dialog there.
Edit: I'm not quite sure if onCreate() is the correct place to show the dialog. Try putting ensureCategorySelected() in onStart() instead of onCreate().
You could also consider implementing an activity for this, which you could start with startActivityForResult().

Android - Spinner : how may I distinguish user's actions from computer's actions in a OnItemSelectedListener

I'm in a trouble managing a spinner, so may I ask for your help ?
I have a spinner with its adapter.
I initialize the spinner with a list of values when starting my activity.
Then I force the selected value to be the one used in the object that I manage.
Once the screen is initialized :
When the user selects a value in the spinner, according to the selected value, I may continue (or not) to another activity for let the user choose a complementary and necessary value.
If the user "cancels" this second activity, I want to rollback the spinner to its previous selected value, and cancel some actions made in the meantime.
If the user goes to the end of the second activity, everything is fine and I want juste to refresh the spinner display with the datas selected in the second activity (I overload the getView method in the adapter to do this).
Overall, I can easily do all of this, however, when I force the selected value in the spinner at the begining of my activity, or whene returning back from the second activity by "Cancel", the change value event is catched and the second activity is triggered (the user did not click anything at all).
How would you allow the second activity to be lauched only if the change of the selected value in the spinner is due to a manual action from the user, and prevent that same second activity to be launched when the value of spinner is changed "in the code "?
I tried many solutions, as setting a boolean into the adapter that tells if the next event will be raised because of an "in the code" action.
Or also putting a boolean in the adapter that tells if the adapter has initialised itself, and I force that boolean to true on the forst change catched event.
But nothing that really works fine.
Thank you for your help.
Oliver
I've always solved that issue with boolean flags, it isnt pretty at all, but it works if you think it through.
The idea is more or less, create a global usable boolean and init with false, in the onSelectedItemListener() use that boolean to choose wether or not to trigger the action, the important thing to remember is to set it to true after the computer has selected it the first time automatically, and reset it to false in the onResume() method.
This isnt perfect but it should work.
Edit:
bool spinnerUsable1;
bool spinnerUsable2;
int positionSpinner;
public void onCreate(Bundle savedInstanceState){
spinnerUsable1 = false;
spinnerUsable2 = true;
if(savedInstanceState != null){
positionSpinner = savedInstanceState.getInt("posSpinner");
if(positionSpinner != 0) spinnerUsable2 = false;
}
//Declare your spinner, set the on item selected lister
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
boolean spinnerUsable = (spinnerUsable1 && spinnerUsable2);
if (!spinnerUsable1) {
spinnerUsable1 = true;
} else if (!spinnerUsable2) {
spinnerUsable2 = true;
}
if (spinnerUsable) {
//Action;
}
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// Nothing
}
});
}
Something like this should work.

Categories

Resources