Custom views are implemented as B4X classes or in a library.
A custom view includes a set of properties that can be set from the visual designer.
Note that the visual designer will show a box instead of the actual view.
Using custom views is very simple. You need to add the class or library to the project and then you can add the custom view in the same way you add other views:
This tutorial will explain how to implement custom views.
B4X Class
Add a custom view class:
Note that you can also add a regular class. The only difference is in the code template.
The template in B4J is:
B4X:
#Event: ExampleEvent (Value As Int)
#DesignerProperty: Key: BooleanExample, DisplayName: Boolean Example, FieldType: Boolean, DefaultValue: True, Description: Example of a boolean property.
#DesignerProperty: Key: IntExample, DisplayName: Int Example, FieldType: Int, DefaultValue: 10, MinRange: 0, MaxRange: 100, Description: Note that MinRange and MaxRange are optional.
#DesignerProperty: Key: StringWithListExample, DisplayName: String With List, FieldType: String, DefaultValue: Sunday, List: Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday
#DesignerProperty: Key: StringExample, DisplayName: String Example, FieldType: String, DefaultValue: Text
#DesignerProperty: Key: ColorExample, DisplayName: Color Example, FieldType: Color, DefaultValue: 0xFFCFDCDC, Description: You can use the built-in color picker to find the color values.
Sub Class_Globals
Private fx As JFX
Private EventName As String 'ignore
Private CallBack As Object 'ignore
End Sub
Public Sub Initialize (vCallback As Object, vEventName As String)
EventName = vEventName
CallBack = vCallback
End Sub
Public Sub DesignerCreateView (Base As Pane, Lbl As Label, Props As Map)
End Sub
Private Sub Base_Resize (Width As Double, Height As Double)
End Sub
Initialize, DesignerCreateView and Base_Resize signatures must be as in the code above.
At runtime the Initialize sub will be called followed by DesignerCreateView. Most of the work is done in DesignerCreateView.
The events and the designer properties are declared in the attributes.
When you create a custom view a pane or panel (with the event name set to Base) is added to the views tree. In most cases you will add the other views to the base panel and resize the views in Base_Resize event. This is true for B4J and B4i. In B4A there is no resize event as the activity is recreated instead.
The passed label includes the text related settings. It is not added to the views tree. You can either ignore it or use its text properties.
The Props map holds the custom properties. You should get the properties values and apply them to the custom view.
Designer Properties
Each property is made of several fields, the following fields are required:
Key - The property key. This will be used to get the value from the Props map.
DisplayName - The property name in the properties grid.
FieldType - One of the following values (case insensitive): String, Int, Float, Boolean or Color.
DefaultValue - The default value.
Optional fields:
Description - Will be displayed at the bottom of the properties grid when the property is selected.
MinRange / MaxRange - Minimum and maximum numeric values allowed.
List - A pipe (|) separated list of items from which the developer can choose (should be used with string fields).
You shouldn't use commas in any of the above fields.
See the attached project for several B4J examples.
Java Custom Views
Creating a custom view in Java is similar to the above. The class needs to implement the DesignerCustomView interface.
The interface declares two methods:
B4X:
@Override
public void DesignerCreateView(final ConcretePaneWrapper base, LabelWrapper label,
Map args) {
base.AddNode(getObject(), 0, 0, base.getWidth(), base.getHeight());
new PaneWrapper.ResizeEventManager(base.getObject(), null, new Runnable() {
@Override
public void run() {
SetLayoutAnimated(0, 0, 0, base.getWidth(), base.getHeight());
}
});
getItems().AddAll(Common.ArrayToList(((String)args.Get("Items")).split("\\|")));
getObject().setStyle(label.getStyle()); //set the font style
}
@Hide
@Override
public void _initialize(BA ba, Object arg1, String EventName) {
innerInitialize(ba, EventName.toLowerCase(BA.cul), false);
}
Properties are declared as annotations, for example:
B4X:
@DesignerProperties(values={
@Property(key="MinValue", displayName="Min Value", fieldType="float", defaultValue="0", minRange="0"),
@Property(key="MaxValue", displayName="Max Value", fieldType="float", defaultValue="100"),
@Property(key="LowValue", displayName="Low Value", fieldType="float", defaultValue="0", minRange="0",
description="Current lower value."),
@Property(key="HighValue", displayName="High Value", fieldType="float", defaultValue="100",
description="Current lower value."),
@Property(key="ShowTickLabels", displayName="Show Tick Labels", fieldType="boolean", defaultValue="false"),
@Property(key="ShowTickMarks", displayName="Show Tick Marks", fieldType="boolean", defaultValue="false"),
@Property(key="SnapToTicks", displayName="Snap To Ticks", fieldType="boolean", defaultValue="false"),
@Property(key="Orientation", displayName="Orientation", fieldType="string", defaultValue="Horizontal",
list="Horizontal|Vertical"),
})
You need to use BADoclet v1.05+ (v1.05 is attached) to generate the XML file.
See the attached ControlsFX source code as an example.
Tips
- In addition to the defined properties the Props map will include the parent form (key=Form) or activity (key=activity) or page (key=page).
- The keys in the Props map are case sensitive.
- If you add a new property to an existing class or library (that was already implemented as a custom view) then you should use Props.GetDefault if you want to maintain backwards compatibility.
- CSSUtils class is very useful for style manipulation: https://www.b4x.com/android/forum/threads/61824/#content
Attachments
Last edited: