Cannot get listitems to reload from database - java

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.

Related

Search listview but instead of filtering, just inflate and display the valid items

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.

Setting ImageView at certain positions in a ListView based on CheckBox

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);}
//////////////////////////////////////////////////

Change image when click imagebutton item custom listview android

I have a custom listview, each item have a imagebutton, i want to change image of each imagebutton immediately when I click. Each item in custom listview is a object named baiHat{}.
I use BaiHatAdapter like this, but it not chane immediately, i must scroll listview to see change.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater=this.context.getLayoutInflater();
View row=inflater.inflate(this.resource, null);
TextView txtMs = (TextView) row.findViewById(R.id.ms);
TextView txtBh = (TextView) row.findViewById(R.id.bh);
TextView txtCs = (TextView) row.findViewById(R.id.cs);
TextView txtLr = (TextView) row.findViewById(R.id.lr);
ImageButton imglike = (ImageButton) row.findViewById(R.id.imageButton);
final BaiHat baiHat = this.objects.get(position);
txtMs.setText(baiHat.getTxtms());
txtBh.setText(baiHat.getTenBh());
txtCs.setText(baiHat.getTxtcs());
txtLr.setText(baiHat.getTxtLr());
imglike.setImageResource(baiHat.getImg());
imglike.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
xulythich(baiHat);
}
});
return row;
}
private void xulythich(BaiHat baiHat) {
if(baiHat.getThich()){
baiHat.setThich(false);
baiHat.setImg(R.drawable.addfav);
}else{
baiHat.setThich(true);
baiHat.setImg(R.drawable.added);
}
}
Create a selector file and assigning it as src would work. But as a better approach you can try to change it to togglebutton, since imageview is not meant to be clickable and give it the background of selector source.
It will just look like any imageview but with the capability of being clickable and changing its background from the selector file.

How do I change data in a ListView of a Fragment from a ListAdapter?

I have a Fragment which contains a few ListViews. I have my ListAdapter, which customizes the ListViews so that only one group will show a button and add an OnClickListener to that button. I am trying to make the OnClickListener add an item to one of my lists in my Fragment, but the problem is that I cannot find out how to interact with any of the methods in my Fragment. Perhaps, there is also a better way to do this than directly through the ListAdapter.
SlidingMenuFragment.java - the fragment
/**
* Adds a child to favorite locations section list
* #param v the view
* #param location the location to add
*/
public void addFavoriteLocation(View v, String location){
mFavoriteLocationsSection.addSectionItem(99, "test location", "slidingmenu_clear");//TODO change dummy values
sectionListAdapter.notifyDataSetChanged();
}
SectionListAdapter.java - the list adapter
#Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.slidingmenu_sectionview,
parent, false);
}
TextView textView = (TextView) convertView
.findViewById(R.id.slidingmenu_section_title);
textView.setText(((Section) getGroup(groupPosition)).getTitle());
//Sets the group "Favorite Locations" to have the only add_button as VISIBLE, and other groups to GONE
//Set an onClickListener to add button as well
if( sections.get(groupPosition).getTitle().equalsIgnoreCase("Favorite Locations") ){
convertView.findViewById(R.id.favoritelocations_addbutton).setVisibility(View.VISIBLE);//works
convertView.findViewById(R.id.favoritelocations_addbutton).setOnClickListener(new OnClickListener() {//doesnt
#Override
public void onClick(View v) {
//I am trying to call addFavoriteLocation(...) here, but can't figure out how to do so
}
});
}else{
convertView.findViewById(R.id.favoritelocations_addbutton).setVisibility(View.GONE);
}
return convertView;
}
I finally figured it out...inside my OnClickListener
MainActivity mainAct = (MainActivity) context;
mainAct.addFavoriteLocation

GridView onItemClickListener never gets invoked

I have a GridView with custom View in it, which is a Button and a TextView. I defined the setOnItemClickListener but it looks like it never invoked, please see peaces of code below.
gridview = (GridView) findViewById(R.id.main_gridview);
gridview.setAdapter(new GridAdapter(this));
gridview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getApplicationContext(), "gadsfadsf",
Toast.LENGTH_SHORT).show();
Log.d("Main", "onItemClick");
}
});
The marked answer is kind of a hack. Instead of setting an onclicklistener to the button just ensure, that the ButtonView and the TextView has the following property:
android:clickable="false"
I had the same issue. While I've not yet figured out why it never gets invoked, I can propose a workaround.
Instead of setting the onClickListener on your GridView, set it on the Button itself inside your GridAdapter, inside your getView() method.
That worked for me!
It could be that some items in your GridView are stealing focus. Try adding these attributes to any elements you have inside the grid:
android:focusable="false"
android:focusableInTouchMode="false"
Instead of setting the onClickListener on your GridView,
set it on the Button itself inside your GridAdapter, inside your getView() method.
That worked for me!
I had the same problem, the event grid.itemClickListener was never launched.
In my case I had two listeners: grid.itemClickListener and another clickListener attached to a Button within the item's layout.
After fiddling with the layout for a while, I realized that if there was a widget, within the item's layout, with focusable=true, then itemClickListener was never launched. The clickListener attached to the Button worked well though.
Maybe that was your case. Anyway, I think this information might be useful to other users running into the same problem.
Thanx to CodingUser
what we were doing is directly accessing the Layout inside the GridView, so the onItemClickListener finds it confusing to access the item.
So the solution is to apply the onClickListener inside the Adapter (i.e. normally ArrayAdapter)
so what i m trying to say is:
public View getView(int position, View convertView, ViewGroup parent) {
//Here row is a view and we can set OnClickListener on this
final View row;
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
//Here we inflate the layout to view (linear in my case)
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ViewHolder();
holder.imageTitle = (TextView) row.findViewById(R.id.text);
holder.image = (ImageView) row.findViewById(R.id.image);
row.setTag(holder);
} else {
row = convertView;
holder = (ViewHolder) row.getTag();
}
ImageItem item = data.get(position);
holder.imageTitle.setText(item.getTitle());
holder.image.setImageBitmap(item.getImage());
//Now get the id or whatever needed
row.setId(position);
// Now set the onClickListener
row.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(context, "Clicked" + row.getId() + "!!",
Toast.LENGTH_SHORT).show();
}
});
return row;
}
You can set OnClick for view in Adapter of GridView .It work for me .
public View getView(final int position, View convertView, ViewGroup parent) {
ObjMenuVideo objListVideo = mListMenuVideo.get(position);
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.item_video_of_kind, null);
holder.tv_number_views = (TextView) convertView
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tv_number_views.setText(String.valueOf(objListVideo.getViews()));
convertView.setId(position);
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent menuVideoIntent = new Intent(mContext,
ActivityDetailVideo.class);
mContext.startActivity(menuVideoIntent);
}
});
return convertView;
}

Categories