B4J Tutorial [BANano] Absolute Placement of Elements & "Hidden" Props

Hi

What we will do:

From:

1692856690636.png


To:

1692856657837.png

How:

Take any BANano custom view, add a Log(Props) on the DesignerCreateView sub, magic happens, use the view in your layout and check the web console for the output.

1692855758134.png


You get to see some "hidden props" that you can use. These are for enabled, visible, hanchor, vanchor, height, width, left and top AS defined in the abstract designer. I will call these "hidden" because these are generated by BANano for you and are read from the values set when you place the view on the abstract designer.

To get access to these anywhere in the code, this is what I have done.

1. create a global variable called CustProps

1692855929562.png


2. Copy these to the global variable

1692856190207.png

3. Set some getters for the values. I did not define temporal values to store these, so I will read them directly from the copied map

B4X:
Sub getB4XEnabled As Boolean
    Return CustProps.Get("B4XEnabled")
End Sub

Sub getB4XVisible As Boolean
    Return CustProps.Get("B4XVisible")
End Sub

Sub getB4XVAnchor As String
    Return CustProps.Get("B4XVAnchor")
End Sub

Sub getB4XHAnchor As String
    Return CustProps.Get("B4XHAnchor")
End Sub

Sub getB4xHeight As String
    Return CustProps.Get("B4XHeight") & "px"
End Sub

Sub getB4XWidth As String
    Return CustProps.Get("B4XWidth") & "px"
End Sub

Sub getB4XTop As String
    Return CustProps.Get("B4XTop") & "px"
End Sub

Sub getB4XLeft As String
    Return CustProps.Get("B4XLeft") & "px"
End Sub

Interestingly enough, if I want to store the "state" of the custom element, I can just add another sub, to convert the whole thing to json.

1692856550807.png


When used, I do a log(...ToJSON) and whala!

1692856601646.png
 

Attachments

  • Demo01.zip
    12.9 KB · Views: 174
Last edited:

Mashiane

Expert
Licensed User
Longtime User
As noted above, we are able to read the exact TOP, LEFT, WIDTH, HEIGHT, HANCHOR and VANCHOR of the element. Let's use these to place out layout in our designer.

To achieve this, we will use the "style" attribute. As we want these to be placed at the actual positions that are based on the abstract designer placement, our "position" should be "absolute"

I have added a prop on the custom view called "Absolute", I read this and when set to True, change the style to take into consideration those positions and apply them.

1692857204554.png


My code in the DesignerCreateView sub includes...


1692857266621.png


This then ensures that for each placed element, when set to absolute, it uses the b4x(props) directly, and thus placing my elements EXACTLY where I placed them.
 

Mashiane

Expert
Licensed User
Longtime User
Anchors

These are rather interesting and Im still exploring how I can make sense and translate them into usable code. What I know so far is that. They mean 0, 1, 2.

1692857443017.png


1692857562266.png
= 0

1692857533908.png
= 1

1692857585309.png
= 2

Same applies to the VAnchors

1692857618869.png
= 0

1692857641231.png
= 1

1692857662686.png
= 2

And yes, changing them DOES change the placement of your element on the final app. For Example...

The placement of SHIonBaseElement1 when anchors are 2 and 1

1692857792423.png


Becomes:

1692857868676.png


I will update this post as soon as I find my way around the anchors. For now, I will attach the demo project.
 

Attachments

  • 1692857757091.png
    1692857757091.png
    30.3 KB · Views: 107

Mashiane

Expert
Licensed User
Longtime User
For now, lets create a copy of our element via code and use the ToJSON content.

I have placed another element on the abstract designer, named lblCode.

1692858788813.png


The output is:

1692858764499.png


I then generate members to access it. We will copy SHIonBaseElement1 to lblCode, via code.

We update our code:

B4X:
'get the state of the component
    Dim sCopy As String = SHIonBaseElement1.ToJSON
    'define a new component
    Dim elCopy As SHIonBaseElement
    elCopy.Initialize(Me, "elCopy", "elCopy")
    'use add to parent to inject the copied state.
    elCopy.AddToParentJSON(lblCode.Here, sCopy)

When ran, the final result is.

1692858963130.png


We achieved this by 1. copying the state of the previous component and 2. using a AddToParentJSON sub, which is an enhanced AddToParent but to use JSON string.

B4X:
Public Sub AddToParentJSON(targetID As String, sJSON As String)
    targetID = CleanID(targetID)
    mTarget = BANano.GetElement("#" & targetID)
    Dim props As Map = BANano.FromJson(sJSON)
    DesignerCreateView(mTarget, props)
End Sub

The original AddToParent is

B4X:
'add this element to an existing parent element
Public Sub AddToParent(targetID As String, props As Map)
    targetID = CleanID(targetID)
    mTarget = BANano.GetElement("#" & targetID)
    DesignerCreateView(mTarget, props)
End Sub

Code on first post updated:
 
Top