带秒数的时间选择器

2023-12-01

我正在使用 Xamarin Forms,在我的应用程序中的某个位置,我需要用户能够以 HH:mm:ss 格式输入时间。所以,基本上我需要一个像这样的控件:

Timepicker with seconds

通过使用自定义 iOS 渲染,我已经能够从 TimePicker 中删除 AM/PM 部分,以实现如下所示的效果:

enter image description here

这是我的渲染器代码:

public class TimePickerSecondsRenderer : TimePickerRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
    {
        base.OnElementChanged(e);

        var timePicker = (UIDatePicker)Control.InputView;
        timePicker.Locale = new NSLocale("CA");

    }
}

我认为这是朝着正确方向迈出的一小步,但是当涉及到为秒添加第三列以及每列的标签时,我真的不知所措。

我看了一下这个post但到目前为止它并没有真正帮助我。

有人设法通过 Xamarin Forms 项目实现这种控制吗?您介意分享一些指示吗?


我终于得到了一个有效的实现。结果如下:

enter image description here

唯一的缺点是标签“hr”、“min”和“sec”位于其自己的列中。因此,如果用户尝试与它们交互,就会产生反弹效果。稍后我会尝试看看是否可以改进。 欢迎提出建议!

当然,还有代码(如果它对某人有用的话):

渲染器

[assembly: ExportRendererAttribute(typeof(MyTimePicker), typeof(MyTimePickerRenderer))]
namespace MyProject.iOS.Renderers
{
    public class MyTimePickerRenderer : PickerRenderer
    {
        internal static  IDevice Device;

        internal const int ComponentCount = 6;

        private const int _labelSize = 30;

        private MyTimePicker _myTimePicker;

        public MyTimePickerRenderer()
        {
            // This is dependent on XForms (see Update note)
            Device = Resolver.Resolve<IDevice>();
        }

        protected override void OnElementChanged (ElementChangedEventArgs<Picker> e)
        {
            base.OnElementChanged (e);

            if (Control != null)
            {
                Control.BorderStyle = UITextBorderStyle.None;

                _myTimePicker = e.NewElement as MyTimePicker;

                var customModelPickerView = new UIPickerView
                    {
                        Model = new MyTimePickerView(_myTimePicker)
                    };

                SelectPickerValue(customModelPickerView, _myTimePicker);
            
                CreatePickerLabels(customModelPickerView);

                Control.InputView = customModelPickerView;
            }
        }

    private void SelectPickerValue(UIPickerView customModelPickerView, MyTimePicker myTimePicker)
    { 
        customModelPickerView.Select(new nint(myTimePicker.SelectedTime.Hours), 0, false);
        customModelPickerView.Select(new nint(myTimePicker.SelectedTime.Minutes), 2, false);
        customModelPickerView.Select(new nint(myTimePicker.SelectedTime.Seconds), 4, false);
    }

    private void CreatePickerLabels(UIPickerView customModelPickerView)
    {
        nfloat verticalPosition = (customModelPickerView.Frame.Size.Height / 2) - (_labelSize / 2);
        nfloat componentWidth = new nfloat(Device.Display.Width / ComponentCount / Device.Display.Scale);

        var hoursLabel = new UILabel(new CGRect(componentWidth, verticalPosition, _labelSize, _labelSize));
        hoursLabel.Text = "hrs";

        var minutesLabel = new UILabel(new CGRect((componentWidth * 3) + (componentWidth / 2), verticalPosition, _labelSize, _labelSize));
        minutesLabel.Text = "mins";

        var secondsLabel = new UILabel(new CGRect((componentWidth * 5) + (componentWidth / 2), verticalPosition, _labelSize, _labelSize));
        secondsLabel.Text = "secs";

        customModelPickerView.AddSubview(hoursLabel);
        customModelPickerView.AddSubview(minutesLabel);
        customModelPickerView.AddSubview(secondsLabel);
    }

    protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        if (Control == null)
        {
            return;
        }

        if (e.PropertyName == "SelectedIndex")
        {
            var customModelPickerView = (UIPickerView)Control.InputView;

            SelectPickerValue(customModelPickerView, _myTimePicker);
        }
    }
    
    public class MyTimePickerView : UIPickerViewModel
    {
        private readonly MyTimePicker _myTimePicker;

        public MyTimePickerView(MyTimePicker picker)
        {
            _myTimePicker = picker;
        }

        public override nint GetComponentCount(UIPickerView pickerView)
        {
            return new nint(MyTimePickerRenderer.ComponentCount);
        }

