Java Question Using setContentView with B4A Activity

Roger Garstang

Well-Known Member
Licensed User
Longtime User
Ok, I know the extends Activity part is wrong (Both because I want to use the current Activity in B4A and the XML grabs all of it for a massive dropdown list in B4A), but what I'm trying to do is make a library to build my layout by code and use Relative Layout. Not much code as I'm just testing how it can work, but how do I use setContentView with a B4A Activity? I can't find it in any B4A classes and it is only available when extending Activity.

addView wouldn't work with the B4A view wrapper either...I had code to check if initialized and such assuming they would need at least that. Martin had some code where he successfully pulled in an XML layout at http://www.b4x.com/forum/bugs-wishlist/18717-wish-automatically-save-restore-view-state.html which I may do if this doesn't work, but I'd really like to just make a library to add the views by code.

B4X:
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.Permissions;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import android.app.Activity;

@ActivityObject // Marking your class with this annotation will make it an activity object.
@ShortName("RelativeLayout") // this is the name as it appear on the IDE
@Permissions(values = {}) // Permissions must always be declared otherwise your app or library won’t work.
@Author("Roger Garstang")
@Version(1f) // the version
public class RelativeLayout extends Activity {
   private android.widget.RelativeLayout myLayout = new android.widget.RelativeLayout(BA.applicationContext);

   public RelativeLayout() {
      
   }
   
   public void AddView(android.view.View View) {
      myLayout.addView(View);
   }
   
   public void DrawLayout() {
      setContentView(myLayout);
   }
}
 

warwound

Expert
Licensed User
Longtime User
I think you've got a couple of options here...

You can create an entire activity layout file in XML and then somewhere in your library code have a method:

B4X:
public void setContentView(BA pBA, String LayoutName){
   pBA.activity.setContentView(BA.applicationContext.getResources().getIdentifier(LayoutName, "layout", BA.packageName));
}

Here the BA.activity property is how you get access to the setContentView method.

Alternatively you can sub-class RelativeLayout:

B4X:
import android.widget.RelativeLayout;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.Hide;

@Hide   //   stops this class being included in the library xml file
public class MyRelativeLayout extends RelativeLayout {

   private BA mBA;
   private String mEventName;
   
   public MyRelativeLayout(BA pBA, String pEventName) {
      super(pBA.context);
      
      mBA=pBA;
      mEventName=pEventName;
      
      //   now create/initialize/customise the default RelativeLayout as required

      //   https://www.google.co.uk/search?q=android+extend+relativelayout&ie=UTF-8&oe=UTF-8
   }
}

And use ViewWrapper to enable you to use your sub-class in B4A:

B4X:
import android.view.View;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.objects.ViewWrapper;

@ActivityObject
@ShortName("MyRelativeLayout")
@Version(1.00f)
public class MyRelativeLayoutWrapper extends ViewWrapper<MyRelativeLayout> {

   @Override
   public void innerInitialize(BA pBA, String pEventName, boolean pKeepOldObject) {
      if (!pKeepOldObject) {
         setObject(new MyRelativeLayout(pBA, pEventName));
      }
      super.innerInitialize(pBA, pEventName, true);
   }

   //   a couple of example methods
   public void Hide(){
      getObject().setVisibility(View.GONE);
   }

   public void Show(){
      getObject().setVisibility(View.VISIBLE);
   }
}

Now in B4A you'd do something like:

B4X:
Sub Process_Globals
End Sub

Sub Globals
   Dim MyRelativeLayout1 As MyRelativeLayout
End Sub

Sub Activity_Create(FirstTime As Boolean)
   MyRelativeLayout1.Initialize("MyRelativeLayout1")
   Activity.AddView(MyRelativeLayout1, 0, 0,100%x,100%y)
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

Using setContentView look much easier but how will you reference and interact with the Views in the layout file that you load (your dropdownlist)?
How will you get a selected value - you'd still need additional java library code to enable your B4A code to reference and interact with the layout.

Sub-classing RelativeLayout is the more elegant way to go.
You'd add what ever methods you need to the sub-class (such as your AddView method), and then add methods to the ViewWrapper to wrap the sub-class methods.
So i'd recommend the sub-class approach - get this to work and you'll have java skills to sub-class other useful classes and wrap them into B4A friendly libraries.

Martin.
 

Roger Garstang

Well-Known Member
Licensed User
Longtime User
Thanks Martin. Gives me something to chew on Monday. The BA object is something that needs explained more in the How to make a Library documents. It mentions it as being something that is hidden from the user in the B4A IDE, so it sounds like it is a special object that when B4A Java code sees it gets passed the BA object kind of behind the scenes. Both code examples should be useful as I may want both capabilities of XML loading and by code layouts.

Once I get the hang of how things interact the main library I want to build is an improved camera library. Been 10 years since I've used Java and hated it then, but it isn't that much different than C#. It has came a long way in ease of use since last used too.
 

warwound

Expert
Licensed User
Longtime User
I'd picture the BA object as a collection of helper methods and assorted properties that belong to various Android Application level classes.

The BA object is of little use within the B4A IDE i think, but within a library object it gives us essential access to various native Android classes with a single BA interface.

