在Xamarin.iOS中存在一些缺失的UIAppearance
功能,就你的问题而言,有一个缺失的API。
- 这是一个bug,我编写了自己的
UIAppearance.cs
以添加缺失的功能并修正了缺失的API,并且假设没有其他Xamarin.iOS开发人员真正使用更新的UIAppearance
功能,因为它从iOS 9开始就已经损坏了。
首先,appearanceWhenContainedIn
已被弃用,您应该使用appearanceWhenContainedInInstancesOfClasses
代替。
AppearanceWhenContainedIn - 在iOS 9中已弃用,不建议使用。
其次,appearanceWhenContainedInInstancesOfClasses
在Xamarin.iOS
中被错误地定义为仅在tvOS
中可用,但这并不正确。
#if TVOS
// new in iOS9 but the only option for tvOS
const string selAppearanceWhenContainedInInstancesOfClasses = "appearanceWhenContainedInInstancesOfClasses:";
~~~
UIAppearance.cs#L77
因此,它在Xamarin.iOS包装API中不可用,但当然可以直接从ObjC运行时中获得:
var NSForegroundColorAttributeName = Dlfcn.GetStringConstant(UIKitLibraryHandle, "NSForegroundColorAttributeName");
var defaultAttributes = NSDictionary.FromObjectsAndKeys(new NSObject[] { UIColor.Red }, new NSObject[] { NSForegroundColorAttributeName });
var styleHandle = GetAppearanceEx(Class.GetHandle("UITextField"), typeof(UISearchBar));
void_objc_msgSend_IntPtr(styleHandle, Selector.GetHandle("setDefaultTextAttributes:"), defaultAttributes.Handle);
![enter image description here](https://istack.dev59.com/xYMJD.webp)
下一个问题是有许多被标记为“internal”的Xamarin.iOS方法需要用于上述代码的功能,因此需要一些源代码的复制/粘贴/修改:
public const string selAppearanceWhenContainedInInstancesOfClasses = "appearanceWhenContainedInInstancesOfClasses:";
public static readonly IntPtr UIKitLibraryHandle = Dlfcn.dlopen("/System/Library/Frameworks/UIKit.framework/UIKit", 0);
[DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")]
public static extern IntPtr IntPtr_objc_msgSend_IntPtr(IntPtr receiver, IntPtr selector, IntPtr arg1);
[DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")]
public static extern void void_objc_msgSend_IntPtr(IntPtr receiver, IntPtr selector, IntPtr arg1);
public static IntPtr GetAppearanceEx(IntPtr class_ptr, params Type[] whenFoundIn)
{
var ptrs = TypesToPointers(whenFoundIn);
var handles = NSArray.FromIntPtrs(ptrs);
using (var array = handles)
{
return IntPtr_objc_msgSend_IntPtr(class_ptr, Selector.GetHandle(selAppearanceWhenContainedInInstancesOfClasses), array.Handle);
}
}
public static IntPtr[] TypesToPointers(Type[] whenFoundIn)
{
IntPtr[] ptrs = new IntPtr[whenFoundIn.Length];
for (int i = 0; i < whenFoundIn.Length; i++)
{
if (whenFoundIn[i] == null)
throw new ArgumentException(String.Format("Parameter {0} was null, must specify a valid type", i));
if (!typeof(NSObject).IsAssignableFrom(whenFoundIn[i]))
throw new ArgumentException(String.Format("Type {0} does not derive from NSObject", whenFoundIn[i]));
var classHandle = Class.GetHandle(whenFoundIn[i]);
if (classHandle == IntPtr.Zero)
throw new ArgumentException(string.Format("Could not find the Objective-C class for {0}", whenFoundIn[i].FullName));
ptrs[i] = classHandle;
}
return ptrs;
}
UIAppearance.cs
替代方案,然后在其上添加了一个 CSS 模板层,所以我有一个优势,即有人付钱让我学习这些技巧 ;-) - SushiHangover