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

Dynamically setting light/dark themes at runtime #19

Open
gaelian opened this issue Sep 2, 2021 · 2 comments
Open

Dynamically setting light/dark themes at runtime #19

gaelian opened this issue Sep 2, 2021 · 2 comments

Comments

@gaelian
Copy link

gaelian commented Sep 2, 2021

I'm currently trying to figure out how to get light/dark themes working with my full Elmish style Fabulous app (multi-page, somewhat following the composition model of the FabulousContacts example app). I've managed to get the themes sorted out, mainly by the F#-coded styling approach, plus some native styling that I needed to do in the Android project (via values and values-night, etc). The F# style code is simple, an excerpt example:

module Style =
    let isDarkTheme = Application.Current.RequestedTheme = OSAppTheme.Dark

    let TabBackgroundColor = if isDarkTheme then Color.FromHex("#2d2d30") else Color.FromHex("#f6f6f6")
    let TabUnselectedColor = if isDarkTheme then Color.FromHex("#d0d0d0") else Color.FromHex("#949594")

These values are used within the various view functions to set colours on elements.

The themes are working, except that I can't apply them at runtime, e.g. if the theme changes automatically due to time of day or if the user manually changes the theme while the app is still running. The theme is only set when the app starts. I was hoping to use the Application.Current.RequestedThemeChanged event to dispatch a message (in conjunction with the approach discussed under Triggering Commands from External Events) as I assumed that I would need to somehow trigger an update of the pages in the app for the F#-coded styling approach to work and reapply the different colours to the view elements. But as @TimLariviere mentions here, the Application.Current.RequestedThemeChanged event does not seem to fire.

If anyone could give any info or examples on how they have managed dynamically applying light/dark themes at runtime for Fabulous, that would be much appreciated.

@gaelian
Copy link
Author

gaelian commented Sep 9, 2021

For anyone coming across this in the future, I managed to get most of what I was hoping for by overriding OnResume(). For example:

type App () as app = 
    inherit Application ()

    let runner = 
        App.program
        |> XamarinFormsProgram.run app

    override this.OnResume () =
        runner.Dispatch App.Msg.RefreshTheme

@edgarfgp
Copy link
Member

edgarfgp commented Nov 9, 2021

@gaelian . I'm implementing a similar use case and what I end up doing was to :

  • Listen for the global theme changed event
    let runner =
    Program.mkProgram App.init App.update App.view
    |> XamarinFormsProgram.run app

    let onRequestedThemeChanged =
    EventHandler(fun _ args -> runner.Dispatch(Msg.AppThemeChanged args.RequestedTheme))

    override this.OnStart() =
    Application.Current.RequestedThemeChanged.AddHandler(onRequestedThemeChanged)`

  • The on the AppThemeChanged make and batch update to all the views to switch the styles to the respective theme
    | AppThemeChanged appTheme ->
    let loginAppThemeMsg =
    LoginPage.Msg.SetRequestedAppTheme appTheme

    let loanAppThemeMsg =
      LoanCommon.Msg.SetRequestedAppTheme appTheme
    
    let cmd =
      Cmd.batch [ Cmd.ofMsg (LoginPageMsg loginAppThemeMsg)
                  Cmd.ofMsg (NewLoanStepsMsg loanAppThemeMsg) ]
    
    model, cmd
    
  • You can find a sample on the AllControls sample https://github.com/fsprojects/Fabulous/blob/8bbb610a2bbfe239e175b8e25ac950d55ebc94f5/Fabulous.XamarinForms/samples/AllControls/AllControls/Samples/UseCases/AppTheming.fs#L7

  • To make sure the view are force be updated you need to add a property to all the model affected and use that in the view so the view will be forced to updated

@TimLariviere TimLariviere transferred this issue from fabulous-dev/Fabulous Jan 15, 2023
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