What action triggers onItemSelected in a ListView? - java

I have a ListView of Medications that use a CursorAdapter. My goal is to obtain a reference to the Cursor of the selected item when the user presses the submit button, but I keep getting a null value. Here is my current code:
mSubmitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Cursor selectedMedication = (Cursor) mMedicationListView.getSelectedItem();
if(selectedMedication != null)
{
MedicationSelectionListener activity = (MedicationSelectionListener) getActivity();
activity.onMedicationSelected(new Medication(selectedMedication));
} else{
Toast.makeText(getActivity(), "Must select a medication.", Toast.LENGTH_SHORT).show();
}
}
});
When this executes, selectedMedication is always null. I have implemented a drawable selector.xml file that changes the background color of the item when it is pressed, and that works fine, so I was under the impression that clicking the item was enough.
I have also tried the following, by setting the selected medication variable each time an item is clicked:
mMedicationListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor c = (Cursor) mMedicationListView.getItemAtPosition(position);
if(c.moveToFirst())
mSelectedMedication = new Medication(c);
}
});
This worked fine, but I felt it preformed a bunch of pointless operations when all I am interested in is the final selected item. Should clicking an item trigger mMedicationListView.onItemSelected()? If not, what action is used to ensure that happens?

so I was under the impression that clicking the item was enough.
Clicks are not selections with a ListView. A selection will occur either when:
you set a selection programmatically, or
the user uses a five-way navigation option (e.g., D-pad, trackball, arrow keys) and presses up/down on that to move a highlight bar around
all I am interested in is the final selected item
A ListView is a command widget by default. When the user taps on a row in a ListView, your app should go do something, usually getting rid of the ListView along the way.
If, OTOH, the user is choosing something, where the list and choice remain on-screen (e.g., master-detail pattern, choosing a state/province as part of filling in an address), then you should be using a choice mode. That could be a single-choice mode (usually represented with radio buttons down the right edge), multiple-choice mode (usually represented with checkboxes down the right edge), or multiple-choice-modal mode (usually represented by an "activated" state setting a persistent highlight, usually reserved for master-detail sorts of scenarios).
Do not attempt to overload "selection" to mean "choice". It sounds like you are presenting a ListView as part of something larger, where the user is making a choice, so use a choice mode for that.

Related

Changing the color of a listview view item that notifies data changes through an outer click listener of another list view

I am trying to change the color of the first row in "monitoredpatientlsit" which is a list view. The change should happen if I click on an item in allpatientslist and it already exists in monitoredpatient. So suppose I click on item 3, which also happens to be item 3 in monitoredpatients. I expect the code to change the color of the first view in monitored patient to red. However it doesn't, and I think it has to something to do with "notifydatasetchanged" method, because when I comment it out, it would work the way I want it to, but when I put it back to the code, there are no changes in the color at all. Any Idea why?
allpatientslist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (selectedpatients.contains(allpatients.get(position))){
selectedpatients.remove(selectedpatients.indexOf(allpatients.get(position)));
refomatToRed();
monitoredPatientListAdapator.notifyDataSetChanged();
view.setBackgroundColor(Color.parseColor("#F4F6F1"));
}else{
view.setBackgroundColor(Color.parseColor("#B0D880"));
selectedpatients.add(allpatients.get(position));
monitoredPatientListAdapator.notifyDataSetChanged();
}
}
});
public void refomatToRed(){
monitoredpatientslist.getChildAt(0).setBackgroundColor(Color.RED);
}
Edit:
I fixed it by just implementing the change of color inside the adaptor, since every time an item is removed by view due to the scrolling feature, the item is actually destroyed and will lose any formatting down to it.
When you call notifyDataSetChanged() on the adapter, the list is re-drawn. Changing the color of the first child has no effect because this child is destroyed at the following line.
Try inverting the lines like this:
monitoredPatientListAdapator.notifyDataSetChanged();
refomatToRed();

Android - How to save checkbox state (checked/unchecked) after changing activity

I have searched through StackOverflow, but have not found a proper answer yet.
I have created a ListView (iteration of a checkbox + itemview) and populated it through my customAdapter (which extends BaseAdapter).
I have a button which takes the values and print it on the screen via a Toast.
So far, so good.
Next step, I still have the button in the MainActivity, but the ListView is now in a child activity that I reach by clicking an image (ImageView placed in the MainActivity). I can still check the checkboxes, but I face two issues:
I am still not able to pass the values to the MainActivity, where they will be printed on screen (or manipulated)
As soon as I press the back button to go back to the MainActivity and I press again the image, every CheckBox that was checked is not checked anymore (they came back to default state)
I don't think that code is needed, as it comes from a standard implementation (ListView - customAdapter with ViewHolder implementation, ...), but in case just let me know.
Thanks a lot in advance!
You can put which checkboxes are checked into sharedpreferences. Then move the listview initialization code to Activity's onResume method.
Sample class to handle sharedpreferences data:
class DataHandler {
private final SharedPreferences dataStore;
DataHandler(Context mContext) {
dataStore = mContext.getSharedPreferences("appname", Context.MODE_PRIVATE);
}
int which() {
return dataStore.getInt("some_key",0);
}
void setCheckedItem(int itemwhat) {
dataStore.edit().putInt("some_key",itemwhat).apply();
}
}
For multiple values, you can put them into an array then convert them to string using toString() method and save. And, to get the values:
String x = "2,3,4,5"; //assume
String[] y = new String[]{x};
int checkablepositions = Integer.parseInt(y[0]); // y[0]....y[y.length-1]
Now, at MainActivity's onResume(), Assume that you have initialized ListView as 'mainList'.
CheckBox x1y2z3 = (CheckBox)mainList.getChildAt(new DataHandler(getBaseContext).which());
x1y2z3.setChecked(true);
And for Saving item,
I would recommend you to show them in an alert-dialog instead of in a Toast. Then set a Positive button to get the values from below code and save them.
Or, if you directly save the values from listview onClick :
mainList.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
new DataHandler(getBaseContext()).setCheckedItem(position);
}
});
That's it. I'm really new at programming (as you can see my StackOverFlow rep) but hope it will be able to help you.
The main concept is to : store the value → get the value → parse the value → show it on UI.

