NullPointerException when clicking ListView item - java

I have a ListView with set onItemClickListener:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// not important
if (!found) {
activity.addSelectedIngredient(ingred);
parent.getChildAt(position).setBackgroundColor(Color.parseColor("#ff99FE80"));
} else {
activity.removeSelectedIngredient(ingred);
parent.getChildAt(position).setBackgroundColor(Color.WHITE);
}
}
The NullPointerException is thrown when parent hasn't got child on selected position (e.g. 15). Why? How it's possible that the element might not be present if she already selected it?
Edit:
if (!found) {
activity.addSelectedIngredient(ingred);
view.setBackgroundColor(Color.parseColor("#ff99FE80"));
} else {
activity.removeSelectedIngredient(ingred);
view.setBackgroundColor(Color.WHITE);
}

getChildAt returns listView's child. getChildAt position is not same position as in your adapter. You can have 1000 items in your adapter and only several childViews in listview because views are reusing.
I think you should change
parent.getChildAt(position).setBackgroundColor(Color.WHITE);
to
view.setBackgroundColor(Color.WHITE);

Try,
if (!found) {
activity.addSelectedIngredient(ingred);
view.setBackgroundColor(Color.parseColor("#ff99FE80"));
} else {
activity.removeSelectedIngredient(ingred);
view.setBackgroundColor(Color.WHITE);
}
Explanation:
so what is happening is that the parent has that view but the indexing is reset. So you clearly don't has any idea as which index is assigned to your element, It depends on the cash the listview has cashed elements for. So instead of getting child you should use the view. This is exactly the same as the item you just clicked.

Related

ListView updating more than one row when clicking on one item

I have a ListView where I store a list of order.
When clicking an item, it should expand to let the user see the detail.
The problem is that the item is actually expanding, but so is another item randomly in the list.
If I scroll the list while one item is open, the first item collapse and another take his place. The second expanded item is NEVER in sight, I have to scroll to see it.
I don't understand anything to this bug, can you help me?
Here is the listener that interract with the listview
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
View v = CommandesSalarieActivity.this.list.getChildAt(position);
LinearLayout ll = view.findViewById(R.id.commande_salarie_list_item_layout_main_layout);
ImageView iv = view.findViewById(R.id.commande_salarie_list_item_layout_dropdown);
if (ll.getVisibility() == View.VISIBLE) {
ll.setVisibility(View.GONE);
iv.setImageResource(R.drawable.ic_dropdown_ressource);
} else {
ll.setVisibility(View.VISIBLE);
iv.setImageResource(R.drawable.ic_dropup_ressource);
}
}

Scroll Android ListView to top without scroll animation [duplicate]

