[xamarin]如何在ios的darkmode裡面正常顯示文字

  • 299
  • 0
  • 2020-03-17

[xamarin]如何在ios的darkmode裡面正常顯示文字

首先在app.xaml.cs新增一個全域變數

public static string AppTheme
{
	get; set;
}


然後在你所有在dark mode會文字消失看不見的.xaml裡面的任何label或text設定如下:(設定會消失的就好,其他的不要亂設定)
一般的label就加上DynamicResource TextPrimaryColor資源來設定文字顏色
一般的editor就一樣加上DynamicResource TextPrimaryColor資源來設定文字顏色
有FormattedText的label什麼都不用加,但是要確認裡面的span text一定要有隨便一個字串(這邊是加入一個點".")
ps.DynamicResource TextPrimaryColor這個資源等等會加入,稍候步驟便知

<Label Grid.Row="0" Grid.Column="1"
   Text="{Binding Name}" TextColor="{DynamicResource TextPrimaryColor}"
   FontAttributes="Bold" FontSize="Subtitle" />
<Editor Placeholder="請輸入路線名稱" Text="{Binding Name}"
	 HeightRequest="50" IsReadOnly="True" x:Name="txtName"
	   TextColor="{DynamicResource TextPrimaryColor}" />
<Label x:Name="lblCons" HorizontalOptions="Start" VerticalOptions="CenterAndExpand">
	<Label.FormattedText>
		<FormattedString>
			<Span Text="." />
		</FormattedString>
	</Label.FormattedText>
</Label>					   


再來到你的 方案名稱.ios專案裡面,加入一個Renderers資料夾,並加入一個PageRenderer類別,類別內容如下:
ps. namespace記得改成自己專案的喔

using System;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using BikeNavLuzhou.Styles;

[assembly: ExportRenderer(typeof(ContentPage), typeof(BikeNavLuzhou.iOS.Renderers.PageRenderer))]
namespace BikeNavLuzhou.iOS.Renderers
{
    public class PageRenderer : Xamarin.Forms.Platform.iOS.PageRenderer
    {
        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null || Element == null)
            {
                return;
            }

            try
            {
                SetAppTheme();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"\t\t\tERROR: {ex.Message}");
            }
        }

        public override void TraitCollectionDidChange(UITraitCollection previousTraitCollection)
        {
            base.TraitCollectionDidChange(previousTraitCollection);

            double currentIosVersion = 12;
            try
            {
                currentIosVersion = Convert.ToDouble(UIDevice.CurrentDevice.SystemVersion.Substring(0, 2));
            }
            catch
            {
                //do nothing
            }
            

            if (currentIosVersion >= 13)
            {
                //dark mode只有在ios13以上才有
                //不能讓未滿ios13的近來這邊 會當機 因為previousTraitCollection會是null
                Console.WriteLine($"TraitCollectionDidChange: {TraitCollection.UserInterfaceStyle} != {previousTraitCollection.UserInterfaceStyle}");

                if (this.TraitCollection.UserInterfaceStyle != previousTraitCollection.UserInterfaceStyle)
                {
                    SetAppTheme();
                }
            }


        }

        void SetAppTheme()
        {
            if (this.TraitCollection.UserInterfaceStyle == UIUserInterfaceStyle.Dark)
            {
                if (App.AppTheme == "dark")
                    return;
                //Add a Check for App Theme since this is called even when not changed really
                App.Current.Resources = new DarkTheme();

                App.AppTheme = "dark";
            }
            else
            {
                if (App.AppTheme != "dark")
                    return;
                App.Current.Resources = new WhiteTheme();
                App.AppTheme = "light";
            }
        }
    }
}


再來到 方案名稱\專案名稱 底下新增一個Styles資料夾,並依序加入DarkTheme.xaml, DarkTheme.xaml.cs, WhiteTheme.xaml, WhiteTheme.xaml.cs,每個檔案內容依序如下:(檔案內容裡面的專案名稱記得要改成自己的)

DarkTheme.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="BikeNavLuzhou.Styles.DarkTheme">

    <Color x:Key="backgroundColor">#FF000000</Color>
    
    <Color x:Key="TextPrimaryColor">#B0FFFFFF</Color>
    <Color x:Key="TextSecondaryColor">#B0FFFFFF</Color>
    <Color x:Key="TextTernaryColor">#C8C8C8</Color>
</ResourceDictionary>


 DarkTheme.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace BikeNavLuzhou.Styles
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class DarkTheme : ResourceDictionary
    {
        public DarkTheme()
        {
            InitializeComponent();
        }
    }
}


WhiteTheme.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="BikeNavLuzhou.Styles.WhiteTheme">

    <Color x:Key="backgroundColor">#FFFFFFFF</Color>

    <Color x:Key="TextPrimaryColor">#B0000000</Color>
    <Color x:Key="TextSecondaryColor">#80000000</Color>
    <Color x:Key="TextTernaryColor">#C8C8C8</Color>
</ResourceDictionary>


WhiteTheme.xaml.cs:
 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace BikeNavLuzhou.Styles
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class WhiteTheme : ResourceDictionary
    {
        public WhiteTheme()
        {
            InitializeComponent();
        }
    }
}


這樣子就OK了,dark mode執行結果如下


這篇大概先這樣囉~


參考資料:
How To Support Dark Mode In Xamarin.Forms (iOS & Android)
https://intelliabb.com/2019/11/02/how-to-support-dark-mode-in-xamarin-forms/
Modernizing iOS Apps for Dark Mode with Xamarin
https://devblogs.microsoft.com/xamarin/modernizing-ios-apps-dark-mode-xamarin/