Saturday 20 January 2018

android - Items not removed properly from RecyclerView

itemprop="text">

I'm populating RecyclerView with
AppWidgetHostViews. They are sorted one below the other and each one of them has delete
button next to it. This is how I'm setting the RecyclerView and Adapter (event.object is
a AppWidgetHostView):



 private
List viewList = new ArrayList<>();

mAdapter =
new AppWidgetAdapter(this);

mRecycler.setLayoutManager(new
LinearLayoutManager(getActivity()));
mRecycler.setItemAnimator(new
DefaultItemAnimator());
mRecycler.setAdapter(mAdapter);

viewList.add((View) event.eventObject);

mAdapter.setData(viewList);


This
is my Adapter that holds
AppWidgetHostViews:



public class
AppWidgetAdapter extends RecyclerView.Adapter
{


private List viewList = new
ArrayList<>();
private AdapterListener
listener;

public AppWidgetAdapter(AdapterListener listener)
{
this.listener = listener;
}

public void
setData(List list) {
viewList.clear();


viewList.addAll(list);

notifyDataSetChanged();
}

@Override
public
AppWidgetHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.app_widget_layout,
parent, false);
return new
AppWidgetHolder(view);
}


@Override
public
void onBindViewHolder(final AppWidgetHolder holder, int position) {
final
View view = getItem(position);
holder.setView(view);

holder.setNum(String.valueOf(position));


holder.button.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
int pos =
holder.getAdapterPosition();

viewList.remove(pos);

notifyItemRemoved(pos);
notifyItemRangeRemoved(pos,
viewList.size());
listener.onItemRemoved(pos);
}

});
}

private View getItem(int position) {

return !viewList.isEmpty() ? viewList.get(position) :
null;

}

@Override
public int
getItemCount() {
return
viewList.size();
}

class AppWidgetHolder extends
RecyclerView.ViewHolder {

private FrameLayout
view;

private Button button;


AppWidgetHolder(View itemView) {
super(itemView);
view =
(FrameLayout) itemView.findViewById(R.id.app_widget);
button = (Button)
itemView.findViewById(R.id.delete);

}


private void setView (View view) {

if(view.getParent() != null)
{
((ViewGroup)view.getParent()).removeView(view);
}

this.view.addView(view);
}

private void setNum (String
num) {
this.button.setText(num);

}


}


}



XML
of my ViewHolder looks like
this:



            xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"

android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginBottom="20dp">


android:layout_centerInParent="true"
android:id="@+id/delete"

android:layout_width="50dp"

android:layout_alignParentEnd="true"


android:layout_height="wrap_content"

android:layout_marginLeft="5dp"
tools:text="Del"
/>


android:layout_toStartOf="@id/delete"

android:layout_centerHorizontal="true"

android:layout_centerInParent="true"
android:id="@+id/app_widget"

android:layout_width="wrap_content"


android:layout_height="wrap_content"
android:layout_alignParentStart="true"
/>




So
inside onBindViewHolder method, I'm setting onClick listener which should remove
AppWidgetHostView in that position.. So after notifying item removed, I'm calling
listener.onItemRemoved(pos), and it's implementation in fragment looks like
this:



 @Override
public
void onItemRemoved(int position) {


viewList.remove(position);
mAdapter.setData(viewList);
}



So it again sets the
data for adapter and notifies data set
changed.



But the problem is, items aren't
properly removed when I click delete button. ViewList resizes ok, but items behave
strangely, if I add 3 items and delete second one for example, it stays on the screen
but third goes on top of it (second still visible), then, if I delete first one, it
stays, previous second one is now deleted and new second one goes on top of first one.
But if I click delete button for every item, it will delete all the views, but they will
behave strangely in that process... Any advice, hint?



Answer




Using both @Adithya and @Stanislav Bondar's
advices, I came up to solution:




This
is the onBindViewHolder method:




@Override
public void onBindViewHolder(final AppWidgetHolder holder, final int
position) {
final View view = getItem(position);

holder.setView(view);

holder.setNum(String.valueOf(position));


holder.button.setOnClickListener(new View.OnClickListener() {


@Override
public void onClick(View v) {

int pos =
holder.getAdapterPosition();
viewList.remove(pos);

listener.onItemRemoved(pos);
}

});
}



And
inside
onItemRemoved:



@Override
public
void onItemRemoved(int position) {
viewList.remove(position);

mAdapter.notifyItemRemoved(position);
}



I
had to remove the item at that position both inside adapter and fragment, because if I
had 5 items in fragment which i pass to adapter and if I remove it only in adapter, once
I pass new item again, it will send 6 items instead 5.. Maybe there is a better way, but
this did solution resolved the problem


No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...