bluelinelabs / Conductor

A small, yet full-featured framework that allows building View-based Android applications
Apache License 2.0
3.9k stars 344 forks source link

Stackless Conductor #450

Open cbnewham opened 6 years ago

cbnewham commented 6 years ago

Hi,

I'm wondering why you have effectively enforced a stack architecture for Conductor? I know you've done this for handling the back button and history, but I have an app which has just a series of tabs which the user can switch between (this is a custom tab setup - not an Android TabLayout as seen in the Conductor Demo). So, there is no need for the back button and view history.

I've got around the problem by getting the stack from the Router, reordering it, and putting it back. But surely there is a nicer solution?

EricKuck commented 6 years ago

There's no real overhead from having the backstack. What's the harm in having it? If you're effectively discarding the router altogether you're not really getting anything from Conductor and might as well just use custom views.

cbnewham commented 6 years ago

Yes, but you have the transition handled nicely and the fact you manage the controllers and their connection to the views. Why can't a router also be just a collection where I can specify the next view I want to display, which may not be in stack order as it currently is?

Just curious. I'm not being critical of Conductor - I think it's great. Thanks for all your work on it.

EricKuck commented 6 years ago

Gotcha, I think I misunderstood how you were using it initially. While there aren't any technical issues with having a router that functions the way you're looking for, it would add quite a bit of complexity to the API in exchange for little gain. The setBackstack method should actually do exactly what you want, including all transition animations. If you're not happy with how dirty the code looks, how about just making a utility/extension method like setFrontController(Controller, ControllerChangeHandler) that would just reorder the backstack for you?

cbnewham commented 6 years ago

OK, that sounds fine. I was just worried I was subverting things. I also want to use the router for some screens that do have a stack-like behaviour, so this will work ok in using setBackstack for the parts of my app that don't.

Thanks for taking the time to answer my query. Much appreciated.

EricKuck commented 6 years ago

It is kind of subverting things, but it's fully supported. All of the backstack-changing methods (ex: pushController, popController, etc) all use the setBackstack method internally anyway, so it should all work with no issues.

BrendonW commented 6 years ago

I'm toying with adding some sort of stash(), stash(<controller tag>), and unstash(<controller tag> that could be used to keep a set of "same level controllers" around while keeping them off the backstack. In order, they would remove the top controller without destroying in, remove a controller with a tag and put a previously stashed controller onto the top of the stack. For completeness I'd probably add <list> getStash() and clearStash(). Or something like that to avoid awkward edge cases.

That would allow easy implimentation of horizontal swipe between controllers without needing to do any dancing around in the backstack which really does not represent the way things are logically organized.

If there is no interest, I'll just keep my own version... but am happy to refine and share if there is interest.

cbnewham commented 6 years ago

I ended up just making a ConductorUtils class with method:

public static void bringToFront(Router router, Class controllerClass)

which just re-orders the internal Conductor list using the get and set Backstack methods as mentioned above.

This has worked out extremely well for my UI which just has a series of tabs for the different main sections of the app. I have no need for the backbutton in this scenario as it wouldn't make any sense - the tabs all being peers. I can still push other "off-tab" screens onto the stack and remove them with the backbutton (or a close button) if required, leaving the underlying core tabs untouched.

My tabs don't allow swipe to tab operations because some have swipe-able content.

mradzinski commented 5 years ago

Hey @BrendonW, just wondering, what's your use case for having "same level controllers" around while keeping them off the backstack?

If its creating some sort of "snapped carousel" where you can horizontally swipe, then having a backstack actually helps a lot. Detecting left and right swipe gestures and using pushController and popController appropriately should very much suffice.

Quite intrigued about your use case, maybe I didn't get what you meant by stash and how it can help having controllers out of the stack.