如何将属性添加到组件
最初由Kate Feeney创作返回首页
本文档介绍如何将新属性添加到现有App Inventor组件。
作为一个例子,我们将展示形状属性是如何加入到ButtonBase Ç omponent 。ButtonBase是按钮和选择器 组件的一个抽象艺术 超类 (ContactPicker,ImagePicker 和ListPicker); 因此, 为ButtonBase定义的所有属性也是为按钮和选择器定义的。最初ButtonBase组件没有形状属性; 它只使用默认形状,它。使用系统的默认值,设备因异而当加入的形状属性, 包括四个选项(默认,圆形,矩形和椭圆形)。 本。文档中的所有示例都显示 了按钮组件,但对于任何选择器组件都是相同的。
用户将首先在设计师的按钮组件的属性面板中看到新属性。因为选择应限制在四个合法值,我们将创建一个属性编辑 这限制了对这些值的选择,并将它们映射到属性的内部表示的整数。当用户更改形状属性的值时,设计中按钮组件的可视表示必须更改,以便用户可以预览界面。为此,我们将创建一个方法,该方法将更改表示设计中按钮组件的GWT按钮小部件的属性。最后,由于用户最终希望在Android的设备上更改属性,我们将添加更改按钮视图的BackgroundDrawable的代码,具体取决于所选的形状值。
第一步是添加属性,在以便 选择按钮时它显示在“ 属性” 面板中。此更改如下图所示。 每个属性都与属性编辑器相关联,以允许用户在合法值中进行选择。 通常,可以使用现有的PropertyEditor,但在某些情况下,例如Shape属性,则需要创建一个 新的PropertyEditor 。最后,我们将属性与组件相关联,以便在选择组件时属性将显示在“属性”面板中。
图1:按钮属性面板
E ach属性具有PropertyEditor ,用于控制可在Designer中指定的值。一些现有的PropertyEditor包括BooleanPropertyEditor (由ButtonBase.Enabled使用),NonNegativeFloatPropertyEditor (由ButtonBase.FontSize使用)和TextPropertyEditor (由ButtonBase.Text使用)。如果已存在合适的PropertyEditor (检查现有属性是否满足您的需求。), 则只需记下其名称并跳至第1.3节。否则,需要按照第1.2节中的描述创建一个新的PropertyEditor。
与Shape属性关联的PropertyEditor 必须提供一个下拉菜单,其中包含四个合法的形状值:默认,圆角,矩形和椭圆形(如下所示)。由于尚不存在,因此必须创建新的PropertyEditor。
图2: Designer中的Shape PropertyEditor
新的PropertyEditor类必须扩展PropertyEditor 类,并将用户输入限制为仅合法值。此类还将定义 PropertyEditor 如何显示给用户(下拉菜单,文本框等)。
对于我们的示例,新类将被称为YoungAndroidButtonShapeChoicePropertyEditor ,它将扩展ChoicePropertyEditor 类, 它本身扩展了PropertyEditor 。这个新的类必须定义数组选择 对象,并通过日Ë 阵列的ChoicePropertyEditor 构造函数,它将创建下拉- 向下选择部件。Choice是ChoicePropertyEditor类中定义的静态类,其构造函数包含两个字符串:caption 和v alue 。 该标题 字符串是在下降中显示文本- 向下选择部件。该值 的字符串是如果选择的选择分配给该属性的值。 新类在图4中定义。
第一步是定义四个描述性字符串(字幕 字符串),这些字符串显示给用户并将放置在传递给ChoicePropertyEditor的数组中。 这 是通过将以下代码添加到OdeMessages 接口来完成的。字符串在单独的文件中定义而不是硬编码的原因是支持抽象和国际化。
//在editor / youngandroid / properties / YoungAndroidButtonShapeChoicePropertyEditor.java中使用
@DefaultMessage(“默认” )
@Description(“按钮形状选择的文字'默认'” )
String defaultButtonShape ();
@DefaultMessage(“舍入” )
@Description(“按钮形状选择的文字'圆形'” )
String roundedButtonShape();
@DefaultMessage(“矩形” )
@Description(“按钮形状选择的文字'矩形'” )
String rectButtonShape();
@DefaultMessage(“椭圆形” )
@Description(“按钮形状选择的文字'椭圆'” )
String ovalButtonShape();
图3:在OdeMessagesÇ定义字符串小姑娘
现在字符串是定义d , 可以创建YoungAndroidButtonShapeEditor类,如图4所示。
包 com.google.appinventor.client.editor.youngandroid.properties;
import static com.google.appinventor.client.Ode。消息;
import com.google.appinventor.client.widgets.properties.ChoicePropertyEditor;
/ **
*按钮样式的属性编辑器。
*
* @author feeney.kate@gmail.com(凯特菲尼)
* /
公共类 YoungAndroidButtonShapeChoicePropertyEditor 扩展ChoicePropertyEditor {
//按钮形状选择
private static final Choice [] shapes = new Choice [] {
新 选择(MESSAGES .defaultButtonShape(),“0” ),
新 选择(MESSAGES .roundedButtonShape(),“1” )
新 选择(MESSAGES .rectButtonShape(),“2” ),
新 选择(MESSAGES .ovalButtonShape(),“3” )
};
public YoungAndroidButtonShapeChoicePropertyEditor(){
超级(形状);
}
}
图4:YoungAndroidButtonShapeEditor c lass
的值 的字符串(例如,“0”,“1”,“2”,在图4中“3”)将被分配到的属性,并且可以 通过访问 该组件的吸气剂S和setter方法。 当组件的getter检索到字符串时,它将作为int 检索 ,其中常量应在Component类中定义。w ^ Ë 将定义常量的组件 类,因为所有组件继承它。因此,需要添加以下代码(图5)。
/ *
*按钮样式。
* /
static final int BUTTON_SHAPE_DEFAULT = 0;
static final int BUTTON_SHAPE_ROUNDED = 1;
static final int BUTTON_SHAPE_RECT = 2;
static final int BUTTON_SHAPE_OVAL = 3;
图5:在Component类中定义值字符串
所述YoungAndroidPalettePanel 类创建在设计器的左侧组件面板和实例化组件的属性编辑。 我们需要在createPropertyEditor ()方法中添加逻辑来执行此操作。首先,我们需要在propertyTypeContants 类中为属性定义一个常量。添加以下代码。
/ **
*按钮形状。* @see com.google.appinventor.client.editor.youngandroid.properties。
* YoungAndroidButtonShapeChoicePropertyEditor
* /
public static final String PROPERTY_TYPE_BUTTON_SHAPE = “ button_shape ”;
然后将以下大小写添加到同一个类中的createPropertyEditor()方法。
} else if (editorType.equals (PropertyTypeConstants.PROPERTY_TYPE_BUTTON_SHAPE)){
返回新的YoungAndroidButtonShapeChoicePropertyEditor();
图6:添加到YoungAndroidPalettePanel。createPropertyEditor ()
为组件类中的新属性创建一个setter和getter方法。必须使用SimpleProperty注释标记setter和getter方法。SimpleProperty注释包含描述,属性的类别以及属性是否可见( 在BlocksEditor中可见)。setter方法还必须使用DesignerProperty注释进行标记。此注释由属性的编辑器类型(在DesignerProperty 注释中定义)和属性的默认值组成。
对于此示例,需要将以下代码添加到ButtonBase 类。
这是吸气剂:
/ **
*返回按钮的样式。
*
* @return {@link Component#BUTTON_SHAPE_DEFAULT}之一,
* {@link Component#BUTTON_SHAPE_ROUNDED},
* {@link Component#BUTTON_SHAPE_RECT}或
* {@link Component#BUTTON_SHAPE_OVAL}
* /
@SimpleProperty(
category = PropertyCategory.APPEARANCE ,
userVisible = false )
public int Shape(){
回归 形状;
}
图7:形状吸气剂
这是二传手:
/ **
*指定按钮的样式。这不会检查参数是否合法
*价值。
*
* @param形成{@link Component#BUTTON_SHAPE_DEFAULT}之一,
* {@link Component#BUTTON_SHAPE_ROUNDED},
* {@link Component#BUTTON_SHAPE_RECT}或
* {@link Component#BUTTON_SHAPE_OVAL}
*
* @throws IllegalArgumentException如果shape不是合法值。
* /
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_BUTTON_SHAPE,
defaultValue = Component.BUTTON_SHAPE_DEFAULT + “” )
@ SimpleProperty (description =“指定按钮的形状(默认,舍入,”+
“矩形,椭圆形。”如果图像是+,则形状将不可见
显示。“,userVisible = false )
public void Shape(int shape){
这个。形状=形状;
updateAppearance();
}
图8:形状设定器
然后使用以下代码在同一文件中定义变量形状。
//支持按钮形状
私人形状;
并将以下行添加到ButtonBase构造函数中。
形状(组件.BUTTON_SHAPE_DEFAULT );
在本节中实现代码之后,当在设计器视图中选择Button时,Shape属性将出现在Properties面板中; 但是,更改属性不会影响Button的外观。
可以在两个位置查看应用程序的用户界面。所述第一位置是在该设计器和第二个是Android装置(即电话,平板电脑或仿真器)上。Designer是浏览器窗口中显示的视图,将在本节中进行更改。
每个Component 在appengine 项目中都有一个相应的mock类。mock类是Designer中组件的可视化表示,mock类通常遵循与Component类相同的层次结构。 如果属性更改了组件的可视方面(例如颜色),则该组件的模拟类必须调整Designer以显示这些可视更改。
已经编写了许多方法来更改MockComponent,MockComponentsUtil 和 MockVisibleComponent中的组件属性; 大多数组件模拟类都从这些类中的至少一个继承。
要在Designer中更改外观,请找到与添加了属性的组件对应的模拟类。确定类是否继承了更改相应属性的方法。 如果存在这样的方法,那么只需编写一个使用适当的参数调用该方法的方法,就像在MockButtonBase 类中的setEnabledProperty()方法中所做的那样。如果方法不存在,则遵循此Shape属性示例。
对于此示例,与ButtonBase组件关联的mock类是MockButtonBa se 。图9显示了Shape属性的每个值的外观。
形状 | 图片 |
默认 | |
圆 | |
长方形 | |
椭圆 |
图9:模拟按钮
模拟组件构建在GWT小部件之上。MockButtonBase创建一个按钮小部件,它使用系统的默认值,为了使上面的形状按钮的角半径需要改变。 MockButtonBase或其任何超类中都不存在可以更改按钮角半径的方法,因此需要将以下方法(图10)添加到MockButtonBase中。
//形状的合法值定义在
// com.google.appinventor.components.runtime.Component.java。
私人 形状;
/ *
*将按钮的Shape属性设置为新值。
* /
private void setShapeProperty(String text){
shape = Integer.parseInt(text);
//带有图像的Android按钮采用图像的形状而不是
//使用其中一个定义的形状。
if (hasImage ){
回归;
}
开关(形状){
案例 0:
//默认按钮
DOM.setStyleAttribute(buttonWidget .getElement(),“border-radius” ,“0px” );
打破;
案例1 :
//圆形按钮
//按钮的角是圆整10像素。
//值10 px严格选择样式。
// 10 px与定义的ROUNDED_CORNERS_RADIUS相同
// com.google.appinventor.components.runtime.ButtonBase.java。
DOM.setStyleAttribute(buttonWidget .getElement(),“border-radius” ,“10px” );
打破;
案例2 :
//矩形按钮
DOM.setStyleAttribute(buttonWidget .getElement(),“border-radius” ,“0px” );
打破;
案例3 :
//椭圆形按钮
String height = DOM.getStyleAttribute(buttonWidget .getElement(),“height” );
DOM.setStyleAttribute(buttonWidget .getElement(),“border-radius” ,height);
打破;
默认值:
//这绝不应该发生
抛出新的 IllegalArgumentException(“shape:” + shape );
}
}
图10:MockButtonBase类的添加
模拟组件类包含 onPropertyChange()方法,当任何组件的属性发生更改时,它由GWT调用,并确定 如何 在Designer中更改视图。onPropertyChange()方法有两个字符串参数,propertyName 和newValue 。 的propertyName的 是在属性的getter定义的方法(也在属性面板中显示的字符串)的名称的字符串表示。该NEWVALUE 是财产的价值,并传递给刚创建的方法。 对于此示例,propertyName 将为“Shape”和 newValue 可以是“0”,“1”,“2”或“3”。
MockVisibleComponent 类中有一个所有可能的propertyName 值的列表。需要将新属性添加到列表中。对于此示例,请添加以下行。
protected static final String PROPERTY_NAME_BUTTONSHAPE = “Shape” ;
现在回到模拟组件的类添加逻辑,这样如果新属性被更改,它将调用刚刚创建的方法。
对于此示例,将以下语句添加到MockButtonBase类的onPropertyChange()方法
} else if (propertyName.equals(PROPERTY_NAME_BUTTONSHAPE )){
setShapeProperty(NEWVALUE);
图11:添加到onPropertyChange()
如果更改新属性不会影响任何其他属性,则此部分已完成。查看模拟组件类中的方法以确认这一点可能是个好主意。如果新属性确实影响其他属性,则根据需要更新在这些属性更改上调用的方法。
对于此示例,由于按钮形状仅在没有背景图像时更改,因此Shape属性和Image属性相互影响。 因此,由于setShapeProperty()方法已创建(或更新),因此需要更新setImageProperty()方法。
需要将以下两条灰色线添加到setImageProperty()方法中。
/ *
*将按钮的Image属性设置为新值。
* /
private void setImageProperty(String text){
imagePropValue = text;
String url = convertImagePropertyValueToUrl(text);
if(url == null){
hasImage = false;
url =“”;
setBackgroundColorProperty(的backgroundColor);
setShapeProperty(Integer.toString(形状));
} else {
hasImage = true;
// Android按钮如果有图像则不显示背景颜色。
//容器的背景颜色通过任何透明显示
//图像的一部分,我们可以在浏览器中获得的效果
//将小部件的背景颜色设置为COLOR_NONE。
MockComponentsUtil.setWidgetBackgroundColor(buttonWidget,
“&H”+ COLOR_NONE);
DOM.setStyleAttribute(buttonWidget.getElement(),“border-radius” ,“0px” );
}
MockComponentsUtil.setWidgetBackgroundImage(buttonWidget,url);
image.setUrl(URL);
}
图12:添加到setImageProperty()
现在,当Shape属性更改时,设计器视图中显示的按钮也将更改以反映用户的首选项。Android设备上的按钮仍然没有变化。
接下来决定如何更改Android设备上组件的可视化表示。然后在您定义属性的getter和setter的类中实现必要的代码。
对于Shape属性,需要更改组件的BackgroundDrawable 以更改形状。下表描述了如何为每个Shape更改ButtonBase组件。
形状 | 图片 | 可绘制 |
默认 | defaultButtonDrawable或没有drawable并设置背景颜色 | |
圆 | RoundRectShape(CornerArray,null,null) 其中CornerArray是和8个浮点数,每个浮点数的值为10f。 | |
长方形 | RectShape()可绘制 | |
椭圆 | OvalShape()可绘制 |
图13:形状抽屉
更改Android设备上的组件的过程非常特定于要更改的组件和要添加的属性。查看当前可用于具有类似属性的组件和组件的方法,以确定需要添加或更改的代码。
下一节详细介绍了实现Shape属性时遵循的过程。
在ButtonBase类中添加以下常量。
//形状常数
// 10px是圆角的半径。
//因为美学原因选择了10px。
private static final float ROUNDED_CORNERS_RADIUS = 10f;
private static final float [] ROUNDED_CORNERS_ARRAY = new float [] {
ROUNDED_CORNERS_RADIUS,ROUNDED_CORNERS_RADIUS,ROUNDED_CORNERS_RADIUS,
ROUNDED_CORNERS_RADIUS,ROUNDED_CORNERS_RADIUS,ROUNDED_CORNERS_RADIUS,
ROUNDED_CORNERS_RADIUS,ROUNDED_CORNERS_RADIUS};
//具有非默认形状的按钮的常量背景颜色
private static final int SHAPED_DEFAULT_BACKGROUND_COLOR = Color.LTGRAY;
用以下内容替换updateAppearance()方法。
//根据backgroundImageDrawable,backgroundColor和的值更新外观
//形状
//图像优先于背景颜色。
private void updateAppearance(){
//如果没有背景图片,
//外观仅取决于背景颜色和形状。
if (backgroundImageDrawable == null){
if (shape == Component.BUTTON_SHAPE_DEFAULT){
if (backgroundColor == Component.COLOR_DEFAULT){
//如果没有背景图像且默认颜色为
//恢复原始的3D斜面外观。
ViewUtil.setBackgroundDrawable(view,defaultButtonDrawable);
} else {
//清除背景图像。
ViewUtil.setBackgroundDrawable(view,null );
//设置为指定的颜色(透明可能为COLOR_NONE)。
TextViewUtil.setBackgroundColor(view,backgroundColor);
}
} else {
//如果没有背景图像且形状不是默认形状,
//使用适当的形状和颜色创建一个drawable。
setShape();
}
} else {
//如果有背景图片
ViewUtil.setBackgroundImage(view,backgroundImageDrawable);
}
}
图14:updateAppearance()的添加
使用以下内容添加setShape()方法。
//如果形状具有非法值,则抛出IllegalArgumentException。
private void setShape(){
ShapeDrawable drawable = new ShapeDrawable();
//设置drawable的颜色。
drawable.getPaint()。setColor((backgroundColor == Component.COLOR_DEFAULT)
?shapedDefaultBackgroundColor:backgroundColor);
//设置drawable的形状。
开关 (形状){
case Component.BUTTON_SHAPE_ROUNDED:
drawable.setShape(new RoundRectShape(ROUNDED_CORNERS_ARRAY,null ,null ));
打破;
case Component.BUTTON_SHAPE_RECT:
drawable.setShape(new RectShape());
打破;
case Component.BUTTON_SHAPE_OVAL:
drawable.setShape(new OvalShape());
打破;
默认值:
抛出新的 IllegalArgumentException();
}
//将drawable设置为按钮的背景。
view.setBackgroundDrawable(绘制);
view.invalidate();
}
图15:添加到setShape()
现在,当按钮的形状发生变化时,Mock按钮和Android设备上的按钮都应该更改。
该YaVersion 类(在com.google.appinventor.components.common)定义了年轻的Android系统版本号,块语言版本号和组件的版本号。如果在前面的部分中更新了Blocks语言或任何组件,则需要增加其版本号和Young Android System版本号。在类中还有描述更新每个值的指令。
对于Button Shape示例,ButtonBase组件已更新,因此需要增加ButtonBase组件版本号以及ButtonBase和Young Android System版本号子类的组件的版本号。 将以下格雷码添加到YaVersion类中。
// ............................年轻的Android系统版本号
// .............................
//当块语言或者一个\时,必须递增YOUNG_ANDROID_VERSION
//组件更改
// TODO(lizlooney) - 应该生成此版本号以便它
//当块语言或组件发生变化时自动递增?
//对于YOUNG_ANDROID_VERSION 2:
// - 删除了Logger组件。应该使用通告程序组件。
// - TINYWEBDB_COMPONENT_VERSION增加到2。
:
:
:
//对于YOUNG_ANDROID_VERSION 54:
// - BUTTON_COMPONENT_VERSION增加到4。
// - CONTACTPICKER_COMPONENT_VERSION增加到4。
// - IMAGEPICKER_COMPONENT_VERSION增加到4。
// - LISTPICKER_COMPONENT_VERSION增加到5。
// - PHONENUMBERPICKER_COMPONENT_VERSION增加到4。
public static final int YOUNG_ANDROID_VERSION = 54 ;
//对于BUTTON_COMPONENT_VERSION 2:
// - Alignment属性已重命名为TextAlignment。
//对于BUTTON_COMPONENT_VERSION 3:
// - 添加了LongClick事件。
//对于BUTTON_COMPONENT_VERSION 4:
// - 添加了Shape属性。
public static final int BUTTON_COMPONENT_VERSION = 4 ;
//对于CONTACTPICKER_COMPONENT_VERSION 2:
// - Alignment属性已重命名为TextAlignment。
//对于CONTACTPICKER_COMPONENT_VERSION 3:
// - 添加了Open方法。
//对于CONTACTPICKER_COMPONENT_VERSION 4:
// - 添加了Shape属性。
public static final int CONTACTPICKER_COMPONENT_VERSION = 4 ;
//对于IMAGEPICKER_COMPONENT_VERSION 2:
// - Alignment属性已重命名为TextAlignment。
//对于IMAGEPICKER_COMPONENT_VERSION 3:
// - 添加了Open方法。
//对于IMAGEPICKER_COMPONENT_VERSION 4:
// - 添加了Shape属性。
public static final int IMAGEPICKER_COMPONENT_VERSION = 4 ;
//对于LISTPICKER_COMPONENT_VERSION 2:
// - Alignment属性已重命名为TextAlignment。
//对于LISTPICKER_COMPONENT_VERSION 3:
// - 添加了SelectionIndex读写属性。
//对于LISTPICKER_COMPONENT_VERSION 4:
// - 添加了Open方法。
//对于LISTPICKER_COMPONENT_VERSION 5:
// - 添加了Shape属性。
public static final int LISTPICKER_COMPONENT_VERSION = 5 ;
//对于PHONENUMBERPICKER_COMPONENT_VERSION 2:
// - Alignment属性已重命名为TextAlignment。
//对于PHONENUMBERPICKER_COMPONENT_VERSION 3:
// - 添加了Open方法。
//对于PHONENUMBERPICKER_COMPONENT_VERSION 4:
// - 添加了Shape属性。
public static final int PHONENUMBERPICKER_COMPONENT_VERSION = 4 ;
图16:YaVersion类的添加
如YaVersion中的说明中所述,如果组件版本已更新,则必须将代码添加到YoungAndroidFormUpgrade (在com.google.appinventor.client.youngandroid中)。对于Button Shape示例,需要将以下格雷码添加到YoungAndroidFormUpgrader类中。
private static int upgradeButtonProperties(Map <String,JSONValue> componentProperties,
int srcCompVersion){
if (srcCompVersion <2){
// Alignment属性已重命名为TextAlignment。
handlePropertyRename(componentProperties,“Alignment” ,“TextAlignment” );
//与此组件相关的属性现已升级到版本2。
srcCompVersion = 2;
}
if (srcCompVersion <3){
//添加了LongClick事件。
//无需修改任何属性即可升级到版本3。
srcCompVersion = 3;
}
if (srcCompVersion <4){
//添加了Shape属性。
//无需修改任何属性即可升级到版本4。
srcCompVersion = 4;
}
return srcCompVersion;
}
private static int upgradeContactPickerProperties(Map <String,JSONValue>
componentProperties,int srcCompVersion){
if (srcCompVersion <2){
// Alignment属性已重命名为TextAlignment。
handlePropertyRename(componentProperties,“Alignment” ,“TextAlignment” );
//与此组件相关的属性现已升级到版本2。
srcCompVersion = 2;
}
if (srcCompVersion <3){
//添加了Open方法。无需任何更改。
srcCompVersion = 3;
}
if (srcCompVersion <4){
//添加了Shape属性。
//无需修改任何属性即可升级到版本4。
srcCompVersion = 4;
}
return srcCompVersion;
}
private static int upgradeImagePickerProperties(Map <String,JSONValue>
componentProperties,int srcCompVersion){
if (srcCompVersion <2){
// Alignment属性已重命名为TextAlignment。
handlePropertyRename(componentProperties,“Alignment” ,“TextAlignment” );
//与此组件相关的属性现已升级到版本2。
srcCompVersion = 2;
}
if (srcCompVersion <3){
//添加了Open方法。无需任何更改。
srcCompVersion = 3;
}
if (srcCompVersion <4){
//添加了Shape属性。
//无需修改任何属性即可升级到版本4。
srcCompVersion = 4;
}
return srcCompVersion;
}
private static int upgradeListPickerProperties(Map <String,JSONValue>
componentProperties,int srcCompVersion){
if (srcCompVersion <2){
// Alignment属性已重命名为TextAlignment。
handlePropertyRename(componentProperties,“Alignment” ,“TextAlignment” );
//与此组件相关的属性现已升级到版本2。
srcCompVersion = 2;
}
if (srcCompVersion <3){
//添加了SelectionIndex属性。无需任何更改。
srcCompVersion = 3;
}
if (srcCompVersion <4){
//添加了Open方法。无需任何更改。
srcCompVersion = 4;
}
if (srcCompVersion <5){
//添加了Shape属性。
//无需修改任何属性即可升级到版本5。
srcCompVersion = 5;
}
return srcCompVersion;
}
private static int upgradePhoneNumberPickerProperties(Map <String,JSONValue>
componentProperties,int srcCompVersion){
if (srcCompVersion <2){
// Alignment属性已重命名为TextAlignment。
handlePropertyRename(componentProperties,“Alignment” ,“TextAlignment” );
//与此组件相关的属性现已升级到版本2。
srcCompVersion = 2;
}
if (srcCompVersion <3){
//添加了Open方法。无需任何更改。
srcCompVersion = 3;
}
if (srcCompVersion <4){
//添加了Shape属性。
//无需修改任何属性即可升级到版本4。
srcCompVersion = 4;
}
return srcCompVersion;
}
图17:YoungAndroidFormUpgrader类的添加
该BlockSaveFile 类(在openblocks.yacodeblocks)也必须进行更新。如果任何组件版本号增加,则将代码添加到upgradeComponentBlocks()。
将以下格雷码添加到Button Shape示例的upgradeComponentBlocks()中。
private int upgradeButtonBlocks(int blkCompVersion,String componentName){
if (blkCompVersion <2){
// Alignment属性已重命名为TextAlignment 。
handlePropertyRename(componentName,“Alignment” ,“TextAlignment” );
//与此组件相关的块现在已升级到版本2。
blkCompVersion = 2;
}
if (blkCompVersion <3){
//添加了LongClick事件。
//无需修改块以升级到版本3。
blkCompVersion = 3;
}
if (blkCompVersion <4){
//添加了Shape属性。
//无需修改块以升级到版本4。
blkCompVersion = 4;
}
返回 blkCompVersion;
}
private int upgradeContactPickerBlocks(int blkCompVersion,String componentName){
if (blkCompVersion <2){
// Alignment属性已重命名为TextAlignment。
handlePropertyRename(componentName,“Alignment”,“TextAlignment”);
//与此组件相关的块现在已升级到版本2。
blkCompVersion = 2;
}
if (blkCompVersion <3){
//添加了Open方法,不需要更改。
blkCompVersion = 3;
}
if (blkCompVersion <4){
//添加了Shape属性。
//无需修改块以升级到版本4。
blkCompVersion = 4;
}
返回 blkCompVersion;
}
private int upgradeImagePickerBlocks(int blkCompVersion,String componentName){
if (blkCompVersion <2){
// Alignment属性已重命名为TextAlignment。
handlePropertyRename(componentName,“Alignment” ,“TextAlignment” );
//与此组件相关的块现在已升级到版本2。
blkCompVersion = 2;
}
if (blkCompVersion <3){
//添加了Open方法,不需要更改。
blkCompVersion = 3;
}
if (blkCompVersion <4){
//添加了Shape属性。
//无需修改块以升级到版本4。
blkCompVersion = 4;
}
返回 blkCompVersion;
}
private int upgradeListPickerBlocks(int blkCompVersion,String componentName){
if (blkCompVersion <2){
// Alignment属性已重命名为TextAlignment。
handlePropertyRename(componentName,“Alignment” ,“TextAlignment” );
//与此组件相关的块现在已升级到版本2。
blkCompVersion = 2;
}
if (blkCompVersion <3){
//添加了SelectionIndex属性,不需要更改。
blkCompVersion = 3;
}
if (blkCompVersion <4){
//添加了Open方法,不需要更改。
blkCompVersion = 4;
}
if (blkCompVersion <5){
//添加了Shape属性。
//无需修改块以升级到版本5。
blkCompVersion = 5;
}
返回 blkCompVersion;
}
private int upgradePhoneNumberPickerBlocks(int blkCompVersion,String componentName){
if (blkCompVersion <2){
// Alignment属性已重命名为TextAlignment。
handlePropertyRename(componentName,“Alignment”,“TextAlignment”);
//与此组件相关的块现在已升级到版本2。
blkCompVersion = 2;
}
if (blkCompVersion <3){
//添加了Open方法,不需要更改。
blkCompVersion = 3;
}
if (blkCompVersion <4){
//添加了Shape属性。
//无需修改块以升级到版本4。
blkCompVersion = 4;
}
返回 blkCompVersion;
}
图18:BlockSaveFile 类的添加
有时,在正在进行的开发中,有必要弃用现有的事件,方法或属性。这将从块调色板和抽屉中删除元素。如果读入包含块的现有项目,则该块将以红色标出并变为非活动状态,表示用户应将其删除。
要弃用块,请将@Deprecated批注添加到组件java文件中。此外,如果这是设计器属性,请注释掉@Designerproperty注释。例如,以下是我们如何弃用Camera.useFront属性(getter和setter):
/ **
*如果要使用前置摄像头,则返回true(如果可用)
*
* @return {@code true}表示默认使用前置,{@ code false}
* /
@Deprecated
@SimpleProperty(category = PropertyCategory.BEHAVIOR)
public boolean UseFront(){
return useFront;
}
/ **
*指定是否应使用前置摄像头(如果可用)
*
* @param front
* {@code true}用于前置摄像头,{@ code false}为默认值
* /
@Deprecated
//隐藏Designer中不推荐使用的属性
// @DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_BOOLEAN,defaultValue =“False”)
@SimpleProperty(description =“指定是否应使用前置摄像头(如果可用)。”
+“如果设备没有前置摄像头,则会忽略此选项”
+“并且相机将正常打开。”)
public void UseFront(boolean front){
useFront = front;
}
同时更新versioning.js以记录弃用已完成 - 尽管“不需要升级”。以下是Camera.useFront对Camera组件版本3的处理方法。
“相机”:{
...
// AI2:已删除UseFront属性
3:“noUpgrade”
...
},//结束相机升级
方法,事件和属性的名称需要国际化,以便它们可以以多种语言出现。不要对这些名称使用硬编码字符串。而是在OdeMessages.java中添加变量。类似的组件描述。
将每个新属性/事件/方法的条目添加到OdeMessages.java中iff具有该名称的属性尚不存在(因此,如果要添加的属性与另一个属性中的另一个属性同名,(即使在一种不同的语言)你第二次不这样做)。例如,要添加“Foo”属性,您需要添加:
@defaultMessage( “富”)
@description(“这是美妙的Foo属性的名字”)
String FooProperties();
不同语言的本地化字符串位于/appengine/src/com/google/appinventor/client.OdeMessages<language>.properties文件中。系统的设计使得如果没有翻译,则使用英语。因此,在实现属性时不需要提供翻译; 这些可以在以后添加。
如果您编辑组件的描述(但尚未编辑)
该组件的属性,方法或事件)您还必须找到和
更新OdeMessages.java中的描述