前段时间,我的门业APP审核被拒,苹果审核团队说APP在登录的时候显示有问题。
We discovered one or more bugs in your app. Specifically, your app displayed an error message during the login.
还附了一张截图给我,
咦,账号密码输入框的提示怎么不见了?不应该呀?我这里都好好的呀。
是不是苹果那边审核团队的手机有问题?难道是我们Delphi支持新版的IOS不够完善?
这个输入框如果没有输入内容,那么至少“请输入验证码”这些提示应该在的吧。现在提示都没有显示,说明是输入了内容的。
那文本框的内容怎么变成透明了呢?再一想,会不会是文本框的字体颜色变成了白色了?难道是最近苹果系统出的暗黑模式搞的鬼?
说完,在测试手机上开启暗黑模式:
果不其然!问题重现了!
那怎么办?难道我得把我的APP也跟着苹果一样搞个深色主题?那工作量还是有点大的,怎么办?客户急着用,APP得赶紧更新上去才行呀。
如何解决呢?在暗黑模式下,字体是如何变成白色的呢?或者说,Edit如何被切换成黑底白字的样式的呢?
这些都是FireMonkey自动处理的。自从苹果13.0系统出了深色主题之后,FireMonkey也做了相应的处理。
首先FMX.Platform.pas中定义了IFMXSystemAppearanceService 接口:
/// <summary>Service provides information about operation system theme.</summary>
IFMXSystemAppearanceService = interface
[‘{AB6A83D9-0118-4C5F-95CC-351DBB5EA943}’]
/// <summary>Returns system theme kind.</summary>
function GetSystemThemeKind: TSystemThemeKind;
/// <summary>Returns system color for specified type.</summary>
function GetSystemColor(const AType: TSystemColorType): TAlphaColor;
/// <summary>System theme kind.</summary>
property ThemeKind: TSystemThemeKind read GetSystemThemeKind;
end;
这个接口用于实现在每个平台下能获取当前系统的样式信息,比如样式类型,是浅色样式还是暗黑样式,还有就是系统主题颜色。
每个平台的TPlatform*****类都要实现IFMXSystemAppearanceService接口,
比如IOS平台,是在FMX.Platform.iOS.pas中的TPlatformCocoaTouch被实现的:
function TPlatformCocoaTouch.GetSystemThemeKind: TSystemThemeKind;
begin
case GetUserInterfaceStyle of
UIUserInterfaceStyleLight:
Result := TSystemThemeKind.Light;
UIUserInterfaceStyleDark:
Result := TSystemThemeKind.Dark;
else
Result := TSystemThemeKind.Unspecified;
end;
end;
那只只要根据SystemThemeKind搜索代码,Delphi肯定在某个地方根据SystemThemeKind来决定用什么样式,太简单了!
可是,我在Delphi的代码中找了半天,没有发现它在哪里切换的样式,只是在IOS下面,发现在TFMXViewController.traitCollectionDidChange事件中发送了样式切换消息TStyleChangedMessage以及系统主题样式更改消息TSystemAppearanceChangedMessage:
procedure TFMXViewController.traitCollectionDidChange(previousTraitCollection: UITraitCollection);
var
Message: TSystemAppearanceChangedMessage;
begin
UITraitEnvironment(Super).traitCollectionDidChange(previousTraitCollection);
TMessageManager.DefaultManager.SendMessage(nil, TStyleChangedMessage.Create(nil, nil), True);
PlatformCocoaTouch.WindowManager.UpdateStatusBar;
Message := TSystemAppearanceChangedMessage.Create(TSystemAppearance.Create, True);
TMessageManager.DefaultManager.SendMessage(nil, Message, True);
end;
难道我关键词找错了?
在TPlatformCocoaTouch.GetSystemThemeKind方法中它是调用的GetUserInterfaceStyle函数返回系统主题样式,那么Delphi是不是直接使用这个方法来判断使用的样式呢?
果然,在FMX.Controls.iOS单元中发现了关键的代码:
首先,这个单元定义了两个样式,
const
iOSLightStyle = ‘iosstyle’;
iOSDarkStyle = ‘ios13darkstyle’;
iosstyle表示浅色样式,而ios13darkstyle则就是暗黑样式的名称了,
然后又定义了一个iOSStyleSelection方法,根据当前的系统样式来返回对应的FireMonkey样式名称。
function iOSStyleSelection(const APlatform: TOSPlatform): string;
begin
{$IFDEF WIN32}
Result := iOSLightStyle;
{$ELSE}
if GetUserInterfaceStyle = UIUserInterfaceStyleDark then
Result := iOSDarkStyle
else
Result := iOSLightStyle;
{$ENDIF}
end;
再继续摸,会发现iOSStyleSelection这个方法是在FMX.Styles.pas中被调用的,
TStyleManager.StyleResourceForContext会返回当前的样式名称,:
class function TStyleManager.StyleResourceForContext(const Context: TFmxObject): string;
var
DeviceInfo: IDeviceBehavior;
OSPlatform: TOSPlatform;
PlatformSelection: TPlatformStyleSelectionProc;
begin
if TBehaviorServices.Current.SupportsBehaviorService(IDeviceBehavior, DeviceInfo, Context) then
OSPlatform := DeviceInfo.GetOSPlatform(Context)
else
raise EStyleException.CreateRes(@SNoIDeviceBehaviorBehavior);
if (FSelections <> nil) and FSelections.TryGetValue(OSPlatform, PlatformSelection) then
Result := PlatformSelection(OSPlatform)
else
Result := FindDefaultStyleResource(OSPlatform);
end;
然后TStyleManager.ActiveStyle从资源中加载出样式并返回:
class function TStyleManager.ActiveStyle(const Context: TFmxObject): TFmxObject;
var
StyleResource: string;
begin
StyleResource := StyleResourceForContext(Context);
Result := GetStyleResource(StyleResource);
end;
我有点好奇想看看这个样式,尝试将这个样式资源取出来,并将它保存到C盘:
报错了,
那应该是样式在Windows下没有编译进去,我想应该是一个res文件,所以我在安装目录搜,
1.72M,体积还蛮大,应该就是它了,
用{$R FMX.Controls.iOS.res}将这个资源编译进去
这次可以了,
用记事本打开看一下,
看着里面一堆控件样式的名字,那应该是对了,
再在窗体上放一个TStyleBook组件,加载这个样式文件,看看是什么样式的,
找到Edit的样式“editstyle”,背景是黑的,那就是了!
那么Edit的字体颜色是受样式中哪个元素控制的呢?
看了一下StyleEdit的代码,
默认,文本框Edit的默认字体颜色是取的样式中foreground元素的画刷颜色,
我们在StyleBook中来看一下这个foreground元素,
字体原来就是这么变白的。
那么如何解决这个问题呢?那就让Edit的字体颜色不受style控制就行了,去掉Edit.StyledSettings中的FontColor的勾即可。
好了,问题搞定,提交审核,等苹果审核通过即可。
下面放几张截图吧,OrangeUI开发的一款门业助手APP:
打算使用Delphi开发APP的朋友,欢迎加入我的QQ群10900297,来一起交流学习: