Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it work for LinearLayout#HORIZONTAL as well. #10

Closed
cmcneil opened this issue Jun 5, 2015 · 6 comments
Closed

Make it work for LinearLayout#HORIZONTAL as well. #10

cmcneil opened this issue Jun 5, 2015 · 6 comments

Comments

@cmcneil
Copy link

cmcneil commented Jun 5, 2015

Hey!
Awesome project! I'm working on this issue. It's mostly just adding a bunch of switch statements :/. Is this a thing you want? https://github.com/cmcneil/DragLinearLayout

@justasm
Copy link
Owner

justasm commented Jun 5, 2015

Hi there, thanks!

I've never personally run into a use case where I needed a dynamic horizontal list; horizontal scrolling is typically reserved for ViewPager paging or gesture actions on list items. Could you elaborate on where / how you'd use this?

A few thoughts regarding the implementation:

  • it does add quite a lot of complexity to the class, so ideally the use case is compelling
  • ScrollView does not support horizontal scrolling, so we'd either also need to support HorizontalScrollView or not support scrolling parents in HORIZONTAL
  • setScrollSensitiveHeight / Width should probably just be consolidated to one
  • likewise for scrollSensistiveHeight / Width attributes
  • enforce the supported orientations in setOrientation() and then you won't have to 'flip out' / 'throw an error' 😄
  • I found 'thickness' quite amusing, but perhaps 'size' is clearer?

And I'm sure you were going to get around to these, but in case it's helpful:

  • the orientation is still hard-coded to VERTICAL
  • DragItem's mOrientation is not updated if setOrientation() is called on the layout

@cmcneil
Copy link
Author

cmcneil commented Jun 8, 2015

Hey!
Sorry for the slow response, I was moving this weekend.

  • "rare use case": Yea, I admit it's definitely a much rarer use case than the vertical one. I want to create a scrollable, horizontal shelf of items, and for these items to be easily re-orderable by the user. An example of an experience like this is the new Google Play Music app.(minus user drag and drop capability). I think that a construct like this is the right one, because what I want to achieve is exactly the behavior of your demo app, but rotated 90 degrees(multiple items visible on the shelf at once, the user can reorder them via drag and drop, and there is a smooth slide to offscreen items). I am new to android though, so if there is something more appropriate, let me know.
  • "parent scrolling in horizontal": Ah thank you, I wasn't aware of this. If I move forwards with my fork I'll attempt to support HorizontalScrollView.
  • "scrollSensitiveHeight" - It was on my todo list, I may have missed it. Thanks!
  • "throwing an error" - Yea, good point.
  • "thickness" - sure :P.

Last two:

  • yep, not finished yet, making a demo activity before I turn off the force VERTICAL.

Finally, I know this makes the code a bit messier, and I understand if you don't want to include this fork in the main project, as my UI need is maybe a bit unusual. (I do think doing this is pretty ideal for my use case, but if you know of a better way to accomplish the same thing, I'm listening). If that is the case, then thanks for the great starting point!

@justasm
Copy link
Owner

justasm commented Jun 8, 2015

So, I'm sure the fork will work for you, but if your UI consists only of a (potentially large) collection of items, DragLinearLayout may not be the ideal solution. A potentially large issue is performance - LinearLayout (and, by extension, this library) creates / inflates all its children on start. Smarter containers like the (now out-of-date) ListView and the (new hotness) RecyclerView actually recycle the Views that go off-screen and reuse them (populating them with new data so everything looks proper) with items that newly appear on-screen. If you have 10, 20 or 50 items there may be little difference. But if you have 1000 list items, lower-end devices will not be able to deal with it. Of course, even with 10 items, if you only ever see 3 on screen it is still more efficient and appropriate to use a recycling container. The recycling containers however are more complicated and handle their own scrolling - they cannot be placed alongside other children inside a ScrollView. This is the primary use case for DragLinearLayout - a relatively small number of draggable Views, inside a ScrollView container, alongside non-draggable children, with minimal hassle. Sorry if the main README does not articulate that clearly enough, I'm open to suggestions on improving the messaging.

So I haven't taken the time to figure out exactly what Play Music is doing (which you could), but if I had to guess I'd wager they're using a RecyclerView with a horizontal LinearLayoutManager. This alone will give you efficient layout, scrolling and display as in Play Music. You could then use another library like DragSortAdapter to add drag support. Thankfully for you, just last week it added support for horizontal layouts. Note that I haven't had the chance to use DragSortAdapter myself, but its documentation seems reasonable. There's a guide here for an alternative custom implementation if DragSortAdapter is not working out.

Using a RecyclerView may make it simpler to change your layout in the future and / or more easily adapt to different screen sizes, if you choose to do so. But if you only have a small fixed set of items, your fork of DragLinearLayout may do the job. It's your call to evaluate the trade-offs - good luck and let me know how it goes 👍

@cmcneil
Copy link
Author

cmcneil commented Jun 23, 2015

Hey justasm!
Sorry I dropped off the face of the earth for a bit. Moving and work and whatnot. Well, I picked it back up today, and got it working, just for completeness. I support HorizontalScrollView(which I may not even end up using) with a crazy Duck-typing-based-on-reflection trick I found. (http://thinking-in-code.blogspot.com/2008/11/duck-typing-in-java-using-dynamic.html My Python background is showing :P) This is definitely hacky, but I really feel it's weird that HorizontalScrollView and ScrollView share so much, yet don't have a shared interface or parent with much of their functionality. Is that weird, or is this usual for Android?

DragSortAdapter does look like it's probably the more correct way to go about things, but honestly at this point I think I'll use my fork because it's already working. I'm not worried about performance, as I expect the case where the items go offscreen to be a pretty rare one. (common case of around 3 items)

Thanks again for all of the tips! (Definitely checking out the HierarchyViewer) :D

@justasm
Copy link
Owner

justasm commented Jun 23, 2015

Reflection is Java's hammer that makes every problem a nail.. Good to hear that it worked out for you, but you're right in that it's absolutely a hack :) It is weird that there's no common interface but Android's API is hit and miss quality-wise, each View itself has some sense of the concept of scrolling, etc.

Best of luck on your Android adventures!

@justasm justasm closed this as completed Jun 23, 2015
@justasm
Copy link
Owner

justasm commented Jun 23, 2015

Actually, just thinking about it - haven't actually given this a go - you could probably just accept a View (in your case you can assume it will always be a ScrollView or HorizontalScrollView) and use its scrollBy() method instead of smoothScrollBy() to achieve similar results without needing reflection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants