第二十七章:自定义渲染器(六)

简介: 有趣的是,Android SeekBar小部件具有与Steps属性等效的功能,但不等同于Minimum和Maximum属性! 这怎么可能? SeekBar实际上定义了一个名为Max的整数属性,SeekBar的Progress属性始终是一个从0到Max的整数。

有趣的是,Android SeekBar小部件具有与Steps属性等效的功能,但不等同于Minimum和Maximum属性! 这怎么可能? SeekBar实际上定义了一个名为Max的整数属性,SeekBar的Progress属性始终是一个从0到Max的整数。 因此,Max属性确实指示了SeekBar可以执行的步骤数,并且SeekBar的Progress属性和StepSlider的Value属性之间需要进行转换。
此转换发生在两个地方:SetValue方法从StepSlider的Value属性转换为SeekBar的Progress属性,OnProgressChanged方法从SeekBar的Progress属性转换为StepSlider的Value属性。
另外,事件处理程序有点不同。 SetOnSeekBarChangeListener方法接受类型为IOnSeekBarChangeListener的参数,该参数定义了三个报告Seekbar更改的方法,包括方法OnProgressChanged。 渲染器本身实现了该接口。
这是Xamarin.FormsBook.Platform.Android库中的完整StepSliderRenderer类:

using System.ComponentModel;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(Xamarin.FormsBook.Platform.StepSlider),
                          typeof(Xamarin.FormsBook.Platform.Android.StepSliderRenderer))]
namespace Xamarin.FormsBook.Platform.Android
{
    public class StepSliderRenderer : ViewRenderer<StepSlider, SeekBar>,
                                      SeekBar.IOnSeekBarChangeListener
    {
        double minimum, maximum;
        protected override void OnElementChanged(ElementChangedEventArgs<StepSlider> args)
        {
            base.OnElementChanged(args);
            if (Control == null)
            {
                SetNativeControl(new SeekBar(Context));
            }
            if (args.NewElement != null)
            {
                SetMinimum();
                SetMaximum();
                SetSteps();
                SetValue();
                Control.SetOnSeekBarChangeListener(this);
            }
            else
            {
                Control.SetOnSeekBarChangeListener(null);
            }
        }
        protected override void OnElementPropertyChanged(object sender,
                                                         PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged(sender, args);
            if (args.PropertyName == StepSlider.MinimumProperty.PropertyName)
            {
                SetMinimum();
            }
            else if (args.PropertyName == StepSlider.MaximumProperty.PropertyName)
            {
                SetMaximum();
            }
            else if (args.PropertyName == StepSlider.StepsProperty.PropertyName)
            {
                SetSteps();
            }
            else if (args.PropertyName == StepSlider.ValueProperty.PropertyName)
            {
                SetValue();
            }
        }
        void SetMinimum()
        {
            minimum = Element.Minimum;
        }
        void SetMaximum()
        {
            maximum = Element.Maximum;
        }
        void SetSteps()
        {
            Control.Max = Element.Steps;
        }
        void SetValue()
        {
            double value = Element.Value;
            Control.Progress = (int)((value - minimum) / (maximum - minimum) * Element.Steps);
        }
        // Implementation of SeekBar.IOnSeekBarChangeListener
        public void OnProgressChanged(SeekBar seekBar, int progress, bool fromUser)
        {
            double value = minimum + (maximum - minimum) * Control.Progress / Control.Max;
            ((IElementController)Element).SetValueFromRenderer(StepSlider.ValueProperty, value);
        }
        public void OnStartTrackingTouch(SeekBar seekBar)
        {
        }
        public void OnStopTrackingTouch(SeekBar seekBar)
        {
        }
    }
}

StepSliderDemo解决方案包含指向Xamarin.FormsBook.Platform库的链接以及对这些库的相应引用。 StepSliderDemo.xaml文件实例化五个StepSlider元素,其中三个是数据绑定,另外两个是显式事件处理程序:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:platform=
                 "clr-namespace:Xamarin.FormsBook.Platform;assembly=Xamarin.FormsBook.Platform"
             x:Class="StepSliderDemo.StepSliderDemoPage">
    <StackLayout Padding="10, 0">
        <StackLayout.Resources>
            <ResourceDictionary>
                <Style TargetType="ContentView">
                    <Setter Property="VerticalOptions" Value="CenterAndExpand" />
                </Style>
                <Style TargetType="Label">
                    <Setter Property="FontSize" Value="Large" />
                    <Setter Property="HorizontalOptions" Value="Center" />
                </Style>
            </ResourceDictionary>
        </StackLayout.Resources>
        <ContentView>
            <StackLayout>
                <platform:StepSlider x:Name="stepSlider1" />
                <Label Text="{Binding Source={x:Reference stepSlider1},
                                      Path=Value}" />
            </StackLayout>
        </ContentView>
        <ContentView>
            <StackLayout>
                <platform:StepSlider x:Name="stepSlider2"
                                     Minimum="10"
                                     Maximum="15"
                                     Steps="20"
                                     ValueChanged="OnSliderValueChanged" />
                <Label x:Name="label2" />
            </StackLayout>
        </ContentView>
        <ContentView>
            <StackLayout>
                <platform:StepSlider x:Name="stepSlider3"
                                     Steps="10" />
                <Label Text="{Binding Source={x:Reference stepSlider3},
                                      Path=Value}" />
            </StackLayout>
        </ContentView>
        <ContentView>
            <StackLayout>
                <platform:StepSlider x:Name="stepSlider4"
                                     Minimum="0"
                                     Maximum="1"
                                     Steps="100"
                                     ValueChanged="OnSliderValueChanged" />
                <Label x:Name="label4" />
            </StackLayout>
        </ContentView>
        <ContentView>
            <StackLayout>
                <platform:StepSlider x:Name="stepSlider5"
                                     Minimum="10"
                                     Maximum="20"
                                     Steps="2" />
                <Label Text="{Binding Source={x:Reference stepSlider5},
                                      Path=Value}" />
            </StackLayout>
        </ContentView>
    </StackLayout>
