I have a RecyclerView, it will show close icon in the last item view,
but when I add new data in the Adapter,
the old item does not refresh their view, it just adds new item view in the RecyclerView.
How could I update the old last item view?
I tried to use notifyItemChanged(int) but it didn't work.
for(int i = lastPosition(); i < mAdapter.getItemCount() - 1; i++) {
mAdapter.notifyItemChanged(i);
}
Add below code after adding item in listview...
mAdapter.notifyDataSetChanged();
you can call this whenever you want to update the item of recyclerview list
mAdapter.notifyItemChanged(ITEM_INDEX);
//ITEM_INDEX IS THE POSITION
Thanks for your help, I have find the problem
the problem is not in adapter, it in my viewholder
my xml layout show the icon in default,
when it is the last item ,I set the icon Gone
public static void hideBottomLine(BaseViewHolder h) {
h.line.setVisibility(View.GONE);
}
when i notifyItemChanged it ,I thought it will show default, but not! So when I add method
public static void showLine(BaseViewHolder h) {
h.line.setVisibility(View.VISIBLE);
}
now it work...
Related
I have a requirement, where I should download the ad item while scrolling and update the list. Since calling notifyDatasetChnaged(), resets everything, I'm calling notifyItemInserted(position). But, calling this duplicated the items in the list. I found that there are no repeated items in the list. But after calling notifyItemInserted, it duplicates the item. I'm not getting how to resolve this issue. This what I'm doing:
mNewsList.add(mPreviousAdPosition, newsItem);
mAdapter.notifyItemInserted(mPreviousAdPosition);
If I call, it works properly, there are no repeated items. But I don't want my list items to recreate. What can be the issue ?
I had the same problem for exactly the same use case, the solution is:
Implement this method in your Adapter :
#Override
public long getItemId(int position) {
//Return the stable ID for the item at position
return items.get(position).getId();
}
Call this method in the Constructor of your Adapter :
//Indicates whether each item in the data set can be represented with a unique identifier
setHasStableIds(true);
You can add the object at the end of the array with each object having a position along with it where it needs to be shown in the recycler view. Sort this array on the basis of position before calling notifyItemInserted(position). In this way only required data will be drawn.I have recenlty followed this approach and works very well with dynamic sections added in between in recycler view.
You should add the item at the end of the list.
mNewsList.add(newsItem);
and then notify like this.
mAdapter.notifyItemInserted(mNewsList.size()-1);
Create a temporary list and add items as mentioned below:
List<YourModel> mTmpList = new ArrayList<YourMdel>();
//add items (from 0 -> mPreviousAdPosition) to mTmpList;
for(int i=0; i<mPreviousAdPosition; i++) {
mTmpList.add(mNewsList.get(i));
}
//add item at mPreviousAdPosition
mTmpList.add(newsItem);
//add remaining items and set i<=mNewsList.size() because we ha
for(int i=mPreviousAdPosition; i<=mNewsList.size(); i++) {
mTmpList.add(mNewsList.get(i - 1)); //because we have added item at mPreviousAdPosition;
}
mNewsList = mTmpList;
mAdapter.notifyDataSetChanged();
You code should be written like this:
public class RecyclerViewAdapter extends RecyclerView.Adapter{
...
public void addData(int position, Item newsItem) {
mNewsList.add(position, newsItem);
notifyItemInserted(position);
}
...
}
and then you need to call the fun addData
I'm faced with strange problem. I've made a ListView, populated it with adapter and everything works fine until I want to delete any item. After I press confirmation button view really deletes, but text inside of it doesn't changes on the text from next view.
For example I've got such items in ListView:
Item 1
Item 2
Item 3
When I press delete Item 2, Item 3 disappears but text in view on position 2 doesn't changes. I know that Item 2 was deleted as I use database for storing data and after app restart everything show as expected. I suppose that problem is in reuse of views by View Holder but I can't figure out how to change text in second view.
Here is code that doesn't work (at least I think that problem is here)
confirmDeleteButton.setOnClickListener(new View.OnClickListener() {//this button is in dialog
#Override
public void onClick(View v) {
DBController.init(context).delete("main", "id=" + item.get(position).getId(), null);//deleting item from database
remove(getItem(position)); //removing view from adapter
notifyDataSetChanged(); //notifying adapter
dialog.dismiss(); //closing dialog
}
});
SOLUTION
Just use RecyclerView instead of ListView.
First you have to remove the data from adapter like adapter.remove(adapter.getItem(position));
and then call notifyDataSetChanged()
don't use the get position to delete the datas, first setid() to confirm buttons like, confirmDeleteButton.setid(position) used in getview adapter class.
then remove the id based on getid() like:
DBController.init(context).delete("main", "id=" + item.get(v.getid()).getId(), null);//deleting item from database
remove(v.getid()); //removing view from adapter
Is better if you use:
adapter.notifyItemRangeRemoved(int positionStart, int itemCount)
adapter.notifyItemRemoved(int position)
More info: https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html
I have a horizontal Recyclerview which displays bitmaps.
The Way it is implemented is I have a Imageview and a recyclerview underneath it. The currently selected item is displayed on the image view. The selected image view is given a blue background to indicate it is selected. I can choose images from the gallery and each time a new image is selected, I want to scroll to the last position and make the item selected.
The list of images is maintained in a array list and each time a new image is added, I add the image to the list and notifyDataChanged().
Currently when I am binding a view, I toggle the visibility of the blue background in
public void onBindViewHolder(final MyRecyclerViewHolder holder, int position) {
}
But the problem is, if the child is off screen, the bind view is not called and I dont scroll to the new position.
I read through the documentation of recycler view and could not figure out how to scroll to that particular child view. I do not there is a SmoothScrollTo method but my question is where do I trigger this ?
There is one solution:
In your RecyclerView adapter, add a variable selectedItem and a methods setSelectedItem():
private static int selectedItem = -1;
... ...
public void setSelectedItem(int position)
{
selectedItem = position;
}
In your onBindViewHolder(...), add:
#Override
public void onBindViewHolder(ViewHolder holder, final int position)
{
... ...
if(selectedItem == position)
holder.itemView.setSelected(true);
}
Now you can scroll to specific item and set it selected programmatically by:
myRecyclerViewAdapter.setSelectedItem(position_scrollTo);
myRecyclerView.scrollToPosition(position_scrollTo);
For example, you want to scroll to last position and make it selected, just:
int last_pos = myRecyclerViewAdapter.getItemCount() - 1;
myRecyclerViewAdapter.setSelectedItem(last_pos);
myRecyclerView.scrollToPosition(last_pos);
[UPDATE]
To add item and make it selected, you should have a addItem(...) method in adapter, which will add item to item list. After adding item, refresh list and scroll to new added/latest item:
myRecyclerViewAdapter.addItem(...);
myRecyclerViewAdapter.notifyDataSetChanged();
myRecyclerViewAdapter.setSelectedItem(myRecyclerViewAdapter.getItemCount() - 1);
myRecyclerView.scrollToPosition(myRecyclerViewAdapter.getItemCount() - 1);
Hope this help!
Your view will not be created until you scroll to the item.
You must call
recyclerView.scrollToPosition(position)
Where position is
recyclerView.getAdapter().size()
So the item became visible.
Use RecyclerView LayoutManager to scroll item at position
recyclerView.getLayoutManager().scrollToPosition(position)
I forgot to address the timing part ideally this should be called when the adapter has been identified of the dataset change.
You could use
recyclerView.smoothScrollToPosition(View.FOCUS_DOWN);
I have a list view with multiple items, where i need to select and deselect the list items, and also delete the selected items.
So i have looked into the example in the below link but its for android:minSdkVersion="11"
but i am working on minSdkVersion="10".
Link : http://www.androidbegin.com/tutorial/android-delete-multiple-selected-items-listview-tutorial/
And yes we can do with checked text view, check box and radio button, but the requirement is like that i cannot use that.
Is there any other way that we can acheive this?
Make custom list adapter and get the click of that each view and maintain flag in adapter. If flag is true that means item selected otherwise item deselected, according to that you can change item view like disable that particular item or show some check box.
What I did was created an ArrayList that stores all the position of selected items, and toggle the background colors on clicks.
In my Adapter I define:
public ArrayList<Integer> selectedIds = new ArrayList<Integer>();
With the following method :
public void toggleSelected(Integer position)
{
if(selectedIds.contains(position))
{
selectedIds.remove(position);
}
else
{
selectedIds.add(position);
}
}
which addes\removes items from the ArrayList
In my getView method :
if (selectedIds.contains(position)) {
convertView.setSelected(true);
convertView.setPressed(true);
convertView.setBackgroundColor(Color.parseColor("#FF9912"));
}
else
{
convertView.setSelected(false);
convertView.setPressed(false);
convertView.setBackgroundColor(Color.parseColor("#000000"));
}
This checks if the position is storred in the ArrayList. if it does, paint it as selected. if not, the opposite.
all is left is the OnItemClick listener, i added :
((YourAdapter)list.getAdapter()).toggleSelected(new Integer(position));
When YourAdapter is the adapter of your ListView
Hope this helps anyone, as it's a generic answer :)
Thanks to eric.itzhak here : How to change background color of selected items in ListView?
I have a ListView with 10 items in it, when i set the 4th item in the ListView as selected then my ListView gets scrolled and 4th item in the ListView gets placed at the top of the screen.
I don't want to scroll the ListView when i call setSelected() for the list item which is not in the view.
I have also tried to scroll the ListView programmatically using scrollTo(0, 0); but it is not working.
An old question, but it may be useful to somebody. You can use setSelectionFromTop. It's rather smart, and you can use it for example like that:
getListView().setSelectionFromTop(selection, getListView().getHeight() / 2);
It begins to scroll only after middle of the list:
Here's what I did:
int top = listView.getChildAt(fixedChildIndex).getTop();
//set selected item, keep scroll position
listView.setSelectionFromTop(newIndex, top);
This keeps the ListViews Child with view index (ListView reuses views!) fixedChildIndex in place.
For example if you want the highlighting to stay use this:
int first = listView.getFirstVisiblePosition();
int fixedChildIndex = listView.getSelectedItemPosition() - first;
View newSelectedChild = listView.getChildAt(selectedViewIndex);
If you want to make sure the selected item is fully visible use this line
//set selected item, keep scroll position and make sure it is completely visible
listView.setSelectionFromTop(newIndex, Math.min(Math.max(0,top), listView.getHeight()-newSelectedChild.getHeight()));
Where newSelectedChild is the view of the child you want to select. You can get it by doing this:
I think it's hardcoded and thus not possible without scrolling
you can use listview.setChoiceMode(ListView.CHOICE_MODE_SINGLE); option with
mListView.setItemChecked(pos, true);
Setup some selectors may be required. Also look for google example IOSchedule App --great example about listview with multi selection controller (have a few bugs :) )
setSelection() may be of your work.
Do NOT use setSelection()!
I do that in another way.
private AdapterView.OnItemClickListener oiclFolders = new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int posi, long id) {
// clear original selected item
if ( mViewOrg!=null ) mViewOrg.setBackgroundDrawable(null);
if ( view!=null ) {
// define your own drawable to set as background
view.setBackgroundResource(R.drawable.item_bg);
mViewOrg = view;
}
curSel = posi; // to store which one is selected
// Do NOT setSelection -> will auto scroll to top
// mlvFolders.setSelection(posi);
}
};
This worked for me -
Set CHOICE_MODE_SINGLE when setting up the custom listview -
Use setSelected() inside OnItemClickListener() as under -
private void setup_view(View rootView) {
listview = (ListView) rootView.findViewById(R.id.list);
if(listview != null) {
listview.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
listview.setAdapter(new MyAdapter(getActivity().getApplicationContext()));
listview.setOnItemClickListener(onitemclicklistener);
}
}
private OnItemClickListener onitemclicklistener = new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position,
long id) {
v.setSelected(true);
}
};
You can override requestChildRectangleOnScreen like this to get rid of the scrolling:
#Override
public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
return false;
}
Use setSelection(4) to set the Selection without scrolling if the new selection is visible.