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

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

目录
相关文章
|
7月前
|
XML 编解码 开发工具
《移动互联网技术》第六章 资源管理: 掌握定制控件样式、界面主题、可绘制资源程序的编写方法
《移动互联网技术》第六章 资源管理: 掌握定制控件样式、界面主题、可绘制资源程序的编写方法
25 0
|
1月前
|
iOS开发 UED
实现一个自定义的iOS动画效果
【4月更文挑战第9天】本文将详细介绍如何在iOS平台上实现一个自定义的动画效果。我们将通过使用Core Animation框架来实现这个动画效果,并展示如何在不同的场景中使用它。文章的目标是帮助读者理解如何使用Core Animation框架来创建自定义动画,并提供一个简单的示例代码。
18 1
|
11天前
|
缓存 前端开发 JavaScript
【亮剑】在React中如何通过点击事件控制组件显示与隐藏,包括基础概念和高级应用
【4月更文挑战第30天】本文介绍了在React中如何通过点击事件控制组件显示与隐藏,包括基础概念和高级应用。使用`useState`钩子和Context API可实现状态驱动的条件渲染,通过CSS类控制组件样式,或利用React Portals在DOM不同位置渲染。性能优化应注意避免不必要的渲染、合理使用Keys、优化事件处理器、使用Memoization及清理资源。测试和验证确保逻辑正确性,以构建动态用户界面并提升应用性能。
|
2月前
|
测试技术 数据库 C++
Qt C++拖放事件探索之旅:多方法深入解析
Qt C++拖放事件探索之旅:多方法深入解析
223 1
|
10月前
|
前端开发 定位技术
百度地图开发自定义信息窗口openInfoWindow样式的解决方案
百度地图开发自定义信息窗口openInfoWindow样式的解决方案
834 0
|
JavaScript
vue uniapp通用省市下拉选择器组件 布局样式可灵活根据ui变更 (区域 可根据数组嵌套的格式继续往下模仿即可)
vue uniapp通用省市下拉选择器组件 布局样式可灵活根据ui变更 (区域 可根据数组嵌套的格式继续往下模仿即可)
536 0
vue uniapp通用省市下拉选择器组件 布局样式可灵活根据ui变更 (区域 可根据数组嵌套的格式继续往下模仿即可)
SwiftUI—借助sizeCategory预览不同字体下的文本视图
SwiftUI—借助sizeCategory预览不同字体下的文本视图
121 0
SwiftUI—借助sizeCategory预览不同字体下的文本视图
SwiftUI直通车系列(5)—— 自定义绘制
SwiftUI直通车系列(5)—— 自定义绘制
128 0
SwiftUI直通车系列(5)—— 自定义绘制
SwiftUI直通车系列(5)—— 自定义绘制(二)
SwiftUI直通车系列(5)—— 自定义绘制
133 0
SwiftUI直通车系列(5)—— 自定义绘制(二)