使用Xamarin.Forms应用Pixate Freestyle Style

时间:2014-07-21 15:19:38

标签: xamarin.forms pixate

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

但是,我还没有弄清楚是否有办法使用Xamarin.Forms编写的视图将样式应用于特定对象。我试过设置button.StyleId,但是还没有完成。我也尝试将PixateFreestyle DLL添加到基础项目中,但是A)不确定我是否可以添加iOS和Android以及B)即使添加它们也没有提供调用(并不惊讶,但是我认为我试了一下)

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

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

是的,也许不是。

是的:您可以为希望自定义的视图类型创建custom renderer,这样您就可以在XAML和iOS应用之间建立链接。在iOS端,您可以执行所需的所有库的所有调用。然后,您可以创建附加属性(例如下面的样式示例),这些属性可以包含配置渲染所需的其他信息,并将这些附加属性放在Style资源中,并在项目周围使用它们。 Xamarin.Forms还不支持合并资源字典,但你可以写一些代码来做到这一点,所以你的所有样式都在一个位置

...然而 可能没有:在Xamarin.Forms中有许多预定义控件及其各自的渲染器,很难为在所有场景中工作的框架创建一致的插件,例如ListView中的按钮可能没有正确渲染(试一试)

如果您确实试了一下,一旦您拥有适用于属性的基本渲染器,您就可以将一组属性与样式扩展一起打包

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}">
...

答案 1 :(得分:0)

我更新了this以使其正常运行。每个控件都有一个自定义渲染器,在事件上:OnElementPropertyChanged,OnElementChanged样式类和id取自xamarin.forms控件并转移到本机控件。

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);
    }
}

效果很好。