Android Tutorial Embedding native android views or widgets in b4a

This is done by inflating xml files that are intended for native Android apps. Since the xml code contains the view, it will be shown (and can be manipulated) in b4a code.
Let's take the following xml file:
XML:
 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="20dp"
    android:background="#FFFFFF">

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/swipetorefresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:id="@+id/RsListView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:dividerHeight="1dp"
            android:divider="#D3D3D3"/>

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

</RelativeLayout>
Which has 'swiperefreshlayout' that is not a native b4a view.
But stop here! We need to add the relevant Android library from SDK manager.
In this case we add the line:
B4X:
#AdditionalJar:androidx.swiperefreshlayout:swiperefreshlayout
Now we established the swipetorefreshlayout, and are ready to show it. A Listview is included inside it as shown above.
Now, we need a function to inflate the xml file into a view that can be added to the activity or Root.
Here is the inflator function:
B4X:
Sub InflateLayout(LayoutName As String, Parent As Panel) As View
    Dim context As JavaObject
    context.InitializeContext

    ' Get Resources and LayoutInflater
    Dim resources As JavaObject
    resources = context.RunMethod("getResources", Null)
   
    Dim inflater As JavaObject
    inflater = context.RunMethod("getSystemService", Array("layout_inflater"))

    ' Get the resource ID (e.g., R.layout.my_layout)
    Dim resName As String = LayoutName.Replace(".xml", "") ' Remove .xml extension
    Dim resID As Int = resources.RunMethod("getIdentifier", Array(resName, "layout",Application.PackageName))
   
    If resID = 0 Then
        Log("Error: Layout file not found in resources - " & LayoutName)
        Return Null
    End If

    ' Inflate using the resource ID
    Dim view As JavaObject
    view = inflater.RunMethod("inflate", Array(resID, Parent, False))


    Return view
End Sub
It produces a view from relevant xml code.
Let's call the inflated view 'inflatedView' and add it to Root ( in B4XPages)
B4X:
'Inflate the XML layout
    Dim inflatedView As View = InflateLayout("main", Root)

    If inflatedView.IsInitialized = False Then
        Log("ERROR: main.xml could not be inflated")
        Return
    End If

    Root.AddView(inflatedView, 0, 0, 100%x, 100%y)
Of course we should have created the xml file in manifest editor beforehand as follows:
XML:
CreateResource(layout, main.xml, <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="20dp"
    android:background="#FFFFFF">

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/swipetorefresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:id="@+id/RsListView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:dividerHeight="1dp"
            android:divider="#D3D3D3"/>

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

</RelativeLayout>)
This will create main.xml file in res/layout folder.
Ready to get the swipeToRefresh view id from the inflatedView. For that, we have the following Sub:
B4X:
Sub GetResourceId(name As String, resType As String) As Int
    Dim jo As JavaObject
    jo.InitializeContext
    Return jo.RunMethodJO("getResources", Null).RunMethod("getIdentifier", _
        Array(name, resType, Application.PackageName))
End Sub
Then:
B4X:
'Find SwipeRefreshLayout inside the inflated XML
    Dim rootJO As JavaObject = inflatedView
    Dim swipeJO As JavaObject = rootJO.RunMethod("findViewById", Array(swipeId))
Next step is to create event that fires when we refresh the view
B4X:
'Create listener
    Dim event As Object = swipeJO.CreateEventFromUI("androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener","onRefreshing",Null)

    swipeJO.RunMethod("setOnRefreshListener", Array(event))

'
''
Private Sub onRefreshing_Event(MethodName As String, Args() As Object)
    Log($"Refreshing:${MethodName}"$)
'    lottieAnimationView.RunMethod("playAnimation", Null)
    Update
 
End Sub
Private Sub Update
    ' When refresh is done:
    swiperefresh.As(JavaObject).RunMethod("setRefreshing", Array(False))
    Log("Refresh done")
   
End Sub
And we are done!
 

Attachments

  • swipetorefresh.gif
    swipetorefresh.gif
    272.9 KB · Views: 93
Last edited:

Mashiane

Expert
Licensed User
Longtime User
This is done by inflating xml files that are intended for native Android apps. Since the xml code contains the view, it will be shown (and can be manipulated) in b4a code.
Let's take the following xml file:
XML:
 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="20dp"
    android:background="#FFFFFF">

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/swipetorefresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:id="@+id/RsListView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:dividerHeight="1dp"
            android:divider="#D3D3D3"/>

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

