RecyclerView에서 항목 제거시 애니메이션이 없습니다.
RecyclerView
처음으로 사용 하고 있습니다. 항목 추가에 대한 애니메이션이 잘 작동하더라도 항목 제거에 애니메이션이 없다는 점을 제외하고는 모든 것이 잘 작동합니다.
커스텀 아이템 애니메이터를 설정하지 않았지만 문서 에 따르면 :
항목 추가 및 제거를위한 애니메이션은 기본적으로
RecyclerView
.
따라서 제거시 애니메이션이 작동합니다.
기본 애니메이션을 제거하고 싶지만 작동하지 않습니다.
RecyclerView를 설정하는 방법은 다음과 같습니다.
private void setupRecyclerView() {
mRecyclerView = (RecyclerView) mRootView.findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
View emptyView = mRootView.findViewById(R.id.empty_view);
mAdapter = new RoutineAdapter(getActivity(), mRoutineItems, emptyView);
mRecyclerView.setAdapter(mAdapter);
}
이것은 내 어댑터입니다.
private class RoutineAdapter
extends RecyclerView.Adapter<RoutineAdapter.ViewHolder> {
private final Context mContext;
private List<RoutineItem> mData;
private View mEmptyView;
public RoutineAdapter(Context context, List<RoutineItem> data, View emptyView) {
mContext = context;
mData = data;
mEmptyView = emptyView;
setEmptyViewVisibility();
}
public void add(RoutineItem routineItem, int position) {
mData.add(position, routineItem);
setEmptyViewVisibility();
notifyItemInserted(position);
}
public void remove(int position){
mData.remove(position);
setEmptyViewVisibility();
notifyItemRemoved(position);
}
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(mContext).inflate(
R.layout.fragment_routines_list_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
final RoutineItem routineItem = getItem(position);
holder.circle.setBackgroundResource(
colorNumberToDrawableResource(routineItem.colorNumber));
holder.initial.setText(routineItem.routineName.substring(0, 1));
holder.routineName.setText(routineItem.routineName);
holder.lastTimeDone.setText(routineItem.lastTimeDoneText);
if (routineItem.isSelected) {
holder.itemView.setBackgroundColor(
getResources().getColor(R.color.background_item_selected));
} else {
holder.itemView.setBackgroundResource(
R.drawable.darker_background_on_pressed);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPresenter.onRoutineClicked(routineItem.routineName);
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
mPresenter.onRoutineLongClicked(routineItem.routineName);
return true;
}
});
}
@Override
public int getItemCount() {
return mData.size();
}
public RoutineItem getItem(int position) {
return mData.get(position);
}
private void setEmptyViewVisibility() {
if (getItemCount() == 0) {
mEmptyView.setVisibility(View.VISIBLE);
} else {
mEmptyView.setVisibility(View.GONE);
}
}
class ViewHolder extends RecyclerView.ViewHolder {
public final View circle;
public final TextView initial;
public final TextView routineName;
public final TextView lastTimeDone;
public ViewHolder(View view) {
super(view);
circle = view.findViewById(R.id.circle);
initial = (TextView) view.findViewById(R.id.initial);
routineName = (TextView) view.findViewById(R.id.routine_name);
lastTimeDone = (TextView) view.findViewById(R.id.last_time_done);
}
}
}
Fragment_routines_list_item.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="@dimen/standard_list_item_height"
android:paddingBottom="8dp"
android:background="@drawable/darker_background_on_pressed"
android:clickable="true">
......
</RelativeLayout>
기본 제거 애니메이션이 작동하지 않는 원인은 무엇입니까?
리사이클 러보기에서 항목을 제거하는 적절한 방법은 데이터 세트에서 항목을 제거한 다음 어댑터에 항목이 제거되었음을 알리는 것입니다.
myDataset.remove(position); // myDataset is List<MyObject>
mAdapter.notifyItemRemoved(position);
해결했습니다.
문제는를 호출 한 후 제거 애니메이션을 중지한다고 가정하는 mAdapter.remove(position)
코드의 다른 부분이 호출된다는 것 mAdapter.notifyDataSetChanged()
입니다.
요약하자면 mAdapter.notifyDataSetChanged
애니메이션이 진행 중일 때 호출 하면 애니메이션이 중지됩니다.
아래와 같이 notifyItemRemoved(position)
대신 사용notifyDataSetChanged()
myDataset.remove(position);
notifyItemRemoved(position);
때문에 notifyDataSetChanged()
단순히 어떤 애니메이션없이 업데이트 된 데이터를 통지합니다.
애니메이션으로보기를 제거하고 다음과 같이 인덱스를 업데이트 할 수있었습니다.
어댑터 내에서
public boolean removeItem(int position) {
if (data.size() >= position + 1) {
data.remove(position);
return true;
}
return false;
}
뷰를 제거하는 동안
if (adapter.removeItem(position)) {
adapter.notifyItemRemoved(position);
adapter.notifyItemRangeChanged(position, adapter.getItemCount());
}
두 번 클릭 등을 보장하기 위해 부울 메서드를 사용했습니다. 충돌을 일으키지 마십시오.
Another reason for a not properly working remove animation could be the RecyclerViews
height. Verify that the height is match_parent
and NOT wrap_content
!
after long debugging I realized I had to add setHasStableIds(true)
to my adapter and implement
@Override
public long getItemId(int position) {
return position;
}
after that remove animation began to work
Late but might be helpful to someone, who want {search items with animation}
Use below code In your activity or fragment where
yourAdapter.animateTo(filteredModelList);
Use below code in your RecyclerAdapter class
public void animateTo(List<CommonModel> models) {
applyAndAnimateRemovals(models);
applyAndAnimateAdditions(models);
applyAndAnimateMovedItems(models);
}
private void applyAndAnimateRemovals(List<CommonModel> newModels) {
for (int i = items.size() - 1; i >= 0; i--) {
final CommonModel model = items.get(i);
if (!newModels.contains(model)) {
removeItem(i);
}
}
}
private void applyAndAnimateAdditions(List<CommonModel> newModels) {
for (int i = 0, count = newModels.size(); i < count; i++) {
final CommonModel model = newModels.get(i);
if (!items.contains(model)) {
addItem(i, model);
}
}
}
private void applyAndAnimateMovedItems(List<CommonModel> newModels) {
for (int toPosition = newModels.size() - 1; toPosition >= 0; toPosition--) {
final CommonModel model = newModels.get(toPosition);
final int fromPosition = items.indexOf(model);
if (fromPosition >= 0 && fromPosition != toPosition) {
moveItem(fromPosition, toPosition);
}
}
}
private CommonModel removeItem(int position) {
final CommonModel model = items.remove(position);
notifyItemRemoved(position);
return model;
}
private void addItem(int position, CommonModel model) {
items.add(position, model);
notifyItemInserted(position);
}
private void moveItem(int fromPosition, int toPosition) {
final CommonModel model = items.remove(fromPosition);
items.add(toPosition, model);
notifyItemMoved(fromPosition, toPosition);
}
I ran into same issue, and I fixed this by implementing my own RecyclerView, and in my recyclerview, I did this:
public class MyRecyclerView extends RecyclerView {
private View mEmptyView;
private AdapterDataObserver mDataObserver = new AdapterDataObserver() {
public void onChanged() {
super.onChanged();
updateEmptyView();
}
public void onItemRangeRemoved(int positionStart, int itemCount) {
super.onItemRangeRemoved(positionStart, itemCount);
updateEmptyView();
}
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
updateEmptyView();
}
};
// private void setAdapter() {}
private void updateEmptyView() {
// update empty view's visibility
}
}
Basically, when you add/remove item into/from recyclerview, you can call notifyItemInserted()/ notifyItemRemoved() and notifyItemRangeChanged(), these method will invoke onItemRangeRemoved()
/ onItemRangeInserted()
in mDataObserver
. So in these method, you can update empty view's visibility, and it will not break animations.
참고URL : https://stackoverflow.com/questions/27187733/no-animation-on-item-removal-on-recyclerview
'IT TIP' 카테고리의 다른 글
MongoDB를 사용한 단위 테스트 (0) | 2020.12.07 |
---|---|
대안 (0) | 2020.12.07 |
Gerrit에서 주어진 패치 세트를 git-pull하는 방법은 무엇입니까? (0) | 2020.12.07 |
v2.4에서 / [post-id]가 더 이상 사용되지 않으므로 개별 게시물을 검색하려면 어떻게해야합니까? (0) | 2020.12.07 |
Angular 2 빠른 시작 : 예기치 않은 토큰 < (0) | 2020.12.07 |