I have a ListActivity that implements onListItemClick() and calls a doSomething() function of the class. The latter contains l.setSelection(position) where l is the ListView object.
Now there is a onClickListener() listening for a button click that perfoms some actions and that too calls doSomething().
In the first case, the selected item get positioned appropriately, but in the latter, nothing happens.
Any clues about this strange behaviour and how I might make it work?
maybe you need to use function:
ListView.setItemChecked(int position, boolean checked);
use requestFocusFromTouch() before calling setSelection() method
I know this is an old question but I just had a similar problem that I solved in this way:
mListView.clearFocus();
mListView.post(new Runnable() {
#Override
public void run() {
mListView.setSelection(index);
}
});
You might need to wrap setSelection() in a posted Runnable (reference).
setSelection() does not necessarily have visual impact. The selection bar only appears if you use the D-pad/trackball to navigate the list. If you tap on the screen to click something, the selection bar appears briefly and vanishes.
Hence, setSelection() will only have a visual impact if the activity is not in touch mode (i.e., the last thing the user did was use the D-pad/trackball).
I am not 100% certain this explains your phenomenon given the description you provided, but I figured it is worth a shot...
If you use an Adapter for your ListView add this code to your adapter:
public class MyAdapter extends
ArrayAdapter<MyClass> {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflator = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflator.inflate(R.layout.my_adapter, null);
} else {
rowView = (View) convertView;
}
//...
// set selected item
LinearLayout ActiveItem = (LinearLayout) rowView;
if (position == selectedItem)
{
ActiveItem
.setBackgroundResource(R.drawable.background_dark_blue);
// for focus on it
int top = (ActiveItem == null) ? 0 : ActiveItem.getTop();
((ListView) parent).setSelectionFromTop(position, top);
}
else
{
ActiveItem
.setBackgroundResource(R.drawable.border02);
}
}
private int selectedItem;
public void setSelectedItem(int position) {
selectedItem = position;
}
}
In your Activity:
myAdapter.setSelectedItem(1);
For me calling
listView.notifyDataSetChanged();
listView.requestFocusFromTouch();
and then
listView.setSelection(position);
solved the issue.
if you do that in a runnable it works without calling requestFocusFromTouch(), but the old position of the ListView is showen for a sekound.
I have an very large Request with Webcontent. When I used the code in onCreateView the Listview wasnt even finished loading.
I put it in onPostExecute of my AsyncTask.
//Get last position in listview
if (listView != null && scrollPosition != 0) {
listView.clearFocus();
listView.requestFocusFromTouch();
listView.post(new Runnable() {
#Override
public void run() {
listView.setItemChecked(scrollPosition, true);
listView.setSelection(scrollPosition);
}
});
}
Dont forget to set the item checked in on Click ;)
Maybe you should use the smoothScrollToPosition(int position) method of ListView
You can try 2 ways like these:
Solution A:
mListView.post(new Runnable() {
#Override
public void run() {
if (null != mListView) {
mListView.clearFocus();
mListView.requestFocusFromTouch();
mListView.setSelection(0);
}
}
});
In some complicated situation, this solution will bring some new problems in Android 8.x. Besides it may cause unexpected onFocusChange().
Solution B:
Define a custom view extends ListView. Override method handleDataChanged().Then setSelection(0). In CustomListView:
#Override
protected void handleDataChanged() {
super.handleDataChanged();
if (null != mHandleDataChangedListener){
mHandleDataChangedListener.onChanged();
}
}
HandleDataChangedListener mHandleDataChangedListener;
public void setHandleDataChangedListener(HandleDataChangedListener handleDataChangedListener) {
this.mHandleDataChangedListener = handleDataChangedListener;
}
public interface HandleDataChangedListener{
void onChanged();
}
In activity:
mListView.setHandleDataChangedListener(new CustomListView.HandleDataChangedListener() {
#Override
public void onChanged() {
mListView.setHandleDataChangedListener(null);
mListView.setSelection(0);
}
});
mAdapter.notifyDataSetChanged();
Ok, That's it.
In my case smoothScrollToPosition(int position) worked, can you also tell me how to set that scrolled position into center of the list. It appeared at the bottom of visible items.
For me it helped to set
ListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); or ListView.CHOICE_MODE_MULTIPLE
then
ListView.setSelection(position) or ListView.setItemChecked(position, true);
works fine
Found a solution in my case. I am not using a Runnable since my class is extending ListFragment. What I had to do is make my index a final;
final index = 5;
mListView.setSelection(index);
I found that sometimes setSelection will not work because I set attribute "android:height" of listView to "wrap_content".
And the times my App won't work is that when listView become scrollable from non-scrollable.
For example, if my app is "File Browser App". When my list is less than, let's say 6, then it's non-scrollable. Now I return to the parent directory, and it has 11 objects, and I want to set selection to some position, and it won't work here.
to\from | Scrollable | non-Scrollable
Scrollable | O | O( of course )
non-Scrollable | X | O( of course )
I don't want to use post(Runnable), because there will has delay.
==================================
Answer:
You can try to set "android:height" to "match_parent"
God, it spends three days.
When use post to setSelection(), the ListView will see first , then scroll to the position , thank to "魏經軒", then layout actually will effect the setSelection(), because setSelection() call the setSelectionFromTop(int position, int y), there is another way to solve it.
listView.setAdapter(listView.getAdapter());
listView.setSelection(123);
For me the solution to this problem was:
listView.clearChoices();
Simply try this code
listView.setAdapter(adapter);
listView.setSelection(position);
adapter.notifyDataSetChanged();

deleted Item place in ArrayAdapter in my ListView left empty

I used animated for deleting Item in ArrayAdapter in my ListView.
but when i deleted one row, It's place remained empty and lower box was not coverd empty place.
what can i do The lower box to come up and The stick-top box?
what can I do?
listViewHome.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(final AdapterView<?> parent, View view, final int position, long id) {
Log.i("######", "setOnItemClickListener: " + position);
view.animate().alpha(0f).setDuration(1000).setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
Log.i("######", "onAnimationEnd: " + position);
contacts.remove(position);
adapter.notifyDataSetChanged();
super.onAnimationEnd(animation);
}
});
}
});
If I don't use animate everything is ok but when I use animate for deleting Its place Item remained empty and lower box was not coverd empty place.
Seems to be ok. Another way you can try (which is actually equal with your way) is:
adapter.remove(yourArraylist.get(position));
adapter.notifyDataSetChanged();
If it still not working try this:
Object toRemove = adapter.getItem([position]);
adapter.remove(toRemove);
This might help Delete Items android ListView Tutorials

