Java Question Loading Activity layout from additional library

itayl

Member
Licensed User
Longtime User
Hi,
I was developing the library wrapper to use from b4a and faced a problem:
I need to set the content view for the activity from library java code, I know that I can use read-only xml layout and use it, but since most b4a-developers are using Designer tool and .bal-layouts I am wondering:
How the developer can add his custom .bal-layout to the activity if it's content view was set from the library?
My guess was somehow use a Panel, load custom layout to the panel and then add it to activity, something like this:

B4X:
Sub Activity_Create(FirstTime As Boolean)   
   MyLibrary.init("xxxxxxxx") 'setContentView(id) is done there

   Dim developersLayout As Panel
   developersLayout .LoadLayout("Main")   
   Activity.AddView(developersLayout , 0, 0, 0, 0)
End Sub

But I'm still getting "Should be initialized (Panel)" error. As I understood from documentation the views shouldn't be initialized if they're being loaded from layout.
Any help with that will be appreciated, thanks
 

thedesolatesoul

Expert
Licensed User
Longtime User
But I'm still getting "Should be initialized (Panel)" error. As I understood from documentation the views shouldn't be initialized if they're being loaded from layout.
Any help with that will be appreciated, thanks
But here, your panel is not being loaded from a layout. (A layout is being loaded inside the panel!)
So you still need to initialize the panel.
 

itayl

Member
Licensed User
Longtime User
Thanks for your answer.

I added the initialize line and now it looks like this:
B4X:
Sub Activity_Create(FirstTime As Boolean)   
   MyLibrary.init("xxxxxxxx") 'setContentView(id) is done there

   Dim developersLayout As Panel
        developersLayout.Initialize("developersLayout")
   developersLayout.LoadLayout("Main")   
   Activity.AddView(developersLayout, 10dip, 10dip, 500dip, 200dip)
End Sub

Error is gone, but the Panel doesn't seem to be added to an Activity.
What am I missing now?
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
The B4A code looks correct. Though there should be a warning (if you run it in Debug) as you should first add the panel and only then load the layout, otherwise the panel doesn't have a known size.

The problem is in the Java code. You removed the main activity ViewGroup. The call Activity.AddView will add the view to a hidden view instead of the correct one.

Why do you need to call setContentView? Can't you add your custom view to the main view group?
 

itayl

Member
Licensed User
Longtime User
The B4A code looks correct. Though there should be a warning (if you run it in Debug) as you should first add the panel and only then load the layout, otherwise the panel doesn't have a known size.

The problem is in the Java code. You removed the main activity ViewGroup. The call Activity.AddView will add the view to a hidden view instead of the correct one.

Why do you need to call setContentView? Can't you add your custom view to the main view group?

The setContentView call is done inside the library, for which I'm creating a wrapper. So in regular Android applications the library initialization replaces the setContentView(id) in onCreate.
To init the library from Java I can only pass the activity and it's content layout resource id and the library is setting activity's content with additional UI elements around.
 

itayl

Member
Licensed User
Longtime User
1. Make sure that your class is annotated with @ActivityObject.
2 Try to add ba.vg to the main view. ba.vg is the main B4A Activity view.

1. It is.
2. Not sure that I understand your thought.
At the moment I have b4a code:
B4X:
Sub Activity_Create(FirstTime As Boolean)    
    MyLibrary.init("xxxxxxxx") 'setContentView(id) is done there

    Dim developersLayout As Panel
    developersLayout.Initialize("developersLayout")
    Activity.AddView(developersLayout, 10dip, 10dip, 500dip, 200dip)
    developersLayout.LoadLayout("Main")
End Sub

In Java(MyLybrary class):
B4X:
private Activity mBaActivity;

public void init(BA ba, String developerToken) {
   mBaActivity = ba.activity;
   MyLibraryJava.init(mBaActivity, developerToken);
    int layoutId = mBaActivity.getResources().getIdentifier("activity_main", "layout", BA.packageName);
   MyLibraryJava.getCustomView(mBaActivity, layoutId);
}

So as you can see I'm already using the ba.activity there and setting it's content view. Not sure how can I add ba.vg view there again.

Edit: as I mensioned earlier, the setContentView(id) is called from the MyLibraryJava.getCustomView(mBaActivity, layoutId) for the provided activity.
 
Last edited:

itayl

Member
Licensed User
Longtime User
Ok, its seems like I've managed to achive positive result by doing this:
In B4A:
B4X:
Sub Activity_Create(FirstTime As Boolean)    
    Dim developersLayout As Panel
    developersLayout.Initialize("developersLayout")
    developersLayout.LoadLayout("Main")

    MyLibrary.init("xxxxxxxx", developersLayout)
End Sub

In Java(MyLybrary class):
B4X:
private Activity mBaActivity;

public void init(BA ba, String developerToken, View developerView) {
   mBaActivity = ba.activity;
   MyLibraryJava.init(mBaActivity, developerToken);
   int layoutId = mBaActivity.getResources().getIdentifier("activity_main", "layout", BA.packageName);
   MyLibraryJava.getCustomView(mBaActivity, layoutId);
   // add developer's view to container
   int containerLayoutId = mBaActivity.getResources().getIdentifier("container", "id", BA.packageName);
   LinearLayout containerView = (LinearLayout) mBaActivity.findViewById(containerLayoutId);   
   containerView.addView(developerView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}

So I'm initializing and loading developer's layout to the Panel and then just add it to the main container of the activity.
What do you think, would it be acceptable for most b4a developers to use a custom library this way?
 

itayl

Member
Licensed User
Longtime User
What is this main view?

developersLayout.LoadLayout("Main") - it's a main.bal which contains any developer-determined layout. In my test-case it's just few Buttons and a Label.

Have you tried to add ba.vg to containerView?

You're right, it's works. So probably I should get rid of "View developerView" method parameter and add my Panel from B4A code:
B4X:
Sub Activity_Create(FirstTime As Boolean)    
    Dim developersLayout As Panel
    developersLayout.Initialize("developersLayout")
    Activity.AddView(developersLayout, 0, 0, 100%x, 100%y)
    developersLayout.LoadLayout("Main")

    MyLibrary.init("xxxxxxxx")
End Sub

And then just use ba.vg instead of "developerView" in java:
B4X:
 // add developer's view to container
    int containerLayoutId = mBaActivity.getResources().getIdentifier("container", "id", BA.packageName);
    LinearLayout containerView = (LinearLayout) mBaActivity.findViewById(containerLayoutId);
    containerView.addView(ba.vg, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
 
Last edited:
Top