教程:自定义文本输入

教程:自定义文本输入

一个常见的被请求的功能是“基于小部件”的文本输入字段,今天的教程为您提供了构建自己的文本输入字段的基础。 这不是一个完整的实现,它只克服了与 native.newTextField() 相关的一些问题,但它应该提供一个良好的起点。

让我们从一些基本的设置代码开始

当然,像这样的小部件最终可能会有很多选项,但让我们从考虑一些基本选项开始

  • top — 距屏幕顶部的距离
  • left — 距屏幕左侧的距离
  • x — 小部件的水平位置(中心)
  • y — 小部件的垂直位置(中心)
  • width — 字段的宽度
  • height — 字段的高度
  • font — 要使用的字体
  • fontSize — 字体的大小
  • backgroundColor — 文本后面的颜色
  • strokeColor — 字段周围笔画的颜色
  • strokeWidth — 笔画的大小
  • cornerRadius — 如果您想要圆角
  • text — 初始文本
  • inputType — 要显示的键盘类型
  • listener — 输入处理程序

显然,这可以扩展到包括诸如“返回”按钮的值,具有在您第一次开始编辑字段时消失的占位符文本,甚至外观功能。 但是,由于此函数将使用原生文本字段,因此我们需要编写 — 核心 — 一个处理字段编辑的函数

如果我们希望将其作为小部件库的一部分,我们只需将其添加到模块并包含小部件库

这将导致将一个新函数 newTextField() 添加到已包含在您的项目中的小部件库的实例中。 然后,在您需要 widget 库的任何场景或模块中,该函数都将可用。

现在让我们定义默认选项值

上面的代码可能看起来有点令人困惑,但我们只是简单地接受一个名为 options 的函数参数。第一行创建了一个名为 customOptions 的表,以确保它是一个 Lua 表。如果您没有传递 options 参数,则会创建一个空表。之后,我们只是将每个单独的选项设置为传递的值或默认值。对于这个小部件,诸如圆角半径和字体大小之类的东西应该默认为适应字段大小的值。

创建视觉元素

在本节中,我们将创建文本字段小部件的视觉部分,包括与之配对的原生 UI 元素

在您检查此代码时,请考虑以下几点:

  • 如果将角变为圆形,请不要让实际的文本字段延伸到角中。
  • 请记住隐藏原生文本字段的背景,以便显示您的自定义视觉效果。
  • native.newTextField() 需要将字体字符串名称转换为native.newFont()。但是,尺寸有点棘手,因为原生文本字段不会自动缩放。因此,我们必须计算设备的实际缩放因子,然后将所需的字体大小乘以该缩放因子。

移除元素

我们需要确保在移除小部件时,也同时移除原生文本字段。以前,我们需要使用我们自己的函数覆盖 removeSelf() 函数,该函数最终会调用原始的 removeSelf()。但是,新的 finalize 事件使此过程更加容易。这使我们能够设置一个函数,该函数在*显示对象从舞台上移除之前*执行,以防我们需要处理相关的清理任务——在本例中,在移除我们的自定义文本字段组之前移除原生文本字段。

使用自定义文本字段

使用我们新的“小部件”文本字段很简单。要将其放置在屏幕上,我们的代码可能如下所示:

检索文本字段的值

设置文本字段的值

总结

本教程应该可以帮助您开始实现“样式化”文本输入字段,并希望将其扩展到更复杂的使用场景。


罗布·米勒克
[email protected]

罗布是 Corona Labs 的开发者关系经理。除了热衷于帮助其他开发者使用 Corona 制作出色的游戏外,他还在空闲时间喜欢制作游戏。自 1979 年以来,罗布一直从事游戏编码,从个人电脑到大型机。他在游戏行业拥有超过 16 年的专业经验。

