I have a custom ListView. It's populated by cursor adapter. It's every row includes one ImageView, two TextViews and one ToggleButton. These all loads fine. When I change state of group of ToggleButtons to true, then when I scroll fast listView not scrolling smoothly it hangs for a sec and scrolls. It happens when after group of unchecked buttons appears group of checked buttons and vice versa. Why list view hangs while scrolling?
Any help would be appreciated. My code looks like this:
public void bindView(View view, Context context, final Cursor cursor) {
final ViewHolder viewHolder = new ViewHolder(view);
(...)
if (viewHolder.toggle_artist != null) {
viewHolder.toggle_artist.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int favourite = isChecked ? 1 : 0;
ContentValues value = new ContentValues();
String where = AmdmContract.ArtistEntry.TABLE_NAME + "." +
AmdmContract.ArtistEntry._ID + " = " + tableId;
value.put(AmdmContract.ArtistEntry.COLUMN_FAVORITE, favourite);
mContext.getContentResolver()
.update(AmdmContract.ArtistEntry.CONTENT_URI,
value, where, null);
}
});
int favFromDB = cursor.getInt(COL_FAVOURITE);
viewHolder.toggle_artist.setChecked(favFromDB == 1);
}
}
Can you please try below code for Toggle Button CheckChangeListener.
Reason: In BaseAdapter getView() method calls on every scroll of ListView and it will calls onCheckChangeListener() automatically.
So replace your code with below code:
tgl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ToggleButton selectedToggle = (ToggleButton) v;
if(selectedToggle.isChecked()){
// Code if toggle is checked
}else{
// Code if toggle is not checked
}
}
});
Hope it will help you.
It is a common problem when you show checkboxex or toggle button in listview items. Once you checked few checkboxes and then scroll down the listview, after scrolling up again it all gets mixed up.
It is advised to use maintain a boolean array which can track the checkbox status.
Check this already answered post - Custom listview with checkbox problem
Related
I have created a horizontal recyclerview list. below is the image I have attached.
problem is that I have to change bulb state when everytime user clicked that row from off state to on state and on state to off state.
How do I implement this logic? please help me to find out the solution.
i want to change light color according to user clicks, if he clicks on then it should change its color for that row and vise versa
public void onClick(View view, int position) {
//toast("clicked" + position );
if (!lightClicked){
ImageView lightPopUp = view.findViewById(R.id.row_light_thumbnail);
DrawableCompat.setTint(lightPopUp.getDrawable().mutate(), ContextCompat.getColor(getContext(), R.color.white));
//toast("light on");
lightClicked = true;
}else {
ImageView lightPopUp = view.findViewById(R.id.row_light_thumbnail);
//toast("light off");
DrawableCompat.setTint(lightPopUp.getDrawable().mutate(), ContextCompat.getColor(getContext(), R.color.colorAccent));
lightClicked = false;
}
//View view1 = mLayoutManager.findViewByPosition(position);
}
Dont directly do this change as the recycler view's cells are reused and it wont work as expected, so instead apply the change in the list you are using. You can add a boolean variable in the model class of the list you use to populate the recycler view, and than on its click you can change the boolean's value and call notifydatasetchange on the adapter, and in bind view you should keep an If else condition based on that boolean for the Bulb's image
ie. if true set one image if false set another
declare this :
int selectedPosition=-1;
inside onBindViewHolder:
public void onBindViewHolder(FiltersAdapter.ViewHolder holder, int position) {
if(selectedPosition==position)
holder.itemView.setImageResource(R.drawable.higlihgt_image);
else
holder.itemView.setImageResource(R.drawable.normal_image);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selectedPosition=position;
notifyDataSetChanged();
}
});
}
I have a listview and in each cell it has a RelativeLayout with 7 buttons.
before the list is scrolled all the buttons work fine (all trigger when clicked) for all visible listView items, but after listView was scrolled some items turn to not clickable (no matter which button in the item I click), and it's random, after another scroll the same item can turn clickable, and other which was before turns to not clickable.
I have noticed that it usually happens (item turns not clickable) after scrolling all the way up.
Another thing that i have noticed that seldom (after 4-5 unsuccessful clicks in a row) the button triggers a few times in a row (like it was delayed). But usually it's not happening after a number of unsuccessful clicks.
In my original code I created an arrayList of RelativeLayouts (each for listView Item), and put the arrayList into adapter. For every 7 buttons (for each cell) I set 7 ids corresponding to their's place in arraylist.
In that way I implemented the OnClick event in the main class.
Here is 3 buttons (out of 7):
for (int i = 0; i < EXPEND_BUTTONS.length; i++) {
if (view.getId() == EXPEND_BUTTONS[i]) {
handleEmojiPanel(i);
break;
}
if (view.getId() == BUTTONS[i] || view.getId() == IMAGES[i]) {
ShowTopItem item = new ShowTopItem(getActivity(), i);
item.show();
break;
}
}
Because of the problem I change the code.
I handled the OnClick event for the buttons in the adapter itself in the getView method (for 2 buttons only):
public View getView(final int position, View convertView, ViewGroup parent) {
pos = position;
Button btn = (Button) listOfObjects.get(position).getChildAt(0);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ShowTopItem item = new ShowTopItem(getActivity(), position + listChosen);
item.show();
}
});
Button imageBtn = (Button) listOfObjects.get(position).getChildAt(2);
imageBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ShowTopItem item = new ShowTopItem(getActivity(), position + listChosen);
item.show();
}
});
return listOfObjects.get(position);
}
I have the same result. Nothing changed.
I have looked all over the internet, and it seems that I'm the only one who encountered such issue.
Id anybody knows what can be the issue here?
If some other code is needed, please feel free to ask.
I did not find the reason, but I changed ListView to ScrollView, and all works fine now.
Maybe there is some kind of bug in ListView, but in this case, I wonder why I did not find any complains regarding it.
Anyway, works perfect with ScrollView.
I have a DialogFragment which I am populating with a ListView and a Cursor Adaptor. I was having issue with selecting a radio button and deselecting others. So I did this thing which works. But I wanted to know if I really need a loop there or there is another better way to do it. Here is my code:
viewHolder.radioButton.setOnClickListener(
new View.OnClickListener()
{ #Override
public void onClick(View v) {
for (int i = 0; i < selectionArrayAr.size(); i++){
selectionArrayAr.put(i, false);
}
selectionArrayAr.put(position, true);
notifyDataSetChanged();
}
}
);
I am setting all values to false in the Sparse Array and then finally setting the clicked radio button to true.
i have the following problem. i have set three checkboxes in my app in a way so when i check one of them the other two get disabled. the problem is that when i scroll up or down namely when the views get recycled some of the disabled checkboxes get enabled which of course i dont want to happen. could you please help me to solve that problem?
the code in the adapter is this :
#NonNull
#Override
public View getView(final int position1, View convertView1, ViewGroup parent1) {
View listItemView1 = convertView1;
if (listItemView1 == null) {
listItemView1 = LayoutInflater.from(getContext()).inflate(R.layout.list_item1, parent1, false);
}
final ColorQuiz currentColorQuiz = getItem(position1);
TextView questionTextView = (TextView) listItemView1.findViewById(question_text_view);
questionTextView.setText(currentColorQuiz.getQuestionHeader());
final CheckBox box1 = (CheckBox) listItemView1.findViewById(R.id.check_Box_view1);
box1.setText(currentColorQuiz.getCheckBoxTextA());
final CheckBox box2 = (CheckBox) listItemView1.findViewById(R.id.check_Box_view2);
box2.setText(currentColorQuiz.getCheckBoxTextB());
final CheckBox box3 = (CheckBox) listItemView1.findViewById(R.id.check_Box_view3);
box3.setText(currentColorQuiz.getCheckBoxTextC());
box1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (box1.isChecked() ) {
thesisA[position1]=true;
box2.setEnabled(false);
box3.setEnabled(false);
} else {
thesisA[position1]=false;
box2.setEnabled(true);
box3.setEnabled(true);
}
int getPositionA = (Integer) compoundButton.getTag(); // Here we get the position that we have set for the checkbox using setTag.
colorQuizs.get(getPositionA).setSelectedA(compoundButton.isChecked());
}
});
box1.setTag(position1);
box1.setChecked(colorQuizs.get(position1).isSelectedA());
.
.
.
and continues the same way with the next two checkboxes (box2, box3).
maybe while you calling box1.setChecked then one of the old listeners is called and it is causing problems (as it still has old tag, and propably setting wrong data to your model ).
Try to add at the beggining to make sure that something wrong does not happen:
box1.setOnCheckedChangeListener(null);
box2.setOnCheckedChangeListener(null);
box3.setOnCheckedChangeListener(null);
This will tell you if not calling callback while property does not change is reason of this problem:
box1.setChecked(!colorQuizs.get(position1).isSelectedA());
box1.setChecked(colorQuizs.get(position1).isSelectedA());
So I have a listview that is built to have each view in the list to have 2 radio buttons. The problem is when the list gets longer than the page the list starts to recycle the views and it also takes along the checked radio buttons. I understand what is causing the problem but I don't really know how to solve this issue and the answers I've looked up online aren't really helping. My problem is a bit unique because I'm using Parse with my adapter so looking up solutions specifically for parse is pretty hard.
Here is my code for my adapter:
// Set up a customized query
ParseQueryAdapter.QueryFactory<AnywallPost> factory =
new ParseQueryAdapter.QueryFactory<AnywallPost>() {
public ParseQuery<AnywallPost> create() {
Location myLoc = (currentLocation == null) ? lastLocation : currentLocation;
ParseQuery<AnywallPost> query = AnywallPost.getQuery();
query.include("user");
query.orderByDescending("PostScore");
query.whereWithinKilometers("location", geoPointFromLocation(myLoc), radius
* METERS_PER_FEET / METERS_PER_KILOMETER);
query.setLimit(MAX_POST_SEARCH_RESULTS);
return query;
}
};
// Set up the query adapter
postsQueryAdapter = new ParseQueryAdapter<AnywallPost>(this, factory) {
#Override
public View getItemView(AnywallPost post, View view, ViewGroup parent) {
if (view == null) {
view = View.inflate(getContext(), R.layout.anywall_post_item, null);
}
//TextView DetailsView = (TextView) view.findViewById(R.id.content_view);
TextView contentView = (TextView) view.findViewById(R.id.content_view);
TextView usernameView = (TextView) view.findViewById(R.id.username_view);
TextView postscoreView = (TextView) view.findViewById(R.id.PostScore);
RadioButton upvote = (RadioButton) view.findViewById(R.id.Upvote);
RadioButton downvote = (RadioButton) view.findViewById(R.id.DownVote);
//DetailsView.setText(post.getDetails());
contentView.setText(post.getText());
usernameView.setText(post.getUser().getUsername());
postscoreView.setText(post.getInt().toString());
upvote.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
post.increment("PostScore", 1);
post.saveInBackground();
}
});
downvote.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//post.decrement();
}
});
return view;
}
};
postsQueryAdapter.setAutoload(false);
postsQueryAdapter.setPaginationEnabled(false);
// Attach the query adapter to the view
ListView postsListView = (ListView) findViewById(R.id.posts_listview);
postsListView.setAdapter(postsQueryAdapter);
So I need these two radio buttons to stay with the post made the entire time but I am still a beginner so I'm not entirely sure how I would go about that. Could anyone provide a solution and explain how it worked? If you need anymore code just let me know. Thank you for you time.
Essentially when you get a new cell, be sure to clear both the radio buttons, then re-check them only if it meets your condition for it to be checked (likely checking the count on the post object). Hard to tell exactly how this will look without knowing more about how you are storing data, but I'd guess something like this:
upvote.setChecked(post.getInt() > 0);
downvote.setChecked(post.getInt() < 0);
Along with the list items I'd carry a list with the state of radio buttons.
So even when the views get recycled you use your own state to check the correct radio button.
A good choice would be a list of Boolean (the boolean wrapper). Where you could keep true for upvote, false for downvote and null for neither.