recyclerview-playground icon indicating copy to clipboard operation
recyclerview-playground copied to clipboard

Implement fixed headers for rows and columns

Open danielocampo2 opened this issue 7 years ago • 9 comments

Hi, first thanks for this playground around RecyclerView adapters. This and the talk are extremely useful resources.

I was thinking on modifying the FixedGridLayoutManager to support fixed headers for both columns and rows (would look something like this: https://github.com/InQBarna/TableFixHeaders) I wanted to know if you would have any advice on how to actually implement this or do you have any recommendation for it?

Thanks!

danielocampo2 avatar Jun 19 '17 00:06 danielocampo2

In case anyone is interested, I implemented this by creating a custom view that combines 3 recyclerviews with different layout managers. One for the row headers that uses a Vertical LinearLayoutManager, one for the column headers with a Horizontal LinearLayoutManager and one for the grid content, that uses this FixedGridLayoutManager. Scroll events of the different recycler views are synchronised.

danielocampo2 avatar Jul 08 '17 01:07 danielocampo2

@danielocampo2 how did you manage to synchronize the scrolling of all 3?

Jogan avatar Jul 29 '17 20:07 Jogan

@Jogan hey, sorry for the delay in the response, I did it with this library: https://github.com/stoyicker/AligningRecyclerView

I synched the vertical scrolling with recyclerview of the row headers and the horizontal scrolling with the recyclerview containing the column headers.

danielocampo2 avatar Aug 08 '17 09:08 danielocampo2

@danielocampo2 - I started to implement the same solution using the same library. But I'm running into issues when you fling the grid, where essentially, the "header recycler" scrolls to the end and then bounces back. Do you have those issues? I think there's a defect in the FixedGridLayoutManager, and I think I even know what's causing it (but I can't figure out how to fix it).

Bradleycorn avatar Jan 16 '19 21:01 Bradleycorn

Hey @Bradleycorn, this was quite some time ago and I am not working in that project anymore, but the issue I remember having was that the header recycler would be at a different column than the actual content. SInce this only happened when flinging, very fast and not all the time, we could just live with it. But I think the issue you mention is different. What do you think it's happening?

danielocampo2 avatar Jan 16 '19 21:01 danielocampo2

@danielocampo2 - That's essentially the same thing I'm running into. When you fling, the recycler using the grid layout goes to the end... The recycler with the header though winds up NOT at the end, and thus they are out of sync. If you watch it very closely and put in some debugging, you can see that the header actually does scroll to the end, but then at the end, the grid emits one last scroll back in the opposite direction, and so the header scrolls backward and winds up not at the end. It happens so fast that you don't really notice what's happening and it just looks like they get out of sync.

Bradleycorn avatar Jan 17 '19 13:01 Bradleycorn

I think I've even tracked down WHY it happens. When you fling (say horizontally), the Grid Manager's scrollHorizontallyBy method gets called with a dx indicating the number of pixels to scroll. Let's say it's 1000, and the child grid views are each 100px wide. The method does some math and then shifts the child views over by 1000px, and then calls fillGrid to fill in the remaining space. So it can fill in 10 columns worth of views. But if you look at fillGrid(), it ALWAYS increments the layoutmanger's "lastVisibleColumnm" by 1 (and only 1). Fling causes a bunch of scroll events in succession. When those next scroll events happen, and scrollHorizontallyBy does it's math, it thinks that the lastVisibleColumn is now 11, but really it's 20, so it starts accounting for extra space. The amount of extra space keeps accumulating. Tt finally figures out on the last scrollby that it's trying to layout view's out of bounds, and so it emits a value to try and scroll backwards the right amount to put the last column in the right place. The header recycler gets that, and it actually scrolls backward. Similarly, when you fling the header to the left, it has the opposite problem, where it only DECREASES the visibileColumn value by one, and you end up at the end with a big area of whitespace where it should've rendered views but thought that it had run out of space too soon.

With all of that said, I've never worked with LayoutManagers before, so I'm not sure how to properly fix it, or else I'd submit a PR.

Bradleycorn avatar Jan 17 '19 14:01 Bradleycorn

@Bradleycorn that's a good investigation. I haven't really worked much with LayoutManagers either so I don't think I can help in this one. I just saw that I actually created an issue long ago in that library, but I don't think it's being maintained at all: https://github.com/stoyicker/AligningRecyclerView/issues/3

Good luck.

danielocampo2 avatar Jan 17 '19 21:01 danielocampo2

@danielocampo2 - If you ever need it, I was able to fix the issue with the scroll amounts, and combine it with the stuff in the AligningRecyclerView repo, and create a fully functional "spreadsheet view" With Sticky row/column headers that stay in sync with the grid. Also converted everything to Kotlin 😋 See it in action here https://github.com/Bradleycorn/Spreadsheet

Bradleycorn avatar Jan 29 '19 03:01 Bradleycorn