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

简介: 有趣的是,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编程,而且只需一步即可完成三个步骤,并继续迈向未来 移动开发。

目录
相关文章
|
前端开发
Threejs - 加载视频纹理渲染 实现一个3D视频播放器
Threejs - 加载视频纹理渲染 实现一个3D视频播放器
2155 0
Threejs - 加载视频纹理渲染 实现一个3D视频播放器
|
3月前
|
JavaScript 前端开发
使用 WebGL 创建 3D 动画
【10月更文挑战第3天】使用 WebGL 创建 3D 动画
|
8月前
|
Python
渲染模板
【2月更文挑战第21天】渲染模板。
31 1
【Redshift渲染器渲染出图片有色差(红移渲染器)】
【Redshift渲染器渲染出图片有色差(红移渲染器)】
211 0
【Redshift渲染器渲染出图片有色差(红移渲染器)】
|
存储 资源调度 JavaScript
2.Vue3中Cesium地图初始化及地图控件配置
本文中,我们主要介绍 Cesium 在 Vue 3运行环境的配置,以及 Cesium 实例中控件的显隐设置,本文是后续文章内容的基础,项目代码在此查看;通过本文,我们可以得到一个纯净的 cesium 项目,后续的操作我们就可以在此基础上进行;
695 0
Sprite渲染流程-纹理绑定
Sprite渲染流程-纹理绑定
98 0
|
人工智能 前端开发 JavaScript
canvas 中如何实现自定义路径动画
前言 大家好!!又到周末了,最近项目忙完了,有时间写文章了。之前有粉丝问我, fly哥怎么实现自定义路径动画, 当时给他说的就是路径无非不就是直线 或者曲线。也就这两种, 直线的话 可以用直线方程, 曲线的话稍微复杂点 ,需要用贝塞尔曲线去做lerp。也就是动画的每一幁的算出路径的对应的坐标就可以了。但是这套方案学习成本太高了, 有没有一种更加简单的方式呢?本篇文章大概花费你5分钟, 你可以学到什么呢 svg 的 两个无敌api 后面介绍 封装了一个自定义路径动画函数 创建Path 制作动画前,先要拿到动画的路径,对此我们可以直接使用svg的path定义规则,比如我们定义了一条较为复杂的路径
canvas 中如何实现自定义路径动画
|
Dart 开发者
【Flutter】Animation 动画 ( AnimatedBuilder 动画使用流程 | 创建动画控制器 | 创建动画 | 创建动画作用的组件 | 关联动画与组件 | 动画执行 )(三)
【Flutter】Animation 动画 ( AnimatedBuilder 动画使用流程 | 创建动画控制器 | 创建动画 | 创建动画作用的组件 | 关联动画与组件 | 动画执行 )(三)
189 0
【Flutter】Animation 动画 ( AnimatedBuilder 动画使用流程 | 创建动画控制器 | 创建动画 | 创建动画作用的组件 | 关联动画与组件 | 动画执行 )(三)
|
JavaScript
vue 动态组件动画-转场动画基础
这个先不用单文件组件来演示 因为单文件组件 一般都是项目使用了,项目中一般都是路由动画
318 0
【Flutter】Animation 动画 ( AnimatedBuilder 动画使用流程 | 创建动画控制器 | 创建动画 | 创建动画作用的组件 | 关联动画与组件 | 动画执行 )(一)
【Flutter】Animation 动画 ( AnimatedBuilder 动画使用流程 | 创建动画控制器 | 创建动画 | 创建动画作用的组件 | 关联动画与组件 | 动画执行 )(一)
167 0

热门文章

最新文章