我正在使用一个自定义的recyclelerView,它可以有一个页脚和一个标题,这会影响动画,这是一个正在发生的事情的视频:http://www.videosprout.com/video?id=00fae6ac-39ff-47b6-b981-803d2773b67b
为什么每个视图都会向后移动一个位置然后再移回到原来的位置而不是不这样做?
这是我的适配器:
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);
}
编辑:使用removeData(getAdapterPosition()
答案 0 :(得分:1)
这种情况正在发生,因为元素被添加到数组的开头(索引0)。当发生这种情况时,RecyclerView
将如视频中所示做出反应,因为它假装后备数据存储是一个列表,并且所有元素都在一个索引上移动,并且元素插入到开头...恰好位于顶部。
如果在适配器的末尾添加了元素,您可以看到它不会做这种丑陋的行为:MyAdapter.addData(MyAdapter.getItemCount() - 1, "Event ");
。但当然,这也不是你想要的,因为它是错误的索引......现在看起来现有元素实际上是在GUI和事物上跳过一个索引......但这是一个有趣的实验,验证理论。
仍然使用MyAdapter.addData(MyAdapter.getItemCount() - 1, "Event ");
在数组末尾添加元素,但反过来使LinearLayoutManager
显示元素!这可以通过以下方式完成:
linearLayoutManager.setReverseLayout(true)
LinearLayoutManager(context,orientation,isReversed)
你可能需要做一些关于页眉和页脚放置在适配器中的内容,以确保它们在RecyclerView.Adapter
中作为页眉和页脚保留但是... RecyclerView.LayoutManager
在显示内容时反转。