AI开发实战4-文本输入框(TextBox)的定制1

本文介绍如何为AppInventor2中的文本输入框组件增加字符长度限制的功能,包括新增属性及函数,并展示了具体实现步骤。

4 文本输入框(TextBox)的定制

4.1增加公共的属性和函数

文本输入框也是常使用的组件,App Inventor2提供的组件已经包含了许多属性和函数,但有些常用的属性并未提供。

如用户在文本框中输入字符的时候,常会有字符个数限制的,现就开发一个设置字符串长度的属性,以方便使用。

App Inventor2默认提供了两种文本输入框:密码输入框和普通的文本输入框,在源码中对应的类分别是:PasswordTextBox和TextBox,两者有共同的基类:TextBoxBase,在TextBase.java中定义了输入框的属性和函数,现就在此文件中增加设置字符串长度的属性和相关函数。

在TextBase.java中的修改如下:

//增加表示字符串长度的变量

private int textLength;

 

/** 增加获取字符串长度的函数

  * Returns the length of thetextbox's text

  */

  @SimpleProperty(

     category = PropertyCategory.BEHAVIOR,

     description = "Set the length oftext")

  public int TextLength() {

   return textLength;

   }

 

   /**增加设置字符串长度的函数,默认值为0

  * Specifies the length of thetextbox's text

  * @param length

  */

  @DesignerProperty(editorType =PropertyTypeConstants.PROPERTY_TYPE_NON_NEGATIVE_INTEGER,

     defaultValue = "0")

  @SimpleProperty

  public void TextLength(int length) {

   this.textLength = length;

   }

 

@SimpleProperty是App Inventor使用的注解,表示定义了一个属性,源码如下:

/**

 *Annotation to mark Simple properties.

 *

 *<p>Both the getter and the setter method of the property need to bemarked

 *with this annotation.

 *

 */

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface SimpleProperty {

  /**

   *If non-empty, description to use in user-level documentation.

   */

  Stringdescription() default "";

 

 /**

  * Category of property for user-level documentation.  This only needs

  * to be specified in the setter or the getter, not both.

  */

 PropertyCategory category() default PropertyCategory.UNSET;

 

 /**

  * If false, this property should not be accessible through Codeblocks.

  * This was added to support the Row and Column properties, so they could

  * be indirectly set in the Designer but not accessed in Codeblocks.

  */

 boolean userVisible() default true;

}

 

category可以赋的值如下:

public enum PropertyCategory {

 // TODO(user): i18n category names

 BEHAVIOR("Behavior"),

 APPEARANCE("Appearance"),

 DEPRECATED("Deprecated"),

 UNSET("Unspecified");

 

 private String name;

 

 PropertyCategory(String categoryName) {

   name = categoryName;

  }

 

 public String getName() {

   return name;

  }

}

 

@DesignerProperty定义属性的类型和默认值,源码如下:

/**

 *Annotation to mark properties to be visible in the ODE visual designer.

 *

 *<p>Only the setter method of the property must be marked with this

 *annotation.

 *

 */

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface DesignerProperty {

 /**

  * Determines the property editor used in the designer.

  *

  * @return  property type

  */

 String editorType() default PropertyTypeConstants.PROPERTY_TYPE_TEXT;

 

 /**

  * Default value of property.

  *

  * @return  default property value

  */

 String defaultValue() default "";

}

 

editorType可以赋的值定义在PropertyTypeConstants.java里,在这里赋值为:

editorType =PropertyTypeConstants.PROPERTY_TYPE_NON_NEGATIVE_INTEGER

表示是非负整型。

 

/** 增加核查字符串长度的函数

  * Check the length of test is ok or not.

  */

 @SimpleFunction(

   description = "Check the length of test is ok or not.")

 public boolean  CheckTextLength(){

    if (textLength != 0){

             if(Text().length() == textLength){

                     returntrue;

              }else{

                     returnfalse;

              }

}else{

        //如果属性的值为0,则表示长度没有限制

          return true;

    }

  }

 

@SimpleFunction是用于定义函数的注解,源码如下:

/**

 *Annotation to mark Simple functions.

 *

 *<p>Note that the Simple compiler will only recognize Java methods marked

 *with this annotation. All other methods will be ignored.

 *

 */

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface SimpleFunction {

 /**

  * If non-empty, description to use in user-level documentation in placeof

  * Javadoc, which is meant for developers.

  */

 String description() default "";

 

 /**

  * If false, this property should not be accessible through Codeblocks.

  * This was added (1) by analogy to {@link SimpleProperty#userVisible()}

  * and (2) to temporarily hide functions for opening additional screens

  * in {@link com.google.appinventor.components.runtime.Form}.

  */

 boolean userVisible() default true;

}

定义好属性和函数后,还需要在OdeMessages.java中添加属性和函数的声明:

