我有一个多租户应用,在用户登录后必须切换主题。
到目前为止,我所拥有的是,当用户已经登录并启动应用程序时,我在MainActivity OnCreate方法上调用setTheme()。
这正常工作,并且该应用以正确的主题显示。
但是,当用户未登录时,该应用程序将以默认主题启动。登录后,我可以识别用户并且必须更改主题。但是我该怎么做。登录过程不在android项目中,从那里我无权访问MainActivity。
如何设置新主题并重新创建应用程序?
我非常感谢您的帮助。
更新
目前,登录方法位于MC.Core(共享)(。NET Standard 2.0)库中,而MainActivity位于MC.Android库中。因此,有一个插件可以访问项目中的实际活动,但是我不能使用它,因为它确实支持.Net Standard。
如果我可以在两个项目上订阅一个活动,我也不愿意。如果可能的话,我该怎么办?
我的最后一个解决方案是将登录方法从核心项目移至Android项目。但是在这种情况下,我必须在每个平台上都实现这一点。
答案 0 :(得分:3)
要从网络标准项目中调用MainActivity中的方法,您需要将对MainActivity的引用传递给标准项目。最好的方法是将引用传递给共享网络标准项目App构造函数,该引用是从MainActivity调用的。当然,您不能在MainActivity类型的App构造函数中声明参数,因为您的网络标准项目无法引用Android项目,并且因为,如果将来您要实现iOS和/或UWP版本的应用,则需要这些不同项目之间的通用类型。
因此,您必须在网络标准项目中定义一个接口:
public interface IThemeChanger
{
void ApplyTheme(string newTheme);
}
然后,在Android项目中,使您的MainActivity实现此接口:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IThemeChanger
{
public void ApplyTheme(string newTheme)
{
if (newTheme?.ToLower() == "dark")
{
SetTheme(Resource.Style.Base_Theme_AppCompat);
}
else
{
SetTheme(Resource.Style.Base_Theme_AppCompat_Light);
}
}
并使其在应用类的构造函数中传递对自身的引用:
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App(this));
}
然后,在网络标准App类中,更改构造函数,使其接受IThemeChanger类型的参数,并将对它的引用存储在私有或公共字段中(取决于您是否需要从外部App访问它)课):
public readonly IThemeChanger ThemeChanger;
public App(IThemeChanger themeChanger)
{
InitializeComponent();
this.ThemeChanger = themeChanger;
MainPage = new MainPage();
}
然后,在登录页面中,用户成功登录后,相应地更改主题,例如:
((App.Current) as App).ThemeChanger.ApplyTheme("Dark");
如果您不直接实例化App类,而是使用依赖项注入容器,则将MainActivity的当前实例注册为容器的IThemeChanger接口的实现者,并在ViewModel的构造函数中简单地请求IThemeChanger实例。当然语法取决于所使用的DI容器,这是Caliburn.Micro SimpleContainer的示例:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IThemeChanger
{
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
var container = IoC.Get<SimpleContainer>();
if (container.HasHandler<IThemeChanger>())
{
container.UnregisterHandler<IThemeChanger>();
}
container.Instance<IThemeChanger>(this);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(container.GetInstance<App>());
}
在这种情况下,请注意,可以在应用恢复过程中创建MainActivity的新实例,因此您需要检查该接口之前是否可能进行了注册并取消注册。
在您的ViewModel中:
public class LoginViewmModel{
private readonly IThemeChanger themeChanger;
public LoginViewModel(IThemeChanger themeChanger){
this.themeChanger = themChanger;
}
private void ApplyTheme{
themeChanger.ApplyTheme("Dark");
}
}