我写了FooterAdapter
似乎完美无缺。
我意识到ViewHolder
有一个字段mPosition
,其中包含每个元素中的状态,导致我怀疑使用装饰器模式无法实现标头,因为它会保持不同每个Adapter
中的位置。
也就是说,除非包装器/装饰器Adapter
没有改变其他元素。也就是说:只要数据不需要绑定到它们,页脚就可以了。
如果Wrapper适配器可行,那么我们需要更多访问ViewHolder?我不确定领域是什么
预期用法:
headerView = new View( context );
footerView = new View( context );
MyAdapter myAdapter = new MyAdapter();
HeaderAdapter headerAdapter = new HeaderAdapter( myAdapter , headerView );
FooterAdapter footerAdapter = new FooterAdapter( headerAdapter , footerView );
RecyclerView recyclerView = new RecyclerView();
recyclerView.setAdapter( footerAdapter );
这真的很酷,因为我们可以添加标题&页脚到任意Adapter
并且不必担心索引和抵消项目计数。
FooterAdapter.java
public class FooterAdapter extends RecyclerView.Adapter
{
private static final String TAG = "FooterAdapter";
private final RecyclerView.Adapter<RecyclerView.ViewHolder> wrappedAdapter;
private View footer;
public static final int FOOTER_TYPE = 0x72846fe;
public FooterAdapter( RecyclerView.Adapter<RecyclerView.ViewHolder> wrappedAdapter , View footer )
{
this.footer = footer;
this.wrappedAdapter = wrappedAdapter;
wrappedAdapter.registerAdapterDataObserver(new ThisObserver());
}
@Override
public int getItemViewType(int position)
{
if( position == wrappedAdapter.getItemCount() ) return FOOTER_TYPE;
return wrappedAdapter.getItemViewType(position);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if( viewType == FOOTER_TYPE )
{
return new RecyclerView.ViewHolder( footer ){};
}else
{
return wrappedAdapter.onCreateViewHolder(parent,viewType);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if( holder.getItemViewType() == FOOTER_TYPE ) return;
return wrappedAdapter.bindViewHolder( holder , position );
}
@Override
public int getItemCount() {
return wrappedAdapter.getItemCount() + 1;
}
private class ThisObserver extends AdapterDataObserver
{
public void onChanged() {
notifyDataSetChanged();
}
public void onItemRangeChanged(int positionStart, int itemCount) {
notifyItemRangeChanged(positionStart,itemCount);
}
public void onItemRangeInserted(int positionStart, int itemCount) {
notifyItemRangeInserted(positionStart,itemCount);
}
public void onItemRangeRemoved(int positionStart, int itemCount) {
notifyItemRangeRemoved(positionStart,itemCount);
}
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
int lower = Math.min( fromPosition , toPosition );
int upper = Math.max( fromPosition , toPosition );
for( int i = itemCount-1 ; i < itemCount ; i++ )
{
notifyItemMoved(upper+i,lower+i+(toPosition-fromPosition));
}
}
}
}
HeaderAdapter.java
public class HeaderAdapter extends RecyclerView.Adapter
{
private static final String TAG = "HeaderAdapter";
private final RecyclerView.Adapter<RecyclerView.ViewHolder> wrappedAdapter;
private View header;
public static final int HEADER_TYPE = 0x747efe;
public HeaderAdapter( RecyclerView.Adapter<RecyclerView.ViewHolder> wrappedAdapter , View header )
{
this.header = header;
this.wrappedAdapter = wrappedAdapter;
wrappedAdapter.registerAdapterDataObserver(new ThisObserver());
}
@Override
public int getItemViewType(int position)
{
return position == 0 ? HEADER_TYPE : wrappedAdapter.getItemViewType(position - 1);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if( viewType == HEADER_TYPE )
{
return new RecyclerView.ViewHolder( header ){};
}else
{
return new RecyclerView.ViewHolder( wrappedAdapter.onCreateViewHolder(parent,viewType).itemView ){};
// I thought some kind of wrapping (hack?) like this might get
// around the different indexing in different Adapters, but
// it doesn't work, it would probably needs more
// information, or to be able to observe changes in
// the "child" ViewHolder.
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if( holder.getItemViewType() != HEADER_TYPE ) wrappedAdapter.bindViewHolder( holder , position - 1 );
}
@Override
public int getItemCount() {
return wrappedAdapter.getItemCount() + 1;
}
private class ThisObserver extends RecyclerView.AdapterDataObserver
{
public void onChanged() {
notifyDataSetChanged();
}
public void onItemRangeChanged(int positionStart, int itemCount) {
notifyItemRangeChanged(1+positionStart,itemCount);
}
public void onItemRangeInserted(final int positionStart, final int itemCount) {
notifyItemRangeInserted(1 + positionStart, itemCount);
}
public void onItemRangeRemoved(int positionStart, int itemCount) {
notifyItemRangeRemoved(1 + positionStart, itemCount);
}
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
fromPosition++;
toPosition++;
int lower = Math.min( fromPosition , toPosition );
int upper = Math.max( fromPosition , toPosition );
for( int i = itemCount-1 ; i < itemCount ; i++ ) notifyItemMoved(upper+i,lower+i+(toPosition-fromPosition));
}
}
}
答案 0 :(得分:1)
事实证明,页脚并不完美。
因此,您无法将此模式用于页眉或页脚。
当您删除页脚时,页脚要达到的最高索引值。
我们无法访问许多包级别变量。我认为预期的用法是一次性编写整个课程。
页眉和页脚可能更适合LayoutManager,我的意思是,我们已经知道它们是什么,它们不需要&#34;适应&#34;