        public override nint GetRowsInComponent(UIPickerView pickerView, nint component)
        {
            if (component == 0)
            {
                // Hours
                return new nint(24);
            }

            if (component % 2 != 0)
            {
                // Odd components are labels for hrs, mins and secs
                return new nint(1);
            }

            // Minutes & seconds
            return new nint(60);
        }

        public override string GetTitle(UIPickerView pickerView, nint row, nint component)
        {
            if (component == 0)
            {
                return row.ToString();
            }
            else if (component == 1)
            {
                return null;
            }
            else if (component == 3)
            {
                return null;
            }
            else if (component == 5)
            {
                return null;
            }
            return row.ToString("00");
        }

        public override void Selected(UIPickerView pickerView, nint row, nint component)
        {
            var selectedHours = pickerView.SelectedRowInComponent(0);
            var selectedMinutes = pickerView.SelectedRowInComponent(2);
            var selectedSeconds = pickerView.SelectedRowInComponent(4);

            var time = new TimeSpan((int)selectedHours, (int)selectedMinutes, (int)selectedSeconds);

            _myTimePicker.SelectedTime = time;
        }

        public override nfloat GetComponentWidth(UIPickerView pickerView, nint component)
        {
            var screenWidth = MyTimePickerRenderer.Device.Display.Width;

            var componentWidth = screenWidth /
                MyTimePickerRenderer.ComponentCount /
                MyTimePickerRenderer.Device.Display.Scale;
        
            return new nfloat(componentWidth);
        }
    }
}

自定义可绑定选择器类

public class MyTimePicker : Picker
{
    public static readonly BindableProperty SelectedTimeProperty =
    BindableProperty.Create<MyTimePicker, TimeSpan>(p => p.SelectedTime, TimeSpan.MinValue, BindingMode.TwoWay,propertyChanged: OnSelectedTimePropertyPropertyChanged);

    public MyTimePicker()
    {
        // Ugly hack since Xamarin Forms' Picker uses only one component internally
        // This is a list of all possible timespan from 0:00:00 to 23:59:59
        for (int hour = 0; hour < 24; hour++)
        {
            for (int minute = 0; minute < 60; minute ++)
            {
                for (int second = 0; second < 60; second++)
                {
                    Items.Add(string.Format("{0:D2}:{1:D2}:{2:D2}", hour, minute, second));
                }
            }
        }

        base.SelectedIndexChanged += (o, e) =>
        {
            if (base.SelectedIndex < 0)
            {
                SelectedTime = TimeSpan.MinValue;
                return;
            }

            int index = 0;
            foreach (var item in Items)
            {
                if (index == SelectedIndex)
                {
                    SelectedTime = TimeSpan.Parse(item);
                    break;
                }
                index++;
            }
        };
    }

    public TimeSpan SelectedTime
    {
        get { return (TimeSpan)GetValue(SelectedTimeProperty); }
        set { SetValue(SelectedTimeProperty, value); }
    }

    private static void OnSelectedTimePropertyPropertyChanged(BindableObject bindable, TimeSpan value, TimeSpan newValue)
    {
        var picker = (MyTimePicker)bindable;

        var itemMatch = picker.Items.FirstOrDefault(x => x == newValue.ToString());
        var index = picker.Items.IndexOf(itemMatch);

        picker.SelectedIndex = index;
    }
}

XAML 用法

<myControls:MyTimePicker SelectedTime="{Binding SelectedTime}" />

其中 SelectedTime 是用于绑定的 ViewModel 属性。必须是 TimeSpan 类型。

我确信它可以改进,所以如果您有建议,请发表评论。


UPDATE

我已经更新了渲染器代码。

  • “小时”、“分钟”和“秒”现在是标签,不再是它们自己的列。这意味着用户不再可以与它们交互(不再有反弹效果)
  • 我还修复了一个错误,如果选择器值是从 ViewModel 设置的,则在打开键盘时,选择仍为 00:00:00
  • 更好地支持 iPhone Plus 分辨率