19 条评论
  • 迪恩·霍奇
    发布于 15:34, 12 月 3 日

    罗布,很棒的教程,但是……

    我兴奋了一会儿,以为这可以解决 textField 的最大问题,即字体大小在各种设备(尤其是 Android)上的缩放问题。

    每次我做一个商业应用程序时,这个问题总会困扰我,以及许多其他人。

    希望我们能尽快解决字体大小缩放问题,因为它已经困扰我和许多其他开发人员很长时间了。

    请尝试找到此问题的解决方案。

    • 克里斯
      发布于 16:01, 12 月 3 日

      +1 在设备上的字体缩放

    • 罗布·米勒克
      发布于 16:03, 12 月 3 日

      你试过这个吗?我在我的 iPhone 5、iPad 4 和 Google Nexus 7(具有 320×480 的基本内容区域)上运行了代码,字体大小在设备之间保持一致。那里有代码来维持缩放。

      罗布

      • 凯雷姆
        发布于 11:54, 12 月 5 日

        刚刚在我的 Android 2.2 三星 Galaxy S 上尝试了代码。字体大小问题仍然存在。不确定这是否是由于过旧的操作系统版本造成的。

        • 罗布·米勒克
          发布于 17:32, 12 月 5 日

          您能否在论坛帖子中回复此内容并提供屏幕截图?

  • 星际碎片
    发布于 15:03, 12 月 4 日

    我记得必须明确地 removeSelf() 小部件...这些小部件是否已经考虑到 finalize 进行了重写?也就是说,我是否可以摆脱该处理代码?

    • 罗布·米勒克
      发布于 15:20, 12 月 4 日

      所有显示对象都需要显式删除并设置为 nil,但 Storyboard 除外,当场景被销毁时,场景视图中的显示对象会被为您删除。

      罗布

      • 星际碎片
        发布于 16:57, 12 月 4 日

        对不起,我表达得不够准确;这可能听起来有点琐碎的问题。我的意思是,对于小部件,removeSelf() 是否仍然是必要的,而不是说 group:remove() 或移除父组,考虑到逻辑已移到终结器中。至少,我假设那些不会调用(可能被覆盖的)removeSelf() 方法...

        当然,也许我会测试一下,看看我的假设是否一直都是错误的。🙂

  • 凯雷姆
    发布于 00:14, 12 月 5 日

    感谢您提供的精彩教程。这是我希望能够发展成为正式的 Corona Labs widget.newTextField() 的一个很好的起点。

    问题 - 我们如何扩展功能,以便如果将一个新参数(即 eraseInitialText)设置为 true,那么当用户第一次点击此输入字段时,最初提供的文本将被删除?我可以在监听器函数的开始字段中执行此操作,但我想将此代码推送到小部件扩展代码中,以便可以重用它。这可能吗?谢谢

  • 肖恩
    发布于 06:54, 12 月 5 日

    嘿,罗布,这些文本字段现在会在小部件 ScrollView 中滚动吗?这对我来说一直是个大问题;让文本字段与屏幕的其余部分一起滚动。关于何时在实际小部件代码库中实现此功能,是否有时间表?

    • 罗布·米勒克
      发布于 16:31, 12 月 6 日

      我没有尝试过,但它应该可以。同步代码将原生文本字段保持在对象所在的任何位置。根据您滚动 scrollView 的速度,系统移动 native.newTextField 时可能会有一些延迟。

      罗布

  • 卡维卡
    发布于 10:03, 12 月 8 日

    有人在使用 X-PRESSIVE.COM 的“Text Candy”吗?

  • 卡维卡
    发布于 12:35, 12 月 8 日

    有人在使用 X-PRESSIVE.COM 的“Widget Candy”吗?

  • bobcgausa
    发布于 06:49, 1 月 15 日

    我使用 Corona 来教学生,他们在使用 Mac 或 Windows 上的模拟器,并且不一定拥有安卓设备。

    “由于此模块仍然使用原生文本字段,因此它将在 Windows Corona 模拟器上绘制小部件背景,但文本字段将不起作用。”

    真的,拥有一个跨平台单行文本框有多难?
    这对课堂使用来说是一个巨大的限制。

    • 罗布·米勒克
      发布于 1月15日 17:51

      我们已经多次解释过这个问题。Corona SDK 基于 OpenGL。在 OS-X、iOS 和 Android 上,操作系统允许原生对象和 OpenGL 画布占据同一窗口。在 Windows 上,它们不允许原生对象和 OpenGL 对象在同一窗口中共存。微软允许基于 DirectX 的应用程序这样做,但我们是基于 OpenGL 的应用程序。

  • sangu
    发布于 9月17日 01:07

    我的代码中 widget.newTextField({}) 显示错误,同时引用了 widget。
    它在 pro-corona 中支持吗?或者我在代码中做错了什么?
    local widget = require("widget")
    local myTextField = widget.newTextField(
    {
    top = 10,
    left = 20,
    width = 200,
    height = 30,
    cornerRadius = 8,
    strokeWidth = 3,
    backgroundColor = { 1, 1, 1 },
    strokeColor = { 0, 0, 0 },
    font = "Helvetica",
    fontSize = 24
    --listener = textFieldHandler
    }

    • 罗布·米勒克
      发布于 9月17日 17:28

      请在论坛中提出这个问题。

      谢谢
      罗布

  • Julius Bangert
    发布于 9月8日 06:21

    是否有人开发出提供类型提前输入/自动完成功能的模块或插件?
    因此,当用户输入前几个字母时,UI 中文本输入附近会显示从 lua 表中提取的建议词汇?
    这将会非常棒。