Not able to change the image color of the image view

I need some help here. I am fetching the data from the JSON.Fetching data. It consists of images and text and I am using the Fast Adapter(mike penz) to populate into recycler view, but when I select the specified row from the recycler view, it needs to change the image color. Where can I change the text view color by using the selector but I can't change the color of the image in the image view of the selected row. Please help me out. Here is the code:
service_type_adapter.withOnClickListener(new FastAdapter.OnClickListener<Service_Type_Adapter>() {
#Override
public boolean onClick(View v, IAdapter<Service_Type_Adapter> adapter, Service_Type_Adapter item, int position) {
AppCompatImageView service_image= (AppCompatImageView) v.findViewById(R.id.service_image);
int service_imagecolors = ContextCompat.getColor(getApplicationContext(), R.color.skyblue);
service_image.setColorFilter(service_imagecolors, PorterDuff.Mode.SRC_IN);
service_type_adapter.select(position);
if (lastselectedposition != -1) {
service_type_adapter.deselect(lastselectedposition);
}
lastselectedposition = position;
servicetypename = item.getServicename();
action = item.getServiceid();
googlemap.clear();
onMapReady(googlemap);
return true;
}
});
The FastAdapter's OnClickListener already provides you everything you need. It passes the clicked item, and also the Adapter responsible for the specific item.
So when the user clicks on the item (and you have enabled selection for that item) the FastAdapter will automatically set the state of that item to selected.
There are multiple ways of automatically applying the color in that case:
Use ColorStateList
The easiest solution is to define a ColorStateList instead of a simple color for that item. For example you could have a Foreground and just define a translucent color if the state is selected.
A very simple ColorStateList could look like this:
return new ColorStateList(
new int[][]{
new int[]{android.R.attr.state_selected},
new int[]{}
},
new int[] {
colorSelected,
Color.TRANSPARENT
}
);
Automatically Notify the Adapter about the change
The FastAdapter allows you to enable the bindView being called in case of the selection. Enable this via: FastAdapter.withSelectWithItemUpdate(true) After this the bindView method of that element is called and you can simply check for isSelected and define the ColorFilter or not
Notify the Adapter manually
If the adapter should not automatically call the notify method you can do this on your own also by doing fastAdapter.notifyAdapterItemChanged(position) (you can optional pass a payload in addition, so you can check for that one in the bindView method) after that check again in the bindView method for isSelected or not and handle the UI as you need it

How to refresh a listadapter from within an onclick

I have an Android app that displays a list using a ListView, and there's an action bar button to clear said list. I decided to add a confirmation dialog so people don't accidentally delete all their entries, and I'm running into problems. If I use setListAdapter inside the onclick for the "yes" button within the dialog, it won't compile. If I use it outside that onclick, it'll work but not refresh the list until the user backs out of the activity and goes back into it, which for obvious reasons is not appropriate. Here's my method that gets called when the "clear list" action bar button is pressed, which contains the relevant onclick for the internal buttons.
I have a feeling I shouldn't be using "this" in setListAdapter since with the dialog, this no longer corresponds to the listview activity I think? But I'm not sure what to put instead.
public void clearTrigger(MenuItem item) {
//Set up a dialog with two buttons to verify that the user really wants to delete
everything
confirm = new Dialog(display.this);
confirm.setContentView(R.layout.conf);
confirm.setTitle("Confirm deletion");
yes = (Button)confirm.findViewById(R.id.yes);
//If the user says yes, then delete everything
yes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Remove everything from Hours.
Hours.clear();
String tempH = " ";
String tempW = " ";
//Then save it again in it's new, empty state so that it doesn't reappear the next time the app is run.
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
SharedPreferences.Editor edit = prefs.edit();
edit.putString("SAVEDATA", TextUtils.join(",", Hours));
edit.remove("totalh");
edit.remove("totalw");
edit.commit();
//And finally... refresh the list view - doesn't work
setListAdapter(new ArrayAdapter<String>(this, R.layout.activity_list, R.id.listText, Hours));
confirm.dismiss();
}
});
confirm.show();
}
The first argument of ArrayAdapter constructor is a Context, so you need to pass the Activity to it, something like new ArrayAdapter<String>(MyActivity.this, ...). Right now you're passing it your instance of OnClickListener which is why it's giving compiler error.
But the best way to update a ListView is to make changes on the ArrayAdapter itself using methods like adapter.add and adapter.remove, and then call adapter.notifyDataSetChanged(). In your case, you would call adapter.clear().

Close Android Dialog Out of Scope

The Background: I've got a dialog that I'm populating with three ListViews, and when the user selects an item from either of those ListViews the dialog should dismiss itself. The ListView items also have long click behavior. This dialog has no buttons. I have no issues with displaying these ListViews.
The Goal: What I would like to do is close the dialog out of scope of the Java method in which I inflate the layout.
The Problem: I'm not quite sure how to do this. Currently my onClick method looks like this:
trigFunctionList.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
String text = trigFunctionStrings.get(position);
input.append(text + "(");
sysInput += text + "(";
}
});
And this is located out of scope of the method in which I declare my dialog. I would like to keep it this way, but I'm not sure how. Is such a thing possible? If so, thanks in advance for answers given.

Categories