Okay so I've been able to hightlight an item in a ListView, but it ends up highlighting every fourth item. I'm pretty sure that's because of recycling. Then I had the issue where the highlighted item would go back to normal after I scrolled, and that's also because of recycling. Is there any way to keep it highlighted, or to maybe stop the ListView from recycling?
This is what the code looks like right now...
runTimes.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> list, View v, int pos, long id) {
v.setSelected(true);
}
});
This is the code where the highlighted item goes back to normal after you scroll.
to hilight a row you should not touch the view at all. you should use listviews setItemChecked with a selector as the background of your view.
runTimes.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> list, View v, int pos, long id) {
runTimes.setItemChecked(pos,true);
}
});
you also need to make sure you keep track of the last position you selected so that you can deselect it when you select a new one
If you want to stop ListView from recycling you should think again if you really need a ListView.
To properly accomplish this with a ListView, though, you need to save the highlighted item states inside of your adapter. Then in getView highlight the items based on their position.
There have been A LOT of questions about saving the state of the ListView items, I'm sure you can find some.
I ended up finding another question that helped me figure out how to do it. This is what I did. In the OnClickListener I check to see if something has been pressed before. If it hasn't been pressed before, then I set the views background color, and prevRunView to the view. If something has been pressed before, then I change the previous view background color to white. After that I do the same thing as before, but for the different view.
if(runIndex == -1){
runIndex = pos;
v.setBackgroundColor(Color.parseColor("#A6A6A8"));
prevRunView = v;
}else{
prevRunView.setBackgroundColor(Color.parseColor("#FFFFFF"));
runIndex = pos;
v.setBackgroundColor(Color.parseColor("#A6A6A8"));
prevRunView = v;
}
In my adapter I wrote this code so it won't seem like it's recycling.
if(ScoreActivity.runIndex == position)
v.setBackgroundColor(Color.parseColor("#A6A6A8"));
else
v.setBackgroundColor(Color.parseColor("#FFFFFF"));
Related
I've a recycler view on my app. I'd like to prevent multi selections on my recyclerView, because I'm getting unexpected output while trying to delete items.
holder.mView.setOnClickListener(v -> {
if (null != mListener) {
mListener.onPreviewItemClicked(position);
if (holder.isSelected) {
holder.mView.setBackgroundColor(Color.TRANSPARENT);
Log.d("positionClicked adapter",position+"");
holder.isSelected = false;
isSelected = holder.isSelected;
} else {
holder.mView.setBackgroundColor(ContextCompat.getColor(mContext, (R.color.accent_light)));
holder.isSelected = true;
positionClicked = position;
isSelected = holder.isSelected;
}
}
});
On my code, I use is Selected boolean to catch if something is clicked. When I click on an item, background of its changes. The thing is :
If I click on item1, then on item2, both items have backgrounds changed, and I'd like to have only one. And when I click on item, code below is done. But then, If i click again on item2, it goes transparent, which is good ! But the position of my item selected is wrong ( should be 1, but it's 2 because last item selected was 2). So when I delete, it will delete 2nd item and not first one...
I delete using positionClicked variable.
Any idea on how to fix this ?
You should keep if item is selected in your model, and use it in the onBindViewHolder to setup background for the ViewHolder. In OnClickListener just set true for the specific data item, false for all others and then call notifyDataSetChanged() to rebinf all items.
FIXED: I was incorrectly updating my ListView adapter. see: How to refresh Android listview?
I have been struggling with an incredibly weird bug for too long of a time, and I wonder if any of you have had similar problems.
A detailed explanation of the bug will be less clear than for me to just show you, so I have attached a gif that displays exactly what goes wrong below.
http://giphy.com/gifs/xT9DPGixQnDIEHlVU4
Question 5 is included to show you how things are supposed to wrong. Then, when the CardView and the ListView inside it resize because the amount of options changes at question 6, the following goes wrong:
- The colors of the listview items do not get updated according to their correctness. (should be either green or a light shade of red)
- The checked RadioButton weirdly gets unchecked, right before I click the button.
Note: this bug only appears once upon resizing of the Listview. Everything proceeds to work fine once a similar size optionlist is supplied at the next question
These actions take place upon the second click of the button, which calls the following code
/*
FOR EACH LISTITEM:
> Make button unclickable
> Animate background change according to correctness of answer
*/
for (int i = 0; i < currentQuestion.getOptionList().size(); i++) {
ListView optionList = (ListView) rootView.findViewById(R.id.optionList);
View item = (View) optionList.getChildAt(i);
item.findViewById(R.id.optionRadioButton).setClickable(false);
final LinearLayout llayout = (LinearLayout) item.findViewById(R.id.itemLinearLayout);
int colorTo = getResources().getColor(R.color.lightPrimary);
if (currentQuestion.getOptionList().get(i).equals(currentQuestion.getAnswer())) {
colorTo = getResources().getColor(R.color.correct);
}
int colorFrom = getResources().getColor(R.color.white);
ValueAnimator colorAnimation = backgroundColorAnimator(
colorFrom,
colorTo,
llayout,
i);
colorAnimation.start();
}
// Bottom part of list view is animated SEPERATELY.
// please note that THIS DOES GET UPDATED ACCORDINGLY.
int colorFrom = getResources().getColor(R.color.white);
int colorTo = getResources().getColor(R.color.lightPrimary);
// Also increments question correct counter (important
if (correctAnswerSelected) {
colorTo = getResources().getColor(R.color.correct);
currentExercise.questionCorrectlyAnswered();
}
ValueAnimator anim = backgroundColorAnimator(
colorFrom,
colorTo,
fabContainer,currentQuestion.getOptionList().size()+1);
anim.start();
My hypothesis: Somehow, upon resizing the CardView / RelativeLayout / ListView, the ListView gets reinitiated and I call a different version of it. I suspect this is the cause because the lower part of the CardView (a FAB within a FrameLayout) does change color accordingly.
Any and all help is appreciated, I am at a complete loss with this question
Thanks in advance.
I have a linear layout that I am adding several views to. Think linear layout of result items. It is possible for there to be up to 150 result items. Generating each view takes a bit, so I want them to show up as they become available.
Here is my current code:
for (final Dealership loc: locations) {
final int x = resultNumber;
view.post(new Runnable(){
public void run(){
if(loc != null && parent != null && currentLocation != null) {
View v = getResultView(x, loc, parent, currentLocation);
v.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
if(parentLayout != null) {
parentLayout.addView(v);
}
}
}
});
resultNumber++;
}
This works in that it runs in the background and adds all the items. The only problem is that all the views appear at once, after a few seconds. I would really like it if they appeared as soon as they were created.
Is there a way I can modify this code so that it works as desired? Am I going about this the wrong way?
Thanks!
It seems like instead of a LinearLayout, you'll want to instead go with a ListView.
A ListView would give you a scrolling list of elements that are backed by a Collection of some sort (Array, List, etc.), and you could update that list on the fly. This is helpful for when you are slowly aggregating data from an external resource.
ListView also does some optimizing under-the-hood, and will only render row views when they are shown on the screen. If it is taking some time to render all 150 views in your LinearLayout, a ListView would help you here as well.
Basically, I have a bug where some of my list view's children will appear selected, when in fact they are not. For example, If I enter ActionMode and select the first child only, several other children will appear as though I've selected them, but aren't actually selected. Why is this happening?
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
final int checkedCount = lv.getCheckedItemCount();
mSelectedConvCount.setText(Integer.toString(checkedCount));
if (checked) {
lv.getChildAt(position).setBackgroundColor(
Color.BLUE);
} else {
lv.getChildAt(position).setBackgroundColor(
Color.TRANSPARENT);
}
}
}
Remember: In a ListView, anything you set or change in any child views must be set every time they are displayed; all you are doing in the code provided is setting it initially. This means your adapter must also setBackgroundColor as appropriate, e.g. in bindView(). Otherwise, when the view is recycled it will retain the previous background color and appear selected when it is not.
I have a ListView that shows the closest word matches to a search.
For example if I search "hi" I get the following results in the ListView
...
hi
hi five
hi-five
high
highlight
....
I am using
ListView.setSelection(wordList.indexOf(searchWord));
ListView.setSelected(true);
The above code puts the selected word "hi" at the top and doesnt highlight the selection.
I want the "hi" to be centrally positioned , selected and highlighted automatically.
See below
...
hello
hello there
hi
hi-five
hi five
...
What code can I use to achieve the above?
Many thanks.
ListView view = (ListView)findViewById(R.id.YourListView);
int height = view.getHeight();
int itemHeight = view.getChildAt(0).getHeight();
view.setSelectionFromTop(position, height/2 - itemHeight/2);
The position (int) is the listitem you want to center in the listview!!
try setSelectionFromTop() you'll have to do the math yourself. setSelection() bring the selected item to the top of the view, which is what you are seeing.
try this.
first, get visible item count of listview
int count=0;
for (int i = 0; i <= listview.getLastVisiblePosition(); i++)
{
if (listview.getChildAt(i)!= null)
{
count++;
}
}
second, scroll the item to the center of listview.
int target = position-count/2;
if (target<0) target = 0;
listview.setSelection(target);
Try this:
ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
Toast.LENGTH_SHORT).show();
}
});
for more information :
http://developer.android.com/resources/tutorials/views/hello-listview.html