使用Xamarin.Forms应用像素自由式样式



我正在Xamarin中构建一个应用程序。我刚刚发现了Pixate Freestyle,这真是太棒了。我用它来设置一个默认的按钮类,例如,把基本的默认样式放在我所有的按钮上,这是伟大的。

然而,我还没能弄清楚是否有一种方法可以使用Xamarin.Forms中编写的视图将样式应用于特定对象。我试过设置按钮。StyleId,但这还没有完成。我还尝试将pixatefrestyle DLL添加到基本项目中,但A)不确定我是否可以添加iOS和Android, B)即使添加了,他们也不提供调用(并不惊讶,但我想我会给它一个机会)

有没有办法通过Xamarin.Forms为Freestyle应用样式?可能在iOS项目中使用某种调用来利用.Forms传递的功能来使用Freestyle设置类?

提前感谢任何帮助。

是,也许不是。

Yes:你可以为你想要能够自定义的视图类型创建自定义渲染器,这将为你提供XAML和iOS应用程序之间的链接。在iOS端,你可以执行所有调用所有你需要的库。然后,您可以创建附加属性(例如下面的Style示例),这些附加属性可以保存配置呈现所需的附加信息,并将这些附加属性放入Style资源中,并在项目中使用它们。Xamarin的。Forms目前还不支持合并资源字典,但是你可以编写一些代码来实现这一点,这样你所有的样式就会在一个位置

然而

可能不:在Xamarin中有许多预定义的控件和它们各自的渲染器。窗体,创建一个在所有场景下都能工作的一致的框架插件是很困难的,例如一个按钮在ListView中可能无法正确渲染(给它一个机会)

如果你想尝试一下,一旦你有了基本的渲染器,你就可以把一组属性打包在一起,并使用Style扩展

public class Setter
    {
        public string Property { get; set; }
        public object Value { get; set; }
        public string ConverterKey { get; set; }
        public object ConverterParameter { get; set; }
    }
[ContentProperty ("Children")]
public class Style
    {
        public ResourceDictionary Resources { get; set; }
        public Style ()
        {
            Children = new List<Setter> ();
        }
        public List<Setter> Children { get; private set; }
        public static readonly BindableProperty StyleProperty = 
            BindableProperty.CreateAttached<BindableObject, Style> ((bob) => GetStyle (bob), null, BindingMode.OneWay
                , propertyChanged: (bindable, oldvalue, newvalue) => {
                    if (newvalue != null) { 
                        var tinf = bindable.GetType ().GetTypeInfo ();
                        foreach (var setter in newvalue.Children) {  
                            PropertyInfo pinfo = null;
                            while (pinfo == null && tinf != null) {
                                pinfo = tinf.DeclaredProperties.FirstOrDefault (p => p.Name == setter.Property);
                                if (pinfo == null) {
                                    tinf = tinf.BaseType.GetTypeInfo ();
                                    if (tinf == typeof(object).GetTypeInfo ())
                                        break;
                                } 
                            }
                            if (pinfo != null) {
                                object convertedValue = null;
                                if (setter.ConverterKey != null && newvalue.Resources != null) {
                                    object valCon;
                                    if (newvalue.Resources.TryGetValue (setter.ConverterKey, out valCon) && valCon != null) { 
                                        if (valCon is IValueConverter)
                                            convertedValue = ((IValueConverter)valCon).Convert (setter.Value, pinfo.PropertyType, setter.ConverterParameter, System.Globalization.CultureInfo.CurrentUICulture);
                                        else if (valCon is TypeConverter)
                                            convertedValue = ((TypeConverter)valCon).ConvertFrom (setter.Value);
                                        else
                                            convertedValue = Convert.ChangeType (setter.Value, pinfo.PropertyType);
                                    } else
                                        convertedValue = Convert.ChangeType (setter.Value, pinfo.PropertyType);
                                } else
                                    convertedValue = Convert.ChangeType (setter.Value, pinfo.PropertyType);
                                pinfo.SetMethod.Invoke (bindable, new [] { convertedValue  });  
                            }
                        } 
                    }
                });
        public static Style GetStyle (BindableObject bindable)
        {
            return (Style)bindable.GetValue (StyleProperty);
        }
        public static void SetStyle (BindableObject bindable, Style value)
        {
            bindable.SetValue (StyleProperty, value);
        } 
    }

在XAML中…

<f:Style x:Key="stackStyle">
    <f:Style.Resources>
        <ResourceDictionary>
            <ColorTypeConverter x:Key="colorConverter" />
        </ResourceDictionary>
    </f:Style.Resources>
    <f:Setter Property="BackgroundColor" Value="#3898DC" ConverterKey="colorConverter" />
</f:Style>
...
<StackLayout f:Style.Style="{StaticResource stackStyle}">
...

我更新了这个以使其工作。每个控件都有一个自定义渲染器,在OnElementPropertyChanged、OnElementChanged事件中,样式类和id取自xamarin。窗体控件并转移到本机控件。

public static class StyledRenderer {
    public static void UpdateStyle (UIView view, VisualElement model = null) {
        var styleId = model.StyleId;
        var classId = model.ClassId;
        UpdateStyle (view, styleId, classId);
    }
    public static void UpdateStyle (UIView view, string styleId, string classId) {
        Console.WriteLine ("Update style " + styleId + " " + classId + " for " + view);
        if (!string.IsNullOrWhiteSpace (styleId)) {
            view.SetStyleId (styleId);
        }
        if (!string.IsNullOrWhiteSpace (classId)) {
            view.SetStyleClass(classId);
        }
        view.UpdateStylesNonRecursivelyAsync ();
    }
    public static void StyleOnElementPropertyChanged (UIView control, VisualElement element, object sender, PropertyChangedEventArgs e) {
        if (e.PropertyName == "ClassId" || e.PropertyName ==  "StyleId") {
            StyledRenderer.UpdateStyle (control, element);
        }
    }
    public static void StyleOnElementChanged ( UIView control, VisualElement element) {
        StyledRenderer.UpdateStyle (control, element);
    }
}
public class StyledEntryRenderer : EntryRenderer
{   
    protected override void OnElementPropertyChanged (object sender, PropertyChangedEventArgs e) {
        base.OnElementPropertyChanged (sender, e);
        StyledRenderer.StyleOnElementPropertyChanged (Control, Element, sender, e);
    }
    protected override void OnElementChanged (ElementChangedEventArgs<Entry> e) {
        base.OnElementChanged (e);
        StyledRenderer.StyleOnElementChanged (Control, e.NewElement);
    }
}

相关内容

  • 没有找到相关文章