【问题标题】:xamarin - Android change theme programmaticallyxamarin - Android 以编程方式更改主题
【发布时间】:2019-04-27 06:28:37
【问题描述】:

我有一个多租户应用,用户登录后必须切换主题。

到目前为止,当用户已经登录并启动应用程序时,我在 MainActivity OnCreate 方法上调用 setTheme()。

这工作正常,应用程序显示在正确的主题中。

但当用户未登录时,应用程序将以默认主题启动。登录后我可以识别用户并且必须更改主题。但我该怎么做。登录过程不在android项目中,从那里我无法访问MainActivity。

如何设置新主题并重新创建应用程序?

非常感谢您的帮助。

更新


登录方法目前在 MC.Core (Shared) (.NET Standard 2.0) 库中,而 MainActivity 在 MC.Android 库中。所以有一个插件,您可以访问项目的实际活动,但我不能使用它,因为它确实支持 .Net 标准。

如果我可以通过两个项目订阅一个事件,我并不担心。如果这是可能的,我该怎么做?

我最后的解决方案是将登录方法从我的核心项目移至 Android 项目。但在这种情况下,我必须为每个平台实现它。

【问题讨论】:

  • 登录过程不在项目中?它在哪里?如何判断用户已经登录?
  • 如果您在登录后触发一个事件,并在您的MainActivity 中订阅该事件以设置主题?
  • @Fuong 更新了描述

标签: xamarin xamarin.forms xamarin.android


【解决方案1】:

要从网络标准项目调用 MainActivity 中的方法,您需要将 MainActivity 的引用传递给标准项目。最好的方法是传递对共享网络标准项目 App 构造函数的引用,该构造函数是从 MainActivity 调用的。当然,您不能在您的 App 构造函数中声明 MainActivity 类型的参数,因为您的网络标准项目无法引用 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 实例,因此您需要检查该接口之前是否可能注册并取消注册。

在您的视图模型中:

public class LoginViewmModel{
    private readonly IThemeChanger themeChanger;

    public LoginViewModel(IThemeChanger themeChanger){
        this.themeChanger = themChanger;
    }

    private void ApplyTheme{
        themeChanger.ApplyTheme("Dark");
    }
}

【讨论】:

  • 很高兴能帮上忙 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-15
  • 1970-01-01
相关资源
最近更新 更多