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

Don't remove view on push #141

Open
manueldidonna opened this issue May 26, 2019 · 14 comments
Open

Don't remove view on push #141

manueldidonna opened this issue May 26, 2019 · 14 comments
Labels
type:question A question about Acorn

Comments

@manueldidonna
Copy link

Is it possible to push a scene on top of another without removing other views from the parent?

I use a custom horizontal draggable view and while sliding users must see the view below

@nhaarman nhaarman added the type:question A question about Acorn label May 27, 2019
@nhaarman
Copy link
Owner

nhaarman commented May 27, 2019

You can have a look at the experimental ConcurrentPairNavigator, which allows a second Scene to be pushed on top of the initial Scene, and have both Scenes active at the same time.

It is considered experimental because it requires quite a bit of boilerplate: you must implement your layouts twice to account for transitions and configuration changes, and you need to define a SceneTransition for the transitions - which I'm not really happy about yet.

The page linked above shows a detailed example of how you could realise this.


This is assuming the draggable view is something that is added as a result of a navigation action. If you want to have multiple Scenes on a single screen, you can 'just' create the two Scenes separately (without any view providing) and create a third Scene that is used to provide the view and delegates the lifecycle methods to the first two Scenes. See #10 for a discussion on this.

@manueldidonna
Copy link
Author

What I need is a similar behaviour to fragment navigation with replace/add instead of push (with Stack navigator) or something like Conductor where the backstack could be manipulated with push & pop functions but you can decide to don't remove other controllers' view


The draggable view is the default layout of every scene (except the root one)

@nhaarman
Copy link
Owner

nhaarman commented May 31, 2019

I'm still not really sure I fully grasp your use case, but here are some thoughts.

Acorn's perspective on app navigation is to have navigational state completely decoupled from the UI. The UI observes changes in the navigation state and reacts appropriately by displaying the right View elements. This means that all information necessary must be available in that navigational state; if multiple Scenes need to provide the data for that draggable view, then they must all do that individually. At least that is how the ext artifacts are designed.

Something different that could be possible, but which isn't directly 'supported' by the library through default implementations, is to have two separate Navigators running in parallel: one for the main navigation, one for the 'draggable view'. The Activity could then subscribe to both Navigators and deal with the layout. However this is completely uncharted territory, so you might run into some problems to get things to work there.

@nhaarman
Copy link
Owner

nhaarman commented May 31, 2019

You could also completely disregard the 'draggable view' from your main navigation flow and let the default Acorn implementations do the main navigation for you. Then inflate a custom layout in your Activity that contains the draggable view and pass a container layout to Acorn:

<FrameLayout>
   <FrameLayout id="@+id/contentLayout" />
   <MyDraggableView />
</FrameLayout>
class MyActivity: AcornAppCompatActivity() {

  override fun onCreate(bundle: Bundle?) {
     setContentView(R.layout.activity_main)
     super.onCreate(bundle)
   }

   override fun provideRootView() : ViewGroup {
      return findViewById<ViewGroup>(R.id.contentLayout)
    }
}

Then do some extra work to make your draggable view work as you want it to. You could add an extra listener to your navigator to be able to hide and show it based on your requirements. This is just some spitballing here though.

@manueldidonna
Copy link
Author

I took a look to samples & android-ext impls. UI reacts to a navigation event displaying the right contents with a transition and there are some navigator implementations. Right?

I'm interested in the StackNavigator class. It has a 'push' function that accepts a scene. If I understood the UI linked to the given scene replaces the current scene's UI and the current scene is stopped.
I don't want to remove the current UI, I want both in the same container. Is it possible?

@nhaarman
Copy link
Owner

nhaarman commented Jun 1, 2019

I don't want to remove the current UI, I want both in the same container

Sure, implement a custom SceneTransition that leaves the shared view intact.

@NickvanDyke
Copy link

Would this be the proper way to implement dialogs as Scenes too? In the ViewController, create an AlertDialog, passing it the view, and use a SceneTransition that doesn't remove the view/scene that's underneath? Initially I was going to use ConcurrentPairNavigator, but that seems wrong for this since we couldn't make the dialog part of the layout file that needs to contain the entirety of both Scenes.

@nhaarman
Copy link
Owner

@NickvanDyke What kind of dialog do you need?

@NickvanDyke
Copy link

NickvanDyke commented Jun 13, 2019

@nhaarman The view would be wrapped in an AlertDialog. So far, it seems the proper way to do this would be to create and show an AlertDialog in the ViewController's init, calling AlertDialog.setView(view) with the view that the ViewController receives in its constructor. And then use a SceneTransition that doesn't remove the view underneath, and doesn't add the new ViewController's view to the parent and doesn't do any animating, since showing the dialog will take care of that. And in detach of the ViewController's Scene, call a method on the ViewController that dismisses the dialog. Does that sound right?

@nhaarman
Copy link
Owner

Interesting approach! I'd have to look into this a bit more, for example to properly deal with configuration changes and such.

@NickvanDyke
Copy link

I'll give it a shot and report back. I used a similar approach with Conductor and it worked well

@manueldidonna
Copy link
Author

manueldidonna commented Dec 27, 2019

Hello guys! I finally get the time to build a fully fledged note taking app with acorn (that I love to use) but I still need to wrap a view in a bottom sheet which is a slideable ViewGroup. I don't know which is the best way to handle the view inflation on configuration changes.

Here is my use case:

  • Root Scene (A)
  • I push Scene B without removing Scene A view. Scene B view is wrapped in a bottom sheet.

What will happen on configuration change?

  • Scene B will be inflated and added to an empty parent ViewGroup but scene A won't be inflated because the scene on top of the stack is B and not A.

Here is what I thought to do

  • Scene B implements a particular interface (ex: BottomSheetScene).
  • When the stack need to be restored, a special navigator will return the first scene in the stack that don't implements that interface.
  • All the subsequent BottomSheetScene's will be added on top of the normal scene.

Tell me if there's a better way to handle this sort of things. I hope to share a gist with a working code in the next weeks. I really appreciate all the work that Niek Haarman has done!

@NickvanDyke
Copy link

NickvanDyke commented Dec 27, 2019

@manueldidonna What I've done in this case is make Scene B nested within Scene A - i.e. A retains a reference to B, and forwards its lifecycle callbacks to B, including attach/detach. It also saves and restores B's state when its own is. Then, the layout that is inflated for A also has B's views in it. A's viewcontroller also instantiates B's view controller, passing to it the part of its layout that belongs to B. It also makes B's view controller available to Scene A, so that it can call attach/detach on Scene B.

This way, you can still separate logic into Scene B, but don't need to fuss with properly re-inflating views since Scene A contains the views for both itself and Scene B.

@manueldidonna
Copy link
Author

@NickvanDyke thanks. I will update this issue as soon as I have some working code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:question A question about Acorn
Projects
None yet
Development

No branches or pull requests

3 participants