我已经制作了一个装饰类来在recyclerview中创建粘性标题。我有两个问题。
所以我想知道如何解决这些问题?编写自定义布局管理器的唯一方法是什么?我无法想到任何其他解决方案。我甚至不确定自定义布局管理器是否可以解决这个问题。
下面你可以找到我的装饰类:
package com.done.xrecyclerview.library;
import android.graphics.Canvas;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
public class StickyHeaderDecoration extends RecyclerView.ItemDecoration
{
private static final boolean D = true;
private static final String TAG = "HeaderDecoration";
private void init()
{
//Do your initializations here.
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state)
{
super.onDrawOver(c, parent, state);
if (parent.getAdapter() != null && parent.getAdapter()
.getItemCount() > 1) //RecylerView's adapter exist and has items.
{
View firstView = parent.getChildAt(0); //get the first visible view.
View secondView = parent.getChildAt(1); //get the second visible view.
View headerView = getHeaderOf(parent, firstView); //get the first visible view's header.
if (isHeaderView(parent, secondView)) //if the second view is also a header
{
if (secondView.getTop() <= headerView.getHeight())
c.translate(0,
secondView.getTop() - headerView.getHeight()); //translate the canvas
}
headerView.draw(c);
c.save();
//c.restore();
c.translate(0, 0);
}
}
/**
* Determines whether the given View is a header.
*
* @param parent Parent of given view.
* @param view View to be checked.
* @return true if the view is a header, false otherwise
*/
private boolean isHeaderView(RecyclerView parent, View view)
{
if (parent.getAdapter() instanceof XRecyclerViewAdapter) //check if the adapter of RecyclerView is an instance of our custom adapter.
{
int childPosition = parent.getChildPosition(view); //get position of the view in the adapter.
XRecyclerViewAdapter adapter = (XRecyclerViewAdapter) parent.getAdapter(); //get the adapter itself.
return adapter.get(childPosition)
.getItemType() == XItemTypes.HEADER; //if the item of the position of view is header.
} else
return false;
}
/**
* Checks whether the given position is occupied by a header.
*
* @param parent RecyclerView that contains the given position.
* @param position Position to be checked.
* @return true if the position is occupied by a header. false otherwise.
*/
private boolean isHeaderPosition(RecyclerView parent, int position)
{
XRecyclerViewAdapter adapter = (XRecyclerViewAdapter) parent.getAdapter();
return adapter.get(position).getItemType() == XItemTypes.HEADER;
}
/**
* Finds the header of given view.
*
* @param parent Parent of the view.
* @param view View itself whose header will be found.
* @return If the given View is already a header, returns that view.
* If the view doesn't have a header returns null.
* If the view has a header returns the view's header.
*/
private View getHeaderOf(RecyclerView parent, View view)
{
if (isHeaderView(parent, view)) //item is already header.
return view; //return the view.
else //item is child. Find it's header.
{
int position = parent.getChildPosition(view); //get the position of given child item in adapter.
//Log.i(TAG, "position = " + position);
XRecyclerViewAdapter adapter = (XRecyclerViewAdapter) parent.getAdapter(); //get the adapter.
for (int i = position; i >= 0; i--) //iterate backwards from the position of given child item.
{
if (isHeaderPosition(parent, i)) //if the iterated position is occupied by a header
{
RecyclerView.ViewHolder viewHolder = adapter.onCreateViewHolder(parent,
XRecyclerViewAdapter.VIEW_TYPE_HEADER); //create its viewholder.
adapter.onBindViewHolder(viewHolder, i); //bind its viewholder.
View header = viewHolder.itemView; //get that header view to set LayoutParams.
if (header.getLayoutParams() == null) //if the LayoutParams null, initiate it.
{
header.setLayoutParams(new RecyclerView.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
int widthSpec;
int heightSpec;
widthSpec = View.MeasureSpec.makeMeasureSpec(parent.getWidth(),
View.MeasureSpec.EXACTLY);
heightSpec = View.MeasureSpec.makeMeasureSpec(parent.getHeight(),
View.MeasureSpec.UNSPECIFIED);
int childWidth = ViewGroup.getChildMeasureSpec(widthSpec,
parent.getPaddingLeft() + parent.getPaddingRight(),
header.getLayoutParams().width);
int childHeight = ViewGroup.getChildMeasureSpec(heightSpec,
parent.getPaddingTop() + parent.getPaddingBottom(),
header.getLayoutParams().height);
header.measure(childWidth, childHeight);
header.layout(0, 0, header.getMeasuredWidth(), header.getMeasuredHeight());
return header;
}
}
}
return null;
}
}