Check unique list identifier from item on click

guys what's up?
I'm still new to android and creating some testing app.
I have two Lists in my view. (Left and Right).
List Filled with values.
I trying to add selected list item value to other lists.
For example, If I clicked on an item in a left list. I wanna add selected item to Right list,
implemented OnItemClickListener into my code and OnItemClickListener onItemClick method is firing for both lists.
Any way to identify clicked list in an onItemClick method?
any suggestions are greatly appreciated.
After reading official API. Found a solution.
We can get the ID on the selected list.
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
if(adapterView.getId() == R.id.leftList){
// It's a left list
}else{
// It's a Right list
}
}
I'm not sure if I understand your question, but if you are trying to identify which list was clicked, you can call getId on the view in onItemCLick:
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
switch (parent.getId()){
case R.id.left_list:
...
break;
case R.id.right_list:
...
break;
}
}

recyclerview.adapter resets radio-buttons

This is my problem:
https://youtu.be/k-N5uthYhYw
and this is my onBindViewHolder() method.
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.specName.setText(specList.get(position).getSpecName());
// Assign a tag number to later identify what radio-button
holder.specRadioBtn.setTag(new Integer(position));
/* Event listenr for longClick - we prob. won't use it, but it's here just in case */
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Toast.makeText(context, "Long press", Toast.LENGTH_SHORT).show();
return false;
}
});
/* Little hack to select its Radio Button when a specific row is tapped */
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Turn rowSelectedFlag to true since the user selected this row
rowSelectedFlag = true;
// When the user taps on a row select that row's radio button
holder.specRadioBtn.setChecked(true);
// I'm not sure why, but locally the interface needs to be started by pointing it
// to where it should drive the data (to send the params)
tempInterface = new AdminUserSpecialty();
// Call the interface to send the data (row spec-name and id) back to AdminUserSpecialty
tempInterface.activateSpecSelect(specList.get(position).getSpecName().toString(),
specList.get(position).getSpecId().toString(), rowSelectedFlag);
int clickedPos = ((Integer) holder.specRadioBtn.getTag());
// Check if the radio button is already selected
if (holder.specRadioBtn.isChecked()) {
if (lastCheckedBtn != null) {
// Don't deselect if user taps on the same row several times
if (lastCheckedBtn == holder.specRadioBtn) {
// do nothing
}
// Otherwise do deselect the previously selected radio button
else {
lastCheckedBtn.setChecked(false);
}
}
lastCheckedBtn = holder.specRadioBtn;
lastCheckedPos = clickedPos;
}
// If radio is not checked set the lastCheckedBtn to null (reset counter)
else {
lastCheckedBtn = null;
}
}
});
/* ----------------------------------------------------------------------*/
}
I can't seem to preserve my radio-button selection on RecyclerView scroll. On scroll the selection becomes erratic and random. I understand that one of RecyclerView's features is to recycle rows as they leave the screen, but what do I need to do to keep my selection? Thanks much.
I know that this was answered already but if some of you are still looking for an easier answer and your application does not rely on the RecyclerView view recycling feature much (for example if you have a fixed size list of items...) you can always set your recycler view cache view size. That way it would not recycler your views hence it would not recycler the views and you will avoid copy selected values to another views...
yourRecyclerView..setItemViewCacheSize(yourItemList.size());
Save the checked / unchecked status of the radio button (you should use checkbox instead if you want to allow the user to select multiple items) to your model (i.e. your items in the list should have a field for this) when the onClick event happens. When you bind the ViewHolder, make sure you set checkbox's value to whatever you saved in your model.
It's happen because of the Recycling mechanism
(PS: its the same for the ListView or RecyclerView).
To fix that:
1) Add a booelan variable to your model to save the state of the RadioButton
2) Update your RadioButton state in onBindViewHolder() method from this boolean in the model.
3) Add setOnCheckedChangeListener() to your RadioButton to listen to his state (checked/unchecked) and to update the boolean in your model when the state changes.

Categories

Resources