Keep this thread updated on your progress!

Martin.
 

Roger Garstang

Well-Known Member
Licensed User
Longtime User
Nevermind...copy and paste error in my last lines. I also had code in there to create ids for views if you get emails with what I had or saw it before this...I never got a 100% answer from Erel though on them. I took the code out and it still works, so B4A must give them IDs.

Corrected code is below (Still rough draft and no comments yet)-

B4X:
package net.garstangs.layout.relative;

import android.view.View;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.Hide;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.objects.ViewWrapper;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.Permissions;

@Permissions(values = {}) // Permissions must always be declared otherwise your app or library won’t work.
@Author("Roger Garstang")

@ActivityObject
@ShortName("RelativeLayout")
@Version(1.00f)
public class MyRelativeLayoutWrapper extends ViewWrapper<MyRelativeLayout> {
   
   public int ViewLeftPadding = 0;
   public int ViewTopPadding = 0;
   public int ViewRightPadding = 0;
   public int ViewBottomPadding = 0;
   public int yAlignParentTop = RelativeLayout.ALIGN_PARENT_TOP; // 10
   public int yAlignParentCentVert = RelativeLayout.CENTER_VERTICAL; // 15
   public int yAlignViewTop = RelativeLayout.ALIGN_TOP; // 6
   public int yAlignViewBottom = RelativeLayout.ALIGN_BOTTOM; // 8
   public int yAlignViewBaseline = RelativeLayout.ALIGN_BASELINE; // 4
   public int yAlignAboveView = RelativeLayout.ABOVE; // 2
   public int yAlignBelowView = RelativeLayout.BELOW; // 3
   public int xAlignParentLeft = RelativeLayout.ALIGN_PARENT_LEFT; // 9
   public int xAlignParentRight = RelativeLayout.ALIGN_PARENT_RIGHT; // 11
   public int xAlignParentCentHorz = RelativeLayout.CENTER_HORIZONTAL; // 14
   public int xAlignViewLeft = RelativeLayout.ALIGN_LEFT; // 5
   public int xAlignViewRight = RelativeLayout.ALIGN_RIGHT; // 7
   public int xAlignLeftOfView = RelativeLayout.LEFT_OF; // 0
   public int xAlignRightOfView = RelativeLayout.RIGHT_OF; // 1
   public int sizeWrapContent = LayoutParams.WRAP_CONTENT;
   public int sizeMatchParent = LayoutParams.MATCH_PARENT;

    @Override
    @Hide
    public void innerInitialize(BA pBA, String pEventName, boolean pKeepOldObject) {
        if (!pKeepOldObject) {
            setObject(new MyRelativeLayout(pBA));
        }
        super.innerInitialize(pBA, pEventName, true);
    }

    @Override
   public void Initialize(BA ba, String EventPrefix) {
      super.Initialize(ba, EventPrefix);
   }

   public void Hide(){
        getObject().setVisibility(View.GONE);
    }

    public void Show(){
        getObject().setVisibility(View.VISIBLE);
    }
    
    public void AddView(View NewView, int Width, int Height, int xAlign, View xView, int yAlign, View yView){
       RelativeLayout.LayoutParams myLayoutParams = new RelativeLayout.LayoutParams(Width, Height);
       myLayoutParams.setMargins(ViewLeftPadding, ViewTopPadding, ViewRightPadding, ViewBottomPadding);
       if (xView == null) { // Assume Parent Align
          if (xAlign == xAlignParentLeft) myLayoutParams.addRule(xAlignParentLeft);
          if (xAlign == xAlignParentRight) myLayoutParams.addRule(xAlignParentRight);
          if (xAlign == xAlignParentCentHorz) myLayoutParams.addRule(xAlignParentCentHorz);
       }
       else {
          if (xAlign == xAlignViewLeft) myLayoutParams.addRule(xAlignViewLeft, xView.getId());
          if (xAlign == xAlignViewRight) myLayoutParams.addRule(xAlignViewRight, xView.getId());
          if (xAlign == xAlignLeftOfView) myLayoutParams.addRule(xAlignLeftOfView, xView.getId());
          if (xAlign == xAlignRightOfView) myLayoutParams.addRule(xAlignRightOfView, xView.getId());
      }
       if (yView == null) { // Assume Parent Align
          if (yAlign == yAlignParentTop) myLayoutParams.addRule(yAlignParentTop);
          if (yAlign == yAlignParentCentVert) myLayoutParams.addRule(yAlignParentCentVert);
       }
       else {
          if (yAlign == yAlignAboveView) myLayoutParams.addRule(yAlignAboveView, yView.getId());
          if (yAlign == yAlignBelowView) myLayoutParams.addRule(yAlignBelowView, yView.getId());
          if (yAlign == yAlignViewTop) myLayoutParams.addRule(yAlignViewTop, yView.getId());
          if (yAlign == yAlignViewBottom) myLayoutParams.addRule(yAlignViewBottom, yView.getId());
          if (yAlign == yAlignViewBaseline) myLayoutParams.addRule(yAlignViewBaseline, yView.getId());
      }
       NewView.setLayoutParams(myLayoutParams);
       getObject().addView(NewView);
    }
}
 
Last edited:
Top