</ContentPage>

代码隐藏文件具有ValueChanged事件处理程序:

public partial class StepSliderDemoPage : ContentPage
{
    public StepSliderDemoPage()
    {
        InitializeComponent();
    }
    void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
    {
        StepSlider stepSlider = (StepSlider)sender;
        if (stepSlider == stepSlider2)
        {
            label2.Text = stepSlider2.Value.ToString();
        }
        else if (stepSlider == stepSlider4)
        {
            label4.Text = stepSlider4.Value.ToString();
        }
    }
}

您会发现StepSlider的功能类似于普通的Xamarin.Forms Slider,只是StepSlider中的可能值现在处于程序控制之下:
2019_06_21_094010
第一个StepSlider的增量值为1,第二个增量为0.25,第三个增量为10,第四个增量为0.01,第五个增量为5,只有三个可能的设置。
现在你可以看到Xamarin.Forms如何提供工具,让你超越它最初的样子。 您可以在三个平台中定义的任何内容都可以在一个通用平台中成为可用的东西。 使用C#编程语言,以及Xamarin.Forms和渲染器的强大功能,您不仅可以进入iOS编程,Android编程或Windows编程,而且只需一步即可完成三个步骤,并继续迈向未来 移动开发。

目录
相关文章
|
1天前
|
图形学
【Unity Shader#自定义材质面板_第二篇】
【Unity Shader#自定义材质面板_第二篇】
|
1天前
|
图形学
【Unity Shader#自定义材质面板_第一篇】
【Unity Shader#自定义材质面板_第一篇】
|
5月前
|
API 图形学
[√]unity渲染一个文本的细节
[√]unity渲染一个文本的细节
48 0
|
负载均衡 安全 vr&ar
【Unity渲染】一文看懂!Unity通用渲染管线URP介绍
Unity 的渲染管线包含内置渲染管线、SRP、URP和HDRP。自从Unity2019.3开始,Unity将轻量级渲染管线修改为了通用渲染管线,这是一种快速、可扩展的渲染管线,支持所有的移动设备,适用于 2D、3D、虚拟现实 (VR) 和增强现实 (AR) 项目。
|
图形学
Unity 基础 之 自定义编辑器布局
Unity 是一个强大的开发引擎,一起来认识一下编辑器布局吧。看看如何才能调整出你想要的布局吧,调整后果然舒适哦~
392 0
|
数据安全/隐私保护 iOS开发 开发者
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建(二)
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建
283 0
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建(二)
|
数据安全/隐私保护 iOS开发 开发者
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建(一)
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建
393 0
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建(一)
|
Windows
第二十七章:自定义渲染器(五)
渲染器和事件(1) 大多数Xamarin.Forms元素都是交互式的。他们通过触发事件来响应用户输入。如果在Xamarin.Forms自定义元素中实现事件,则可能还需要在呈现器中为本机控件触发的相应事件定义事件处理程序。
685 0
|
前端开发 Android开发 iOS开发
第二十七章:自定义渲染器(四)
渲染器和属性(2) 现在,对于iOS,EllipseUIView类是存在的,可以使用EllipseUIView作为本机控件来编写EllipseViewRenderer。 从结构上讲,这个类几乎与Windows渲染器相同: using System.
549 0
|
Android开发 iOS开发 Windows
第二十七章:自定义渲染器(三)
渲染器和属性(1) Xamarin.Forms包含一个BoxView元素,用于显示矩形颜色块。 你有没有希望你有类似的东西画一个圆圈,或使它更通用,椭圆?这就是EllipseView的目的。 但是,因为您可能希望在多个应用程序中使用EllipseView,所以它在第20章“异步和文件I / O”中介绍的Xamarin.FormsBook.Platform库中实现。
756 0