@DefaultMessage("TextLength")

 @Description("")

 String TextLengthProperties();

 

@DefaultMessage("CheckTextLength")

 @Description("")

 String CheckTextLengthMethods();

到目前为止,已经成功添加了属性和相关函数,可以正常使用了,但属性名称和函数名称在中文环境下也显示为英文,需要在OdeMessages_zh_CN.properties中添加中文字符串:

TextLengthProperties = 文本长度

CheckTextLengthMethods = 核查文本长度

最终的实现效果如下:

可以看到在组件属性中,多了一个设置文本长度的属性,在此设置值为6。

因为是添加在密码输入框和文本输入框组件的共同基类里的,所以密码输入框和文本输入框都继承并拥有了添加的属性和函数。

在密码输入框和文本输入框的工作面板中,都可以看到多了个核查文本长度的函数:

 

在工作面板中,也都可以设置文本长度:

 

 

使用示例如下:

你提供的这段 XAML 代码: ```xml <TextBox Grid.Row="1" Grid.Column="1" x:Name="NameTextBox" PlaceholderText="在这里输入..." Width="200" /> ``` 是一个在 Avalonia 中定义 `TextBox` 输入框的常见写法。下面我们来详细解释这段代码的含义,并确保它能在你的项目中正常运行。 --- ## ✅ 代码解析 ```xml <TextBox Grid.Row="1" Grid.Column="1" x:Name="NameTextBox" PlaceholderText="在这里输入..." Width="200" /> ``` ### 属性解释: | 属性 | 说明 | |------|------| | `Grid.Row="1"` | 指定该控件位于父级 Grid 的第 2 行(索引从 0 开始) | | `Grid.Column="1"` | 指定该控件位于父级 Grid 的第 2 列 | | `x:Name="NameTextBox"` | 为这个 TextBox 指定一个名称,用于在 C# 后台代码中引用 | | `PlaceholderText="在这里输入..."` | 设置输入框为空时显示的提示文字 | | `Width="200"` | 设置输入框的宽度为 200 像素 | --- ## ⚠️ 注意事项 如果你在运行时遇到类似如下错误: > **"Unable to resolve suitable regular or attached property PlaceholderText on type Avalonia.Controls.TextBox"** 说明你的 Avalonia 版本 **低于 11.0**,不支持 `PlaceholderText` 属性。 --- ## ✅ 解决方案:根据 Avalonia 版本选择合适的方式 ### ✅ 方式一:Avalonia 11+(推荐) 如果你使用的是 **Avalonia 11 或更高版本**,那么 `PlaceholderText` 是官方支持的属性,可以直接使用,无需额外处理。 --- ### ✅ 方式二:Avalonia 10 及以下版本 #### 替代方案 1:使用 Watermark(推荐) ```xml <TextBox Grid.Row="1" Grid.Column="1" x:Name="NameTextBox" Width="200" xmlns:i="https://github.com/avaloniaui/avalonia/xaml/interactivity" i:Watermark.Watermark="在这里输入..." /> ``` 你需要确保项目中引用了 `Avalonia.Controls.Watermark` 相关包。 #### 替代方案 2:手动模拟 Placeholder(兼容所有版本) ```xml <TextBox Grid.Row="1" Grid.Column="1" x:Name="NameTextBox" Text="在这里输入..." GotFocus="NameTextBox_GotFocus" LostFocus="NameTextBox_LostFocus" Width="200" Foreground="Gray" /> ``` ##### 后台 C# 代码: ```csharp private void NameTextBox_GotFocus(object sender, RoutedEventArgs e) { var tb = sender as TextBox; if (tb.Text == "在这里输入..." && tb.Foreground == Brushes.Gray) { tb.Text = ""; tb.Foreground = Brushes.Black; } } private void NameTextBox_LostFocus(object sender, RoutedEventArgs e) { var tb = sender as TextBox; if (string.IsNullOrWhiteSpace(tb.Text)) { tb.Text = "在这里输入..."; tb.Foreground = Brushes.Gray; } } ``` --- ## ✅ 示例完整结构(放在 Grid 中) ```xml <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <TextBlock Grid.Row="0" Grid.Column="0" Text="姓名:" VerticalAlignment="Center"/> <TextBox Grid.Row="1" Grid.Column="1" x:Name="NameTextBox" PlaceholderText="在这里输入..." Width="200" /> </Grid> ``` --- ## ✅ 总结 | 功能 | Avalonia 11+ | Avalonia 10 及以下 | |------|---------------|---------------------| | 原生 Placeholder | ✅ 支持 `PlaceholderText` | ❌ 不支持 | | 使用 Watermark | ✅ 支持(推荐) | ✅ 支持(推荐) | | 手动模拟 Placeholder | ✅ 支持 | ✅ 支持 | --- ##
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值