Reputation: 33
i am making an app using xamarin.forms and i have set up a color scheme that i want to be able to change within the settings to either a dark style or a light style right now it all works except i have to restart the app everytime after i select a different color scheme.
here is where i am trying to change it at runtime
private void DarkThemeClick(object sender, EventArgs e)
{
database.DropTable(new StyleModel());
database.CreateTable(new StyleModel());
database.SaveItem(new StyleModel() { ThemeNum = 1 });
App.ActiveStyle = new DarkStyle();
}
private void LightThemeClick(object sender, EventArgs e)
{
database.DropTable(new StyleModel());
database.CreateTable(new StyleModel());
database.SaveItem(new StyleModel() { ThemeNum = 0 });
App.ActiveStyle = new LightStyle();
}
here is an example of an item that im using that i want to change the colors on
using System;
using TestXamForms.Style;
using Xamarin.Forms;
namespace TestXamForms.Helpers
{
class EntryValueCell : StackLayout
{
public EntryValueCell(string key,int FieldIdx, string value = "", bool isNumber = false)
{
Entry entry;
Label label = new Label()
{
TextColor = App.ActiveStyle.LabelTextColor,
Text = key,
HorizontalOptions = LayoutOptions.End
};
if (isNumber)
{
entry = new Entry()
{
ClassId = FieldIdx.ToString(),
TextColor = App.ActiveStyle.LabelTextColor,
HorizontalOptions = LayoutOptions.FillAndExpand,
Keyboard = Keyboard.Numeric,
Text = value,
};
}
else
{
entry = new Entry()
{
ClassId = FieldIdx.ToString(),
TextColor = App.ActiveStyle.LabelTextColor,
HorizontalOptions = LayoutOptions.FillAndExpand,
Keyboard = Keyboard.Text,
Text = value
};
}
BackgroundColor = App.ActiveStyle.StackLayoutBackground;
Orientation = StackOrientation.Horizontal;
VerticalOptions = LayoutOptions.FillAndExpand;
Children.Add(label);
Children.Add(entry);
}
}
}
here is an example of one of the color schemes
using Xamarin.Forms;
namespace TestXamForms.Style
{
public class LightStyle : StyleBase
{
public LightStyle()
{
LabelTextColor = Color.Black;
ButtonColor = Color.FromHex("337ab7");
StackLayoutBackground = Color.FromHex("eff0f1");
InputBackgroundColor = Color.White;
PlaceHolderColor = Color.Gray;
TableColor = Color.FromHex("e6e6e6");
StacklayoutBorderColor = Color.Black;
}
}
}
here is styleBase that the file above is inheriting
using TestXamForms.Models;
using Xamarin.Forms;
namespace TestXamForms.Style
{
public class StyleBase : ModelBase
{
public enum ThemeNum : int
{
Light = 0, Dark = 1
}
public Color LabelTextColor { get; set; }
public Color ButtonColor { get; set; }
public Color StackLayoutBackground { get; set; }
public Color InputBackgroundColor { get; set; }
public Color PlaceHolderColor { get; set; }
public Color StacklayoutBorderColor { get; set; }
public Color TableColor { get; set; }
public int ThemeNums { get; set; }
}
}
here is the part of App.cs file that loads the color scheme when the app starts
static StyleBase activeStyle { get; set; }
public static StyleBase ActiveStyle
{
get
{
if (activeStyle == null)
{
StyleModel styleBase = database.GetItems(new StyleModel()).First();
if (styleBase == null)
{
database.SaveItem(new StyleModel() { ThemeNum = 0 }); //sets the default color scheme to light style
styleBase = database.GetItems(new StyleModel()).First();
}
int themeNum = styleBase.ThemeNum;
switch (themeNum)
{
case (int)StyleBase.ThemeNum.Dark:
activeStyle = new DarkStyle();
break;
case (int)StyleBase.ThemeNum.Light:
activeStyle = new LightStyle();
break;
}
}
return activeStyle;
}
set { } }
Upvotes: 3
Views: 6312
Reputation: 11787
The problem you are facing is that everything is already rendered and you have not bound to any property which will re render the changes you made in the code to the UI. You can take the MVVM approach and create properties and bind to them and notify when they are changed in the UI thread.
If you are interested only in dark and light themes then you can use the in built Light Theme and Dark Theme. You can also create Custom Themes.
A theme is added to a Xamarin.Forms application by including the Xamarin.Forms.Theme.Base Nuget package, plus an additional package that defines a specific theme (eg. Xamarin.Forms.Theme.Light) or else a local theme can be defined for the application.
In addition to automatically styling the common controls the Light and Dark themes currently support the following classes that can be applied by setting the StyleClass on these controls:
BoxView - HorizontalRule, Circle, Rounded
Image - Circle, Rounded, Thumbnail
Button - Default, Primary, Success, Info, Warning, Danger, Link, Small, Large
Label - Header, Subheader, Body, Link, Inverse
To add a theme to your application, do the following :
Add the Nuget packages to your project.
Add theme to Resource Dictionary in App.xaml
Use the Style class to apply predefined style classes in the theme.
<Button Text="Button Class Default" StyleClass="Default" />
<Button Text="Button Class Primary" StyleClass="Primary" />
<Button Text="Button Class Success" StyleClass="Success" />
Read more about themes here.
Upvotes: 1
Reputation: 993
Have a look at this blog post. Particularly the bit about DynamicResources
and Styles
.
<Application
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Your.App">
<Application.Resources>
<ResourceDictionary>
<Color x:Key="backgroundColor">#33302E</Color>
<Color x:Key="textColor">White</Color>
</ResourceDictionary>
</Application.Resources>
</Application>
Now set your resources
<Label Text="{Binding Name}" FontSize="Medium" FontAttributes = "Bold" TextColor = "{DynamicResource textColor}" LineBreakMode="NoWrap"/>
<Label Text="{Binding Text}" FontSize="Small" LineBreakMode="WordWrap" TextColor = "{DynamicResource textColor}"/>
Now in code you can change your resource on the fly
App.Current.Resources ["backgroundColor"] = Color.White;
App.Current.Resources ["textColor"] = Color.Black;
If you're using 2.3 you could also try the built in themes
Upvotes: 3