</RelativeLayout>
Which has 'swiperefreshlayout' that is not a native b4a view.
But stop here! We need to add the relevant Android library from SDK manager.
In this case we add the line:
B4X:
#AdditionalJar:androidx.swiperefreshlayout:swiperefreshlayout
Now we established the swipetorefreshlayout, and are ready to show it. A Listview is included inside it as shown above.
Now, we need a function to inflate the xml file into a view that can be added to the activity or Root.
Here is the inflator function:
B4X:
Sub InflateLayout(LayoutName As String, Parent As Panel) As View
    Dim context As JavaObject
    context.InitializeContext

    ' Get Resources and LayoutInflater
    Dim resources As JavaObject
    resources = context.RunMethod("getResources", Null)
  
    Dim inflater As JavaObject
    inflater = context.RunMethod("getSystemService", Array("layout_inflater"))

    ' Get the resource ID (e.g., R.layout.my_layout)
    Dim resName As String = LayoutName.Replace(".xml", "") ' Remove .xml extension
    Dim resID As Int = resources.RunMethod("getIdentifier", Array(resName, "layout",Application.PackageName))
  
    If resID = 0 Then
        Log("Error: Layout file not found in resources - " & LayoutName)
        Return Null
    End If

    ' Inflate using the resource ID
    Dim view As JavaObject
    view = inflater.RunMethod("inflate", Array(resID, Parent, False))


    Return view
End Sub
It produces a view from relevant xml code.
Let's call the inflated view 'inflatedView' and add it to Root ( in B4XPages)
B4X:
'Inflate the XML layout
    Dim inflatedView As View = InflateLayout("main", Root)

    If inflatedView.IsInitialized = False Then
        Log("ERROR: main.xml could not be inflated")
        Return
    End If

    Root.AddView(inflatedView, 0, 0, 100%x, 100%y)
Of course we should have created the xml file in manifest editor beforehand as follows:
XML:
CreateResource(layout, main.xml, <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="20dp"
    android:background="#FFFFFF">

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/swipetorefresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:id="@+id/RsListView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:dividerHeight="1dp"
            android:divider="#D3D3D3"/>

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

</RelativeLayout>)
This will create main.xml file in res/layout folder.
Ready to get the swipeToRefresh view id from the inflatedView. For that, we have the following Sub:
B4X:
Sub GetResourceId(name As String, resType As String) As Int
    Dim jo As JavaObject
    jo.InitializeContext
    Return jo.RunMethodJO("getResources", Null).RunMethod("getIdentifier", _
        Array(name, resType, Application.PackageName))
End Sub
Then:
B4X:
'Find SwipeRefreshLayout inside the inflated XML
    Dim rootJO As JavaObject = inflatedView
    Dim swipeJO As JavaObject = rootJO.RunMethod("findViewById", Array(swipeId))
Next step is to create event that fires when we refresh the view
B4X:
'Create listener
    Dim event As Object = swipeJO.CreateEventFromUI("androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener","onRefreshing",Null)

    swipeJO.RunMethod("setOnRefreshListener", Array(event))

'
''
Private Sub onRefreshing_Event(MethodName As String, Args() As Object)
    Log($"Refreshing:${MethodName}"$)
'    lottieAnimationView.RunMethod("playAnimation", Null)
    Update
 
End Sub
Private Sub Update
    ' When refresh is done:
    swiperefresh.As(JavaObject).RunMethod("setRefreshing", Array(False))
    Log("Refresh done")
  
End Sub
And we are done!
I kindly request that you please provide a simple working b4a project for this. Its a very informative tutorial and an example project would add a lot of value.

Its just a beautiful thing that the b4x ecosystem is plug-n-play with these things. One can create their layouts in android studio and or even from figma to android studio and then to b4x.

Thanks again for the informative code.
 

jkhazraji

Active Member
Licensed User
Longtime User
I kindly request that you please provide a simple working b4a project for this. Its a very informative tutorial and an example project would add a lot of value.

Its just a beautiful thing that the b4x ecosystem is plug-n-play with these things. One can create their layouts in android studio and or even from figma to android studio and then to b4x.

Thanks again for the informative code.
Thanks for your compliment! An example is found on Github
 

jkhazraji

Active Member
Licensed User
Longtime User
Its just a beautiful thing that the b4x ecosystem is plug-n-play with these things. One can create their layouts in android studio and or even from figma to android studio and then to b4x.
That is one of the great merits of b4a. It provides power and flexibility in a platform that is friendly to accept components from Android studio just by supplying xml settings and proper modifications and imports!
 
Top