The title pretty much says it all. I have a listview being populated by a simple adapter and an xml layout that changes based on how many rows are present in the listview item. When I add data to one of the items in the activity, calling the notifyondatasetchanged does not update the list, but if I back out of the activity and go back in everything looks the way it should. What do I need to do so when I refresh the adapter the getview gets updated as well?
public AlarmListAdapter(Context context, ArrayList<HashMap<String, String>> list, int textViewResourceId, String[] fields, int[] textViewId) {
super(context, list, textViewResourceId, fields, textViewId);
this.list = list;
this.context = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.alarm_list_item, null);
}
if(list.get(position).get("alert") == null){
v.findViewById(R.id.ListViewItemSub).setVisibility(View.GONE);
}
return super.getView(position, convertView, parent);
}
public void forceReload(){
notifyDataSetChanged();
}
The notifyondatasetchanged is being called from a popup within my activity. The code for that button is listed below:
addCustomAlertButton = (Button)pView.findViewById(R.id.AddCustomAlertButton);
addCustomAlertButton.setOnClickListener(new OnClickListener(){
public void onClick(View v){
arrayList.get((int) customAlertId).setAlertDialog(customAlertInput.getText().toString());
Toast.makeText(EditAlarmsActivity.this, "Custom Alert Added", Toast.LENGTH_SHORT).show();
updateListArray();
pw.dismiss();
}
You could try setListAdapter(yourAdapter);
or listview.requestLayout();
If those didn't work then you could also try refreshing the listview through scrolling, since the getView() function is called once the listview is scrolled.
Related
I have a arraylist of buttons (reserveButtons) that I can display in a listview. I have made a search function which searches in my database and outputs a list of integers (resultID). They correspond to the indexes of reserveButtons I want to display.
Simply put, I want to do something like this when the search button is clicked:
ArrayAdapter<ReserveButton> adapter = new MyListAdapter();
ListView list = (ListView) myView.findViewById(R.id.resultslist);
list.setAdapter(adapter);
for (int result : resultID) {
adapter.add(reserveButtons.get(result));
}
So, for each result, I want to add the corresponding button to the listview.
Here is the private class MylistAadapter :
private class MyListAdapter extends ArrayAdapter<ReserveButton> {
public MyListAdapter() {
super(getActivity(), R.layout.list_item, reserveButtons);
}
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = convertView;
if(itemView == null) {
itemView = gettActivity().getLayoutInflater().inflate(R.layout.list_item, parent, false);
}
ReserveButton currentButton = reserveButtons.get(position);
//the resultItem is the id of the buttons
Button butt = (Button) itemView.findViewById(R.id.resultItem);
butt.setBackground(currentButton.getImage());
return itemView;
}
}
I know that getView will just display every reserveButton, but I want the code in getView to be executed when I add each button, but the position doesn't change since position = result in the for loop of the first code block.
//This code is inside MyListAdapter
#Override
public void add(ReserveButton object) {
/* What do I write here to inflate a list_item and give it
the background image reserveButton.get(result).getImage() */
super.add(object);
}
How do I override the add method of MyListAdapter so that I can add a reserveButton and change its background image for each result in the resultID list.
If the same thing can be accomplished without the add method, please do tell.
P.S: I do not want to just list every reserveButton and then filter them with the search; I want to display ONLY the buttons that the user is looking for.
I figured it out myself!
Basically, what I did was create a separate ArrayList of ReserveButtons and do the foreach loop like so:
int index = 0;
for (int result : resultID) {
//result is the single ID of an answer
answerButtons.add(index,reserveButtons.get(result));
index ++;
}
populateListView();
So I end up storing ONLY the buttons I want to display in the answerButtons list. And here is what happens in populateListView()
private void populateListView() {
ArrayAdapter<ReserveButton> adapter = new MyListAdapter();
ListView list = (ListView) myView.findViewById(R.id.resultslist);
list.setAdapter(adapter);
}
and the getView() method:
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = convertView;
if(itemView == null) {
itemView = getActivity().getLayoutInflater().inflate(R.layout.list_item, parent, false);
}
//Just set the image of the corresponding answerButton
ReserveButton currentButton = answerButtons.get(position);
Button butt = (Button) itemView.findViewById(R.id.resultItem);
butt.setBackground(currentButton.getImage());
return itemView;
}
Problem solved. I haven't seen any answers to a problem like this, so this post should make it easily google-able for any newcomer who stumbles upon this problem.
So I have a List View that when you click on a row it opens up a new activity. In the new activity there's a checkbox. If you check the check box and then go back to the listview activity it should set a checkmark next to the list view item that was initially clicked.
Whats happening right now is when I check the checkbox and return to the listview every row has a checkmark next to it regardless of which row the checkbox was checked from.
heres my mainactivity with the listview and on click listener that starts the second checkbox activity
//fill list view with xml array of routes
final CharSequence[] routeListViewItems = getResources().getTextArray(R.array.routeList);
//custom adapter for list view
ListAdapter routeAdapter = new CustomAdapter(this, routeListViewItems);
final ListView routeListView = (ListView) findViewById(R.id.routeListView);
routeListView.setAdapter(routeAdapter);
routeListView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int listViewItemPosition = position;
CharSequence route = routeListViewItems[position];
int imageId = (int) image.getResourceId(position, -1);
if (route.equals(routeListViewItems[position]))
{
Intent intent = new Intent(view.getContext(), RouteDetails.class);
intent.putExtra("route", routeDetail[position]);
intent.putExtra("imageResourceId", imageId);
intent.putExtra("routeName", routeListViewItems[position]);
intent.putExtra("listViewItemPosition", listViewItemPosition);
startActivity(intent);
}
}
}
);
}
then heres what im passing from the second activity back to the listview activity
#Override ///////for back button///////
public void onBackPressed() {
super.onBackPressed();
////////sets checkmark next to listview item//////
if (routeCheckBox.isChecked())
{
Intent check = new Intent(RouteDetails.this,MainActivity.class);
check.putExtra("checkImageResource", R.drawable.checkmark);
check.putExtra("listViewItemPosition", listViewItemPosition);
startActivity(check);
}
}
and heres back in my listview activity where I recieve the info from my checkbox activity and set the checkmark
edited to include full adapter class
edited to include code that I found to solve my issue!
class CustomAdapter extends ArrayAdapter<CharSequence> {
public CustomAdapter(Context context, CharSequence[] routes) {
super(context, R.layout.custom_row ,routes);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater routeInflater = LayoutInflater.from(getContext());
View customView = convertView;
if(customView == null){customView = routeInflater.inflate(R.layout.custom_row, parent, false);}
CharSequence singleRoute = getItem(position);
TextView routeText = (TextView) customView.findViewById(R.id.routeText);
routeText.setText(singleRoute);
/////////////set check mark/////////////
ImageView checkImageView = (ImageView) customView.findViewById(R.id.checkImageView);
int checkImageResourceId = ((Activity) getContext()).getIntent().getIntExtra("checkImageResource",0);
int listViewItemPosition = ((Activity) getContext()).getIntent().getIntExtra("listViewItemPosition",0);
/////my solution was just setting where listviewitemposition == position in my getview method//////
if (listViewItemPosition == position)
{
checkImageView.setImageResource(checkImageResourceId);}
//////////////////////////////////////////////////
return customView;
}
thanks for any help!
The solution was I just needed use an if statement to set listviewItemPosition == position in my getView method
/////my solution was just setting where listviewitemposition == position in my getview method//////
if (listViewItemPosition == position)
{
checkImageView.setImageResource(checkImageResourceId);}
//////////////////////////////////////////////////
Im trying disable some items in listview , but cant to do it.
I have Array of booleans
private boolean[] array; //10 items all false, and some of them true
in code im trying
for(int i=0;i<array.length();i++){
if(!array[i]){
listview.getChildAt(i).setEnabled(false);
}
}
but im always got nullpointerexception on string "listview.getChildAt()"
if write like
if(listview.getChildAt(i)!=null){ //do code here }
than i see what no entrance to string "getChildAt(i).setEnabled(false)"
im little not understand about getChildAt but i was thinking its way where i can get items by position. Any one can help me how to do it?
adapter for list view
public class LevelAdapter extends ArrayAdapter<String> {
public LevelAdapter(Activity context, ArrayList<String> le, ArrayList<Integer> co, boolean[] bools) {
super(context, R.layout.listviewitem, le);
this.context = context;
this.l = le;
this.s = co;
this.boolStates = bools;
}
#Override
public View getView(final int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.listviewitem, null, true);
tvL = (TextView) rowView.findViewById(R.id.l);
tvC = (TextView) rowView.findViewById(R.id.s);
tvL.setText(""+l.get(position));
tvCt.setText(""+s.get(position) + "/3");
return rowView;
}
}
regards , Peter.
SOLUTION
in adapter check
if(lvl[position]==false){
rowView= inflater.inflate(R.layout.listviewitemdisabled, null, true);
rowView.setEnabled(false);
}else
{
rowView= inflater.inflate(R.layout.listviewitem, null, true);
}
and when click on
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (view.isEnabled()) {
// do our code here
thanks for this easy solution
You can set enabled state in your adapter.
rowView.setEnabled(false)
Use Adapter approach.
Create an adapter and a viewHolder and in OnBind method just get that item of list and disable it.
send value to the adapter using method and notify the adapter about change.
I have written a small app that has a ListView with a custom adapter. Each row contains some Buttons, which will change background color when clicked, and I got the list items to be clickable as well by putting
android:descendantFocusability="blocksDescendants"
in the xml of the list items. But now I have this weird bug where clicking on the list item reverts all clicked Buttons back to their original colorless state. How can I get the Buttons to keep their color?
Details:
Part of the custom adapter:
View.OnClickListener onButtonClicked = new View.OnClickListener() {
#Override
public void onClick(View button) {
View listItem = (View) button.getParent();
final long DBid = (long) listItem.getTag();//database ID
final Button b = (Button) button;
sqldataDataSource datasource = new sqldataDataSource(context);
datasource.open();
datasource.updateButton(DBid);
datasource.close();
b.setBackgroundColor(0xFF386F00);
}
};
As you can see, I change the background color AND change the database entry, so when the whole list is reloaded, the Button keeps its color (another part of my custom adapter):
public View getView(int i, View convertView, ViewGroup parent) {
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.hrlistitems, parent, false);
Button b = (Button) rowView.findViewById(R.id.HRlistB);
b.setOnClickListener(onButtonClicked);
if(!(values.get(i).getB().equals(""))){
b.setBackgroundColor(0xFF386F00);
}
return rowView;
}
This works fine when going to another activity and coming back to this one. The buttons are created colored as expected.
So my guess was that the list is recreated from the original listItem array when an item is clicked, which is why I tried to fix this by reloading my database, like so (from my activity):
#Override
protected void onStart() {
super.onStart();
datasource = new sqldataDataSource(this);
datasource.open();
listItems = datasource.getOnlyRoutes(id);//this works fine
Collections.sort(listItems, HallenRoute.vergleichen());
if (mListView == null) {
mListView = (ListView) findViewById(R.id.listViewHalle);
}
adapter=new customAdapter(this, listItems);
setListAdapter(adapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int pos, long nid) {
listItems.get(pos).increaseCount();
datasource.updateCountHR(listItems.get(pos));
listItems = datasource.getOnlyRoutes(id);//fix I tried, doesn't work
Collections.sort(listItems, HallenRoute.vergleichen());
adapter.notifyDataSetChanged();
}
});
}
But this doesn't work.
How can I get the ListView to either not reload on ItemClick or reload properly (i.e. from database)?
You don't have to reload the whole data for every Button click.
In your Button click you're just updating the data base and not your adapter dataset values, this is why you always get the old background color.
public View getView(int i, View convertView, ViewGroup parent) {
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.hrlistitems, parent, false);
Button b = (Button) rowView.findViewById(R.id.HRlistB);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View button) {
View listItem = (View) button.getParent();
final long DBid = (long) listItem.getTag();//database ID
final Button b = (Button) button;
sqldataDataSource datasource = new sqldataDataSource(context);
datasource.open();
datasource.updateButton(DBid);
datasource.close();
//b.setBackgroundColor(0xFF386F00); no need for this line, getView() method will take care of the background
//update your adapter dataset, eg: values.get(i).setB("newColor");
notifyDataSetChanged(); // to refresh your adapter
}
});
if(!(values.get(i).getB().equals(""))){
b.setBackgroundColor(0xFF386F00);
}
return rowView;
}
PS: It's better if you save your "database ID" in your Model object not as a View tag.
I have made a ListView which is populated with elements of an ArrayList. I do not have an XML file with this ListView, it is only in Java. Given this, how would I change the background color of the ListView as well as change the color of the text of the ListView?
This is the code for the ListView:
setListAdapter(new ArrayAdapter<String>(CollegeList.this, android.R.layout.simple_list_item_1, nameList));
In case you want to customize each line of the listview you have to use a custom adapter with custom listview item. Then you can use the "getView" Method to catch each item and position to change colors.
Here is a sample:
public class ListViewAdapter extends ArrayAdapter<Item> {
private Context context;
private int itemResourceId;
private ArrayList<Item> items;
public ListViewAdapter(Context context, int layoutId, ArrayList<Item> items) {
super(context, layoutId, items);
this.context = context;
this.itemResourceId = layoutId;
this.items = items;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
ViewHolder holder = null;
if (view == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(itemResourceId, null);
holder.listItem = (TextView) view.findViewById(R.id.item);
view.setTag(holder);
}
else
holder = (ViewHolder) view.getTag();
if (position % 2 == 0)
view.setBackgroundColor(context.getResources().getColor(R.color.listItemEven));
else
view.setBackgroundColor(context.getResources().getColor(R.color.listItemOdd));
Item item = items.get(position);
holder.listItem.setText((position+1) + ". " + item.sTitle);
return view;
}
static class ViewHolder {
TextView listItem;
}
}
android.R.layout.simple_list_item_1
You have to add an extra parameter to your ArrayAdapter, this will be a CUSTOM XML OF YOUR OWN and the next one will be a textview that is inside that custom layout, that way the array adapter will know which layout to fill and which textview needs to show the data you want to show.
from that xml you can modify background and color. will look something like this:
setListAdapter(new ArrayAdapter<String>(CollegeList.this, R.layout.your_custom_layout, R.id.the-text-view-in-that-layout, nameList));
You can get the xml for simple_list_item_1 here. You can copy it to your project and modify it, just change the code for your listview to setListAdapter(new ArrayAdapter<String>(CollegeList.this, R.layout.simple_list_item_1, nameList)); You can also create one yourself, since simple_list_item_1 is nothing but a textview. Just make sure that the id is android:id="#android:id/text1" otherwise it won't work with the default adapter.