请注意,此代码依赖于 XForms (https://github.com/XLabs/Xamarin-Forms-Labs)来获取设备屏幕尺寸,因为这是我用于我的项目的框架,但它可以轻松修改。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带秒数的时间选择器 的相关文章

  • SSH 主机密钥指纹与模式 C# WinSCP 不匹配

    我尝试通过 WinSCP 使用 C 连接到 FTPS 服务器 但收到此错误 SSH 主机密钥指纹 与模式不匹配 经过大量研究 我相信这与密钥的长度有关 当使用 服务器和协议信息 下的界面进行连接时 我从 WinSCP 获得的密钥是xx xx
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • 如何在 EKRecurrenceRule 中设置一周中某一天的数组?

    我想在用户选择的特定日期每周添加事件 可以是一个或多个 也可以是一整天 我将用户选择的日期值存储在模型类变量中 但是 当我添加事件并选择日期时 假设今天是星期一 我选择星期二和星期三并保存 然后我查看周一和周三添加的 iPhone 日历 我
  • 具有多种自定义单元格类型的 RxSwift 表视图

    我想知道是否有任何代码示例RxSwift当我可以在一个表视图中使用多个自定义单元格时 例如 我有两个部分 第一部分有 10 个单元格 类型为CellWithImage标识符和第二部分有 10 个带有类型的单元格CellWithVideo标识
  • Windows 窗体不会在调试模式下显示

    我最近升级到 VS 2012 我有一组在 VS 2010 中编码的 UI 测试 我试图在 VS 2012 中启动它们 我有一个 Windows 窗体 在开始时显示使用 AssemblyInitialize 属性运行测试 我使用此表单允许用户
  • 初始化变量的不同方式

    在 C 中初始化变量有多种方法 int z 3 与 int 相同z 3 Is int z z 3 same as int z z 3 您可以使用 int z z 3 Or just int z 3 Or int z 3 Or int z i
  • 播放(非库)Apple Music 内容 - 请求失败

    我正在尝试使用以下代码播放专辑 let predicate MPMediaPropertyPredicate value 1459938538 forProperty MPMediaItemPropertyAlbumPersistentID
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • Xamarin:“框架不在模块中”- VS 2013&2015

    我对 XAMARIN 支持感到非常失望 那么 我将从头开始 过去几个月一切都很好 直到我更新了 xamarin 的最新版本 4 0 3 214 结果是我现在无法调试 我收到以下消息 框架不在模块中 我向 Xamarin 支持发送了一封电子邮
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • 下标:使用字符串枚举访问我的字典值

    我想做类似的事情 使用字符串枚举访问我的字典值 我试图重载字典的下标但没有成功 访问字典 let district address JsonKeys district 其中 JsonKeys 是 enum JsonKeys String c
  • 当设置 setVisibleXRangeMaximum 时,iOS-Charts X 轴值无限重复

    我正在尝试绘制一个图表 其中 x 轴是TimeIntervalY 轴是power consumption 由于每天都会有数据 因此将有太多数据无法显示 因此 我想一次显示 5 个值 我通过设置实现了这一点self chart setVisi
  • 在 ASP.NET 中将事件冒泡为父级

    我已经说过 ASP NET 中的层次结构 page user control 1 user control 2 control 3 我想要做的是 当控件 3 它可以是任何类型的控件 我一般都想这样做 让用户用它做一些触发回发的事情时 它会向
  • C++ 成员函数中的“if (!this)”有多糟糕?

    如果我遇到旧代码if this return 在应用程序中 这种风险有多严重 它是一个危险的定时炸弹 需要立即在应用程序范围内进行搜索和销毁工作 还是更像是一种可以悄悄留在原处的代码气味 我不打算writing当然 执行此操作的代码 相反
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co
  • 不同类型的指针可以互相分配吗?

    考虑到 T1 p1 T2 p2 我们可以将 p1 分配给 p2 或反之亦然吗 如果是这样 是否可以不使用强制转换来完成 或者我们必须使用强制转换 首先 让我们考虑不进行强制转换的分配 C 2018 6 5 16 1 1 列出了简单赋值的约束

随机推荐

  • 从 UILabel Swift 中获取 Int

    我遇到的问题是 有大量以数字作为标签的按钮 所以我想我可以将标签视为整数 而不是为每个按钮创建一个操作 IBAction func NumberInput sender UIButton var input Int sender title
  • 使用 Foundation 6 的中间人

    我想将 Middleman 与出色的 Foundation 6 一起使用 Here是我在 Middleman 网站上找到的一个存储库 我安装了 Middleman 以及 Xcode 开发人员工具 当我跑步时middleman init T
  • 如何在android中的服务中调用振动器

    我正在尝试运行vibrator如果从我的应用程序调用服务 我将从Fragment但我不知道为什么振动器在服务内不起作用 我什至无法打印Toast 我的代码 从片段调用 Intent buzz new Intent getActivity L
  • Entity Framework Core 中动态更改架构

    UPD here这是我解决问题的方法 尽管它可能不是最好的 但它对我有用 我在使用 EF Core 时遇到问题 我想通过模式机制在项目数据库中分离不同公司的数据 我的问题是如何在运行时更改架构名称 我找到了类似的问题关于这个问题 但它仍然没
  • Google 图表:自定义刻度

    我想在 Google 图表的水平轴上设置自己的刻度 我包括了 hAxis ticks 根据文档 在我下面的尝试中 但它拒绝工作 因为刻度仍然不是整数 即使我指定它们是整数 我究竟做错了什么
  • 是否可以在未计算的上下文中从 STD 形成指向不可寻址函数的指针?

    如中所述命名空间 std 6 让 F 表示标准库函数 除非 F 被指定为可寻址函数 否则如果 C 程序显式或隐式尝试形成指向 F 的指针 则其行为是未指定的 可能是格式错误的 这对于以下程序意味着 include
  • 字符 Å Ö 没有显示在我的 DDL 中,我如何告诉 Restclient 使用特定的字符集?

    在我开始之前 这里是一个问题 应该是这样的 Bj rn Nilsson 相反 它显示奇怪的特殊字符 所有包含字符 和 的值都变成这样 我用 XML 格式的 API 中的值填充我的 DDL 其中包含所有值 并且我们还使用 Linq2Rest
  • 如何显示带有动态创建的姓名首字母的头像图标

    我有一个要求 通过传递名称 它应该返回头像 图标 其中包含该名称中包含的单词的第一个字母 例如 如果我通过 John Abraham 它应该返回一个带有 JA 的图标 我需要在 SAPUI5 控件中使用该图标 我对此没有任何想法 如何实施
  • Java 一行 if 不适用于打印[重复]

    这个问题在这里已经有答案了 如果你写这样的东西 boolean condition String out condition true false System out println out 有用 但如果你写 condition Syst
  • 正则表达式将所有字符都放在第一个空格的右侧?

    我正在尝试创建一个正则表达式 该表达式将匹配字符串中第一个空格之后 但不包括 的所有字符 输入文本 foo bar bacon 期望的比赛 bar bacon 到目前为止我发现的最接近的是 s 然而 这与 bar bacon 之外的第一个空
  • Eclipse 插件更新错误日志在哪里?

    当我尝试更新一个 Eclipse 插件时 它显示以下错误 但我在 Eclipse 文件夹下没有找到任何内容 日志路径在哪里 an error has occurred see the error log for details Thx 该日
  • NSURLCredentialStorage 和客户端证书认证

    从我在 MPMoviewPlayerController 的文档中看到的 NSURLCredentialStorage 可以设置为 NSURLConnection 身份验证挑战的替代方案 这对于从 URL 加载资源但抽象 NSURLConn
  • iOS:如何获取两个坐标之间的路线路径

    在我的项目中 我必须借助纬度和经度找出两个位置之间的路线路径 我正在使用以下代码 void viewDidLoad super viewDidLoad Do any additional setup after loading the vi
  • .net MVC:如何仅向授权用户提供静态文件

    我的网站中有静态文件 例如 http myurl com Content a html http myurl com Content b html etc 我想在访问时验证用户的身份验证 身份验证应通过数据库数据进行检查 我的框架 ASP
  • Swift 多关卡场景

    我正在尝试开发一个新的游戏项目 其中将包含多个级别 我正在读这个问题 Sprite Kit 定义多个场景的变量 关于使用尽可能少的重复代码来完成多个场景的最佳方法 答案当然是子类化 假设我创建了 baseScene 它是 SKScene 的
  • 如何监听来自 Kafka 的正确 ACK 消息

    我正在做一个POC使用 Spring Boot 和 Kafka 进行事务性项目 我有以下疑问 设想 一个微服务MSPUB1接收来自客户的请求 该请求发布有关主题的消息TRANSACTION TOPIC1在 Kafka 上 但微服务可以并行接
  • Twig Excel 捆绑包自动调整大小

    如何在 Twig Excel Bundle 中设置自动调整大小 https twigexcelbundle readthedocs io en latest 您可以设置默认值autoSize片材的属性true via columnDimen
  • Java 中的垃圾回收与递归函数

    我知道在常规循环的每次迭代中 对象都会变得无法访问并标记为垃圾回收 那么递归调用呢 就像是 public void doWork Object a new Object some work with a this sleep 60000 d
  • 如何计算SQL中两个日期之间的“星期二”数?

    我想弄清楚如何计算 TSQL 中两个日期之间的 星期二 数量 Tuesday 可以是任何值 谢谢 t clausen dk 救了我几天 要获取每天的实例数 declare from datetime 3 1 2013 declare to
  • 带秒数的时间选择器

    我正在使用 Xamarin Forms 在我的应用程序中的某个位置 我需要用户能够以 HH mm ss 格式输入时间 所以 基本上我需要一个像这样的控件 通过使用自定义 iOS 渲染 我已经能够从 TimePicker 中删除 AM PM