ebarrenechea / header-decor Goto Github PK
View Code? Open in Web Editor NEWA couple of sticky header decorations for android's recycler view.
License: Apache License 2.0
A couple of sticky header decorations for android's recycler view.
License: Apache License 2.0
viewHolder.buttonDelete.setOnClickListener(new View.OnClickListener() {
@OverRide
public void onClick(View v) {
Log.v("test", "clicked delete");
}
});
isn't working. I'm setting this in the onBindViewHolder(). How do I implement on click?
I'm trying to put a ProgressBar in the header but the animation does not play ? Does the header support animations ?
Thanks.
Please can any one help me to add click event to the header views?
Hi,
I have an issue when the first visible headers on the screen are empty.
Here my code:
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.rv_list);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
Adapter adapter = new Adapter (list);
StickyHeaderDecoration decoration = new StickyHeaderDecoration(adapter);
recyclerView.addItemDecoration(decoration);
recyclerView.setAdapter(adapter);
What I do wrong ? Thanks. :)
I was trying to add some buttons on the header view.
And I realized that it doesn't allow to be clicked because the view was drew by onDrawOver.
It is not the normal item view on the RecyclerView but just the same shape of the item view.
Could you recommend how I can add the click event on the header buttons?
Someone asked the question on the StackOverFlow page.
But still I don't have any solution from it.
http://stackoverflow.com/questions/31102738/how-to-handle-click-event-in-recyclerview-itemdecoration
A very useful complement to your library is https://github.com/thefuntasty/infinity
To use it, we need to extend from an adapter class of their own.
When we want to use both libraries, there is a name collision for the functions. The easy way to fix it would be to simply be more specific in the function names for your interface:
long getStickyHeaderId(int position);
T onCreateStickyHeaderViewHolder(ViewGroup parent);
void onBindStickyHeaderViewHolder(T viewholder, int position);
Would that be possible?
The current workaround is to use a generic ViewHolder as the template parameter for the interface, but that defeats the purpose of having a generic interface and forces you to make some ugly casts in code.
It would be nice to have a quick start guide with code and XML examples. Also, is switching from linear to grid has any affect? In my case, I wouldn't need headers for my grid.
thanks a lot
Hard to implement, because first row, that is 1st level header in my case does not have subheader (its on 2nd position in adapter) but code does not accept this.
It will be useful
Hi there,
I'm new to android, I just wanted to use the app in my upcoming project. Please give us wiki link or sample code to how to use the library in code like in Sticky Headers Recyclerview.
For example, if I use this simple condition to check(for simplicity)
if(task.getTitle().equals("Sticky Above This")){ return (long) position; } return StickyHeaderDecoration.NO_HEADER_ID;
When there are multiple items between a view, it produces this strange behavior
When I use
return (long) position / 2
it shows a header every 2 items and scrolls just fine. I'm not 100% sure if it's me or the library but it would be nice to have a sense of direction.
hi i´m trying to use the header -Decor with the gridLayoutmanager but when i uses it all the information in the recycleview is in disorder
Hello, I found a small issue related with header-decor. I have a RecyclerView with two view types, like a chat app. As I saw in your sample I've implemented StickyHeaderAdapter and created a new StickyHeaderDecoration(adapter) and add it on my RecyclerView through addItemDecoration(decor, 0).
If I have a sequence of layout rows on the same type the header works like a charm. However, if I have different view types close (one view type above/below the another one) the header view shift to right or left. I'm using the version 0.2.8
Hi just a suggestion:
Would be awesome if this library supported collapsed / expanded states for subheaders & headers.
kindest regards
Hi!
I'm wondering if this library could work also with a GridLayoutManager for RecyclerView.
Cheers!
I want using in ScrollView.
But header-decor is not working in ScrollView.
How can I using in ScrollView
I'm setting up the StickyHeaderDecoration like this:
mRecyclerViewAdapter = new MyStickyHeaderAdapter(...);
mStickyHeaderDecoration = new StickyHeaderDecoration(mRecyclerViewAdapter);
mRecyclerView.setAdapter(mRecyclerViewAdapter);
mRecyclerView.addItemDecoration(mStickyHeaderDecoration);
And the layout is something like:
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
The sticky header works, but then the headers are showing on top of the scroll bars:
Not sure if anything I can do to make the headers not covering the scrollbar?
Thanks!
Hi there,
This might be a simple question, but I was just playing around with the library and couldn't figure out a way to set up a custom position for each header using getHeaderId()
method.
Any idea how to do it?
Thanks in advance.
In my RecyclerView I use 'notifyItemChanged(int position)' method to animate an image on an item when click on it. And when I click, above the item an excess header appears for a second and disappears.
This doesn't happen if the list has only one header or with the last header if they are many.
Step 1 (do nothing):
Hello, I'm using this library in a project that requires accessibility.
When using the TalkBack in a screen with "sticky headers" the headers can't be read or focused by the TalkBack (or accessibility inspector?).
Is there any workaround?
Thanks in advance.
header item's child click is not working
here is my code
public HeaderViewHolder(View itemView) { super(itemView); this.textView = (TextView) itemView.findViewById(R.id.txtDateSection); itemView.findViewById(R.id.imgClickTest).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context, "Position=>"+ getAdapterPosition(), Toast.LENGTH_LONG).show(); } }); }
I'm getting error trying to build my project with header-decor dependency:
com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java'' finished with non-zero exit value 2
Here's my dependencies from app-level build.gradle:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:design:23.4.0'
compile 'ca.barrenechea.header-decor:header-decor:0.2.8'
}
It only happened in the first time using the listview. Scroll up and down with different header.
The top stickyheader works fine. But there would be another header glitch a frame in the middle of listview that suppose not to show a header there.
And then keep using listview there would be no glitch at all if the whole listview item was surfed.
It happens with notifyItemRangeChanged too
I implemented my adapter using the library, but still I am not able to make headers stick.
Here is my adapter implementation:
public class StickyFeedAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements StickyHeaderAdapter<StickyFeedAdapter.HeaderViewHolder> {
protected final String TAG = getClass().getSimpleName();
private Context context;
private List<FeedItems> feedItems;
private Fragment fragment;
String API;
private String token;
TinyDB tinyDB;
RestAdapter restAdapter;
private static int radius = Utils.dpToPx(28);
private LayoutInflater mInflater;
Galleri5Application application;
MixpanelAPI mixpanel;
private static final int ITEM_TYPE_HEADER = 0, ITEM_TYPE_CARD = 1, ITEM_TYPE_RIBBON = 2, ITEM_TYPE_LOADING = 3;
public StickyFeedAdapter(Context context, List<FeedItems> list, Fragment fragment) {
this.context = context;
this.feedItems = list;
this.fragment = fragment;
mInflater = LayoutInflater.from(context);
application = (Galleri5Application) ((AppCompatActivity) context).getApplication();
API = application.getAPI();
mixpanel = MixpanelAPI.getInstance(context, application.getMixpanelId());
OkHttpClient okHttpClient = new OkHttpClient();
tinyDB = new TinyDB(context);
token = tinyDB.getString(AppConstants.GALLERI5_ACCESS_TOKEN);
RequestInterceptor requestInterceptor = new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
request.addHeader("Accept", "application/json");
request.addHeader("Authorization", "Token " + token);
}
};
restAdapter = new RestAdapter.Builder()
.setClient(new OkClient(okHttpClient))
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(API)
.setRequestInterceptor(requestInterceptor)
.build();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LogUtil.i(TAG, "onCreateViewHolder called");
if (viewType == ITEM_TYPE_HEADER) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.feed_row, parent, false);
return new HeaderViewHolder(view);
} else if (viewType == ITEM_TYPE_CARD) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.feed_new_card, parent, false);
return new CardViewHolder(view);
} else if (viewType == ITEM_TYPE_RIBBON) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.feed_row_ribbon, parent, false);
return new RibbonViewHolder(view, context);
} else if (viewType == ITEM_TYPE_LOADING) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_loading, parent, false);
return new LoadingViewHolder(view);
} else {
return null;
}
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
LogUtil.i(TAG, "onBindViewHolder called");
int viewType = getItemViewType(position);
FeedItems currentItem = getItem(position);
StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams();
if (viewType == ITEM_TYPE_HEADER) {
final HeaderItem headerItem = currentItem.getHeaderItem();
layoutParams.setFullSpan(true);
if (headerItem.isFollowing()) {
((HeaderViewHolder) holder).mightLike.setVisibility(View.GONE);
((HeaderViewHolder) holder).followButton.setBackgroundResource(R.drawable.button_background_filled);
((HeaderViewHolder) holder).followText.setTextColor(Color.parseColor("#424447"));
((HeaderViewHolder) holder).followText.setText("FOLLOWING");
} else {
((HeaderViewHolder) holder).mightLike.setVisibility(View.VISIBLE);
((HeaderViewHolder) holder).followButton.setBackgroundResource(R.drawable.button_background);
((HeaderViewHolder) holder).followText.setTextColor(Color.parseColor("#F0F0E9"));
((HeaderViewHolder) holder).followText.setText("FOLLOW");
}
((HeaderViewHolder) holder).followButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!headerItem.isFollowing()) {
//follow gallery
headerItem.setFollowing(true);
((HeaderViewHolder) holder).mightLike.setVisibility(View.GONE);
((HeaderViewHolder) holder).followButton.setBackgroundResource(R.drawable.button_background_filled);
((HeaderViewHolder) holder).followText.setTextColor(Color.parseColor("#424447"));
((HeaderViewHolder) holder).followText.setText("FOLLOWING");
follow(headerItem.getGalleryPk());
} else {
//unfollow gallery
headerItem.setFollowing(false);
((HeaderViewHolder) holder).mightLike.setVisibility(View.VISIBLE);
((HeaderViewHolder) holder).followButton.setBackgroundResource(R.drawable.button_background);
((HeaderViewHolder) holder).followText.setTextColor(Color.parseColor("#F0F0E9"));
((HeaderViewHolder) holder).followText.setText("FOLLOW");
unfollow(headerItem.getGalleryPk());
}
}
});
((HeaderViewHolder) holder).shareButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
((HeaderViewHolder) holder).galleryName.setText(headerItem.getGalleryName());
((HeaderViewHolder) holder).numPhotos.setText(String.format("%s PHOTOS", String.valueOf(headerItem.getNumPhotos())));
((HeaderViewHolder) holder).numFollowers.setText(String.format("%s FOLLOWERS", String.valueOf(headerItem.getNumFollowers())));
} else if (viewType == ITEM_TYPE_CARD) {
final FeedPhoto cardItem = currentItem.getCardItem();
layoutParams.setFullSpan(false);
double aspectRatio = (double) cardItem.getWidth() / cardItem.getHeight();
((CardViewHolder) holder).image.setAspectRatio((float) aspectRatio);
Uri uri = Uri.parse(cardItem.getPhotoUrl());
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setProgressiveRenderingEnabled(true)
.build();
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(request)
.setOldController(((CardViewHolder) holder).image.getController())
.build();
((CardViewHolder) holder).image.setController(controller);
Picasso.with(context)
.load(cardItem.getProfilePic())
.resize(radius, radius)
.centerCrop()
.transform(new CircleTransform())
.into(((CardViewHolder) holder).profilePic);
((CardViewHolder) holder).username.setText(cardItem.getUserName());
((CardViewHolder) holder).timestamp.setText(cardItem.getTime());
if (TextUtils.isEmpty(cardItem.getLocation())) {
((CardViewHolder) holder).locationBox.setVisibility(View.GONE);
} else {
((CardViewHolder) holder).locationBox.setVisibility(View.VISIBLE);
((CardViewHolder) holder).locationText.setText(cardItem.getLocation());
}
if (TextUtils.isEmpty(cardItem.getCaption())) {
((CardViewHolder) holder).captionText.setVisibility(View.GONE);
} else {
((CardViewHolder) holder).captionText.setVisibility(View.VISIBLE);
((CardViewHolder) holder).captionText.setText(cardItem.getCaption());
}
((CardViewHolder) holder).collectButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(context, AddToCollectionActivity.class);
intent.putExtra("photoPk", cardItem.getPk());
intent.putExtra("imageUrl", cardItem.getPhotoUrl());
intent.putExtra("location", cardItem.getLocation());
intent.putExtra("caption", cardItem.getCaption());
context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.slide_up, R.anim.no_change);
}
});
} else if (viewType == ITEM_TYPE_RIBBON) {
RibbonItem ribbonItem = currentItem.getRibbonItem();
layoutParams.setFullSpan(true);
FeedRibbonAdapter feedRibbonAdapter = new FeedRibbonAdapter(context, fragment, ribbonItem);
((RibbonViewHolder) holder).feedRibbonAdapter = feedRibbonAdapter;
((RibbonViewHolder) holder).ribbonText.setText(ribbonItem.getTitle());
((RibbonViewHolder) holder).recyclerView.setAdapter(feedRibbonAdapter);
} else if (viewType == ITEM_TYPE_LOADING) {
layoutParams.setFullSpan(true);
((LoadingViewHolder) holder).indicator.setVisibility(View.VISIBLE);
}
}
public FeedItems getItem(int position) {
return feedItems.get(position);
}
@Override
public int getItemViewType(int position) {
LogUtil.i(TAG, "getItemViewType called");
FeedItems currentItem = getItem(position);
if (currentItem.getType() == 0) {
return ITEM_TYPE_HEADER;
} else if (currentItem.getType() == 1) {
return ITEM_TYPE_CARD;
} else if (currentItem.getType() == 2) {
return ITEM_TYPE_RIBBON;
} else {
return ITEM_TYPE_LOADING;
}
}
@Override
public int getItemCount() {
return feedItems == null ? 0 : feedItems.size();
}
@Override
public long getHeaderId(int position) {
LogUtil.i(TAG, "getHeaderId called");
if (position == 0) { // don't show header for first item
return StickyHeaderDecoration.NO_HEADER_ID;
} else {
return getHeaderForPosition(position);
}
}
private long getHeaderForPosition(int position) {
for (int i = position; i > 0; i--) {
if (getItem(position) != null) {
if (getItem(position).getType() == 0) {
return (long) i;
}
}
}
return StickyHeaderDecoration.NO_HEADER_ID;
}
@Override
public HeaderViewHolder onCreateHeaderViewHolder(ViewGroup parent) {
LogUtil.i(TAG, "onCreateHeaderViewHolder called");
View view = mInflater.inflate(R.layout.feed_row, parent, false);
return new HeaderViewHolder(view);
}
@Override
public void onBindHeaderViewHolder(final HeaderViewHolder viewholder, int position) {
LogUtil.i(TAG, "onBindHeaderViewHolder called");
FeedItems currentItem = getItem(position);
StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) viewholder.itemView.getLayoutParams();
final HeaderItem headerItem = currentItem.getHeaderItem();
layoutParams.setFullSpan(true);
if (headerItem.isFollowing()) {
viewholder.mightLike.setVisibility(View.GONE);
viewholder.followButton.setBackgroundResource(R.drawable.button_background_filled);
viewholder.followText.setTextColor(Color.parseColor("#424447"));
viewholder.followText.setText("FOLLOWING");
} else {
viewholder.mightLike.setVisibility(View.VISIBLE);
viewholder.followButton.setBackgroundResource(R.drawable.button_background);
viewholder.followText.setTextColor(Color.parseColor("#F0F0E9"));
viewholder.followText.setText("FOLLOW");
}
viewholder.followButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!headerItem.isFollowing()) {
//follow gallery
headerItem.setFollowing(true);
viewholder.mightLike.setVisibility(View.GONE);
viewholder.followButton.setBackgroundResource(R.drawable.button_background_filled);
viewholder.followText.setTextColor(Color.parseColor("#424447"));
viewholder.followText.setText("FOLLOWING");
follow(headerItem.getGalleryPk());
} else {
//unfollow gallery
headerItem.setFollowing(false);
viewholder.mightLike.setVisibility(View.VISIBLE);
viewholder.followButton.setBackgroundResource(R.drawable.button_background);
viewholder.followText.setTextColor(Color.parseColor("#F0F0E9"));
viewholder.followText.setText("FOLLOW");
unfollow(headerItem.getGalleryPk());
}
}
});
viewholder.shareButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
viewholder.galleryName.setText(headerItem.getGalleryName());
viewholder.numPhotos.setText(String.format("%s PHOTOS", String.valueOf(headerItem.getNumPhotos())));
viewholder.numFollowers.setText(String.format("%s FOLLOWERS", String.valueOf(headerItem.getNumFollowers())));
}
private void follow(int galleryPk) {
LogUtil.i(TAG, "follow called");
PostAPI api = restAdapter.create(PostAPI.class);
api.follow(galleryPk, new Callback<ActionResponse>() {
@Override
public void success(ActionResponse actionResponse, Response response) {
LogUtil.i(TAG, "follow successful");
}
@Override
public void failure(RetrofitError error) {
LogUtil.i(TAG, "follow failed");
}
});
}
private void unfollow(int galleryPk) {
LogUtil.i(TAG, "unfollow called");
PostAPI api = restAdapter.create(PostAPI.class);
api.unfollow(galleryPk, new Callback<ActionResponse>() {
@Override
public void success(ActionResponse actionResponse, Response response) {
LogUtil.i(TAG, "unfollow successful");
}
@Override
public void failure(RetrofitError error) {
LogUtil.i(TAG, "unfollow failed");
}
});
}
public static class HeaderViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.mightLike)
TextView mightLike;
@Bind(R.id.galleryName)
TextView galleryName;
@Bind(R.id.shareButton)
RelativeLayout shareButton;
@Bind(R.id.shareText)
TextView shareText;
@Bind(R.id.followButton)
RelativeLayout followButton;
@Bind(R.id.followText)
TextView followText;
@Bind(R.id.numPhotos)
TextView numPhotos;
@Bind(R.id.numFollowers)
TextView numFollowers;
public HeaderViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
public static class CardViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.profilePic)
ImageView profilePic;
@Bind(R.id.username)
TextView username;
@Bind(R.id.timestamp)
TextView timestamp;
@Bind(R.id.image)
SimpleDraweeView image;
@Bind(R.id.tagButton)
ImageView tagButton;
@Bind(R.id.reminderButton)
ImageView reminderButton;
@Bind(R.id.collectButton)
RelativeLayout collectButton;
@Bind(R.id.shareButton)
RelativeLayout shareButton;
@Bind(R.id.locationBox)
LinearLayout locationBox;
@Bind(R.id.locationText)
TextView locationText;
@Bind(R.id.captionText)
TextView captionText;
public CardViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
public static class RibbonViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.recyclerView)
FlingRecyclerView recyclerView;
@Bind(R.id.ribbonText)
TextView ribbonText;
FeedRibbonAdapter feedRibbonAdapter;
public RibbonViewHolder(View view, Context context) {
super(view);
ButterKnife.bind(this, view);
LinearLayoutManager layoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(layoutManager);
SpacesItemDecoration spacesItemDecoration = new SpacesItemDecoration(Utils.dpToPx(8));
recyclerView.addItemDecoration(spacesItemDecoration);
}
}
public static class LoadingViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.avloadingIndicatorView)
AVLoadingIndicatorView indicator;
public LoadingViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
private static class SpacesItemDecoration extends RecyclerView.ItemDecoration {
private int space;
public SpacesItemDecoration(int space) {
this.space = space;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view);
int count = state.getItemCount();
if (position == 0) {
outRect.left = space;
outRect.right = space / 2;
} else if (position == count - 1) {
outRect.right = space;
outRect.left = space / 2;
} else {
outRect.left = space / 2;
outRect.right = space / 2;
}
}
}
}
I see that the getHeaderId() is never called. I have one type of view which will be header and 3 other view types that would not be header and won't stick. What's wrong with my implementation?
please tell me how to resolve this dude..
Android 5.1.1 Device Sony M2
FilterAdapter filterAdapter = new FilterAdapter();
StickyHeaderDecoration decoration = new StickyHeaderDecoration(filterAdapter);
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
filterRecyclerView.setHasFixedSize(true);
filterRecyclerView.setLayoutManager(layoutManager);
filterRecyclerView.addItemDecoration(decoration);
filterRecyclerView.setAdapter(filterAdapter);
ArrayList<String> headers = new ArrayList<>(Arrays.asList(getResources().getStringArray(R.array.filter_list_headers)));
List<Object> filterModels = new ArrayList<>();
filterModels.add(new Object());
filterModels.add(new Object());
filterModels.add(new Object());
filterAdapter.addHeaders(headers);
filterAdapter.addAll(filterModels);
filterAdapter.notifyDataSetChanged();
Process: co.route1.client.staging, PID: 7038
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.support.v7.widget.RecyclerView$ViewHolder.getLayoutPosition()' on a null object reference
at android.support.v7.widget.RecyclerView$LayoutParams.getViewLayoutPosition(RecyclerView.java:9472)
at android.support.v7.widget.RecyclerView$LayoutManager.getPosition(RecyclerView.java:6800)
at android.support.v7.widget.LinearLayoutManager.findReferenceChild(LinearLayoutManager.java:1615)
at android.support.v7.widget.LinearLayoutManager.findFirstReferenceChild(LinearLayoutManager.java:1597)
at android.support.v7.widget.LinearLayoutManager.findReferenceChildClosestToStart(LinearLayoutManager.java:1592)
at android.support.v7.widget.LinearLayoutManager.updateAnchorFromChildren(LinearLayoutManager.java:745)
at android.support.v7.widget.LinearLayoutManager.updateAnchorInfoForLayout(LinearLayoutManager.java:713)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:484)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3028)
at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:2625)
at android.view.View.measure(View.java:17637)
at ca.barrenechea.widget.recyclerview.decoration.StickyHeaderDecoration.getHeader(StickyHeaderDecoration.java:128)
at ca.barrenechea.widget.recyclerview.decoration.StickyHeaderDecoration.getItemOffsets(StickyHeaderDecoration.java:67)
how to set different positions for headers like set one header at position 10 and the second one on 13 and so on ? thanks
You have switched parameters in getHeaderTop method in DoubleHeaderDecoration. Calling it with subHeader, header as params, but method expects exactly opposit order (header, subHeader) looks like it works by mistake :-)
Hi Eduardo! I tried use Header-decor view with Expandable RecyclerView library (by Ryan Brooks https://github.com/rbro112/expandable-recycler-view ) to create Expandable items with sticky headers but, I have a problem, can you write any commentary to me. When I StickerheaderDecoration send request to adapter by method getHeaderId I can retrun right header position but when expandable items expended then header will be draw header on incorrect position. Can you any suggestion to solve this?
Hi,nice job on this one.Is there any support or plan to support sticky headers when using a gridlayout manager on android recyclerview.Thanks
In Sticky Header both onCreateHeaderViewHolder and onCreateViewHolder is invoked in one item in same time
Hi Eduardo! I'm trying to use your nice library, but for some random reason, the main header disappears when a subheader pushes the upcoming subheader. Did you ever experience that?
Thanks in advance!
You'll need to do is deprecate onCreateHeaderViewHolder(ViewGroup parent)
and add a new method: onCreateHeaderViewHolder(ViewGroup parent, int viewType)
The viewType can be derived from the adapter like so:
mAdapter.getItemViewType(position);
This makes it consistent with the onCreateViewHolder(ViewGroup parent, int viewType)
method.
(As a side note, you should really add nullability annotations. Nice implementation otherwise!)
I set on my LinearLayout manager reverseLayout
to true
and sticky headers are not working.
I want to see headers acting same as reverseLayout
is set to false
.
Can anybody help with this?
private boolean StickyHeaderDecoration::hasHeader(int position)
should be protected,
so subclasses can define specific items (such as empty-views, special items or footers) to have no header.
How can I make the first item without header, then all else will contain header.
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:1976)
at android.view.ViewGroup.addView(ViewGroup.java:1871)
at android.view.ViewGroup.addView(ViewGroup.java:1828)
at android.view.ViewGroup.addView(ViewGroup.java:1808)
I have tried to implement your library, but adapters and recyclerview are very complex in my project and when I tried to add new code from your example it is really hard.
Maybe you should try to do something like this project: https://github.com/carlonzo/StikkyHeader just call one method and you get the header.
Thank you for your work.
Hi and thx for great lib, my issue is this:
I can't achieve elevation on headers although they are set in xml, headers are being rendered flat with z = 0 no matter what i do. Do you have any suggestion what to try?
Issue is manifested on Google Nexus 5X with Android 6.0.1 on it.
When i try to add LayoutAnimationController to the list(which has StickyHeaderDecoration), header views are not animated only child views are animated
So What when I use the library it seems that we can only make the textViews stick because it doesnt accept any other views. Am I doing something wrong or is the library designed that way?
when i use v0.2.8 and when i scrolling the recyclerview, the header of which item will attach the top is showing, the word(A,B,C,D...) will changing still.
but when i change to v0.2.6, this problem disappeared。
How can I add onClick
to views in the header? The findHeaderViewUnder
seems doesn't work most of the time even in your sample project. Specially after scrolling and having headers overlapped.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.