gpt4 book ai didi

java - Android:在 RecyclerView 中添加 View 时出现奇怪的 react

转载 作者:行者123 更新时间:2023-11-30 10:46:12 24 4
gpt4 key购买 nike

我正在使用一个自定义的 recyclerView,它可以有一个页脚和一个页眉,它应该不会影响动画,这里是一个正在发生的事情的视频:http://www.videosprout.com/video?id=00fae6ac-39ff-47b6-b981-803d2773b67b

为什么每个 View 都向后移动一个位置,然后又回到原来的位置,而不是不这样做?

这是我的适配器:

public class AddEventsAdapter extends HFRecyclerViewAdapter<String, AddEventsAdapter.ViewHolder> {

public AddEventsAdapter(Context context) {
super(context);
}

@Override
public void footerOnVisibleItem() {

}

@Override
public void addData(int position, String item) {
super.addData(position, item);
}

@Override
public ViewHolder onCreateDataItemViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.event_item, parent, false);
return new ViewHolder(v);
}

@Override
public void onBindDataItemViewHolder(ViewHolder holder, int position) {
holder.itemTv.setText(getData().get(position));
}

class ViewHolder extends RecyclerView.ViewHolder{
TextView itemTv;
public ViewHolder(View itemView) {
super(itemView);
itemTv = (TextView)itemView.findViewById(R.id.eventName);

}
}
}

实现:

    final AddEventsAdapter MyAdapter = new AddEventsAdapter(this);
AddEventsRecycler.setAdapter(MyAdapter);
AddEventsRecycler.setLayoutManager(new LinearLayoutManager(this));

//add footer
final View footerView = LayoutInflater.from(this).inflate(R.layout.events_footer, AddEventsRecycler, false);
MyAdapter.setFooterView(footerView);

footerView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyAdapter.addData(0, "Event number" + ++g);
}
});

ArrayList<String> data = new ArrayList<>();
data.add("Vacation");

MyAdapter.setData(data);

自定义 RecyclerAdapter:

public abstract class HFRecyclerViewAdapter<T, VH extends RecyclerView.ViewHolder> extends BaseRecyclerViewAdapter<T> {

public HFRecyclerViewAdapter(Context context) {
super(context);
}

private static final int TYPE_HEADER = Integer.MAX_VALUE;
private static final int TYPE_FOOTER = Integer.MAX_VALUE - 1;
private static final int ITEM_MAX_TYPE = Integer.MAX_VALUE - 2;
private RecyclerView.ViewHolder headerViewHolder;
private RecyclerView.ViewHolder footerViewHolder;

class HFViewHolder extends RecyclerView.ViewHolder {
HFViewHolder(View v) {
super(v);
}
}

public void setHeaderView(View header){
if (headerViewHolder == null || header != headerViewHolder.itemView) {
headerViewHolder = new HFViewHolder(header);
notifyDataSetChanged();
}
}

public void setFooterView(View foot){
if (footerViewHolder == null || foot != footerViewHolder.itemView) {
footerViewHolder = new HFViewHolder(foot);
notifyDataSetChanged();
}
}

public void removeHeader(){
if (headerViewHolder != null){
headerViewHolder = null;
notifyDataSetChanged();
}
}
public void removeFooter(){
if (footerViewHolder != null){
footerViewHolder = null;
notifyDataSetChanged();
}
}

public boolean isHeader(int position){
return hasHeader() && position == 0;
}

public boolean isFooter(int position){
return hasFooter() && position == getDataItemCount() + (hasHeader() ? 1 : 0);
}

private int itemPositionInData(int rvPosition){
return rvPosition - (hasHeader() ? 1 : 0);
}
private int itemPositionInRV(int dataPosition){
return dataPosition + (hasHeader() ? 1 : 0);
}

@Override
public void notifyMyItemInserted(int itemPosition) {
notifyItemInserted(itemPositionInRV(itemPosition));
}
@Override
public void notifyMyItemRemoved(int itemPosition) {
notifyItemRemoved(itemPositionInRV(itemPosition));
}

@Override
public void notifyMyItemChanged(int itemPosition) {
notifyItemChanged(itemPositionInRV(itemPosition));
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_HEADER) {
return headerViewHolder;
} else if (viewType == TYPE_FOOTER) {
return footerViewHolder;
}
return onCreateDataItemViewHolder(parent, viewType);
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (!isHeader(position) && !isFooter(position))
onBindDataItemViewHolder((VH)holder, itemPositionInData(position));

if (isFooter(position)){
footerOnVisibleItem();
}
}

public abstract void footerOnVisibleItem();

@Override
public int getItemCount() {
int itemCount = getDataItemCount();
if (hasHeader()) {
itemCount += 1;
}
if (hasFooter()) {
itemCount += 1;
}
return itemCount;
}

@Override
public int getItemViewType(int position) {
if (isHeader(position)) {
return TYPE_HEADER;
}
if (isFooter(position)) {
return TYPE_FOOTER;
}
int dataItemType = getDataItemType(itemPositionInData(position));
if (dataItemType > ITEM_MAX_TYPE) {
throw new IllegalStateException("getDataItemType() must be less than " + ITEM_MAX_TYPE + ".");
}
return dataItemType;
}

public int getDataItemCount() {
return super.getItemCount();
}

/**
* make sure your dataItemType < Integer.MAX_VALUE-1
*
* @param position item view position in rv
* @return item viewType
*/
public int getDataItemType(int position){
return 0;
}


public boolean hasHeader(){
return headerViewHolder != null;
}
public boolean hasFooter(){
return footerViewHolder != null;
}

public abstract VH onCreateDataItemViewHolder(ViewGroup parent, int viewType);

public abstract void onBindDataItemViewHolder(VH holder, int position);



}

编辑: 删除 View 时会发生同样的情况,使用 removeData(getAdapterPosition()

最佳答案

为什么

这是因为元素被添加到数组的开头(索引 0)。发生这种情况时,RecyclerView 将做出视频中所示的 react ,因为它假装后备数据存储是一个列表,并且所有元素都移动到一个索引上,并且该元素被插入到开头...恰好在顶部。

您可以看到,如果在适配器末尾添加元素,它不会执行这种丑陋的行为:MyAdapter.addData(MyAdapter.getItemCount() - 1, "Event "); .但是当然,这也不是你想要的,因为它是错误的索引......现在看起来现有元素实际上在 GUI 和其他东西上跳了一个索引......但这是一个有趣的实验验证理论。

一个解决方案

仍然使用 MyAdapter.addData(MyAdapter.getItemCount() - 1, "Event "); 在数组末尾添加元素,但使 LinearLayoutManager 显示逆向元素!这可以通过以下方式完成:

您可能需要对位于适配器中的页眉和页脚做一些事情,以确保它们在 RecyclerView.Adapter 中保留为页眉和页脚,但是...一旦 RecyclerView .LayoutManager 正在反向显示内容。

关于java - Android:在 RecyclerView 中添加 View 时出现奇怪的 react ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36678466/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com