Android Code Snippet [B4X] CreateB4XFont

Function to create custom B4XFont for all platforms.

I don't know if it is the best possible nor if it works perfectly with B4I, as I cannot test it, therefore suggestions/improvements will certainly be welcome.

B4XPages test project attached.

B4X:
'NativeFontSize is needed only for B4J or B4I.
'Of course you have to pass a dummy-not-used value if you are developing in B4A.
'It uses XUI (also FX in B4J) which must be declared at module level.
Public Sub CreateB4XFont(FontFileName As String, FontSize As Float, NativeFontSize As Float) As B4XFont
    #IF B4A
        Return xui.CreateFont(Typeface.LoadFromAssets(FontFileName), FontSize)
    #ELSE IF B4I
        Return xui.CreateFont(Font.CreateNew2(FontFileName, NativeFontSize), FontSize)
    #ELSE ' B4J
        Return xui.CreateFont(FX.LoadFont(File.DirAssets, FontFileName, NativeFontSize), FontSize)
    #END IF
End Sub
 

Attachments

  • CreateB4XFontTest.zip
    59.1 KB · Views: 302
Last edited:

aeric

Expert
Licensed User
Longtime User
Thanks for sharing. I have posted my solution here.

 

aeric

Expert
Licensed User
Longtime User
I don't have B4I; I had found that "directive" but hoped it was no longer needed. Is it?
No, it is required in B4i (Main module):
B4X:
#Region  Project Attributes
    #AppFont: D3-Biscuitism-Bold.ttf
#End Region
Take note: B4i doesn't like filename contains underscore "_", so please use filename with dash (hyphen) "-".
It is better use filename with dash for all 3 platforms.

To call the Sub, B4i doesn't require file extension:
B4X:
#If B4i
    Label1.Font = CreateB4XFont("D3-Biscuitism-Bold", 30, 30)
#Else
    Label1.Font = CreateB4XFont("D3_Biscuitism_Bold.ttf", 30, 30)
#End If

So, the Sub is simplified as below:
B4X:
'NativeFontSize is needed only for B4J or B4I.
Public Sub CreateB4XFont(FontFileName As String, FontSize As Float, NativeFontSize As Float) As B4XFont
    #If B4A
        Return xui.CreateFont(Typeface.LoadFromAssets(FontFileName), FontSize)
    #Else If B4i
        Return xui.CreateFont(Font.CreateNew2(FontFileName, NativeFontSize), FontSize)
    #Else    ' B4J
        Return xui.CreateFont(fx.LoadFont(File.DirAssets, FontFileName, NativeFontSize), FontSize)
    #End If
End Sub
 

Attachments

  • CreateB4XFontTest.zip
    43.3 KB · Views: 210

LucaMs

Expert
Licensed User
Longtime User
To call the Sub, B4i doesn't require file extension:
and this is because there is that directive, otherwise it could not distinguish two files with identical name and different extension.

The need for that directive makes it impossible to load at runtime font files that are downloaded by the app-user; however I think this is a rather rare case.

---

You have removed the local jfx declaration but instead it would be better to keep it and add xui, because the module to which the routine will be added does not necessarily have them (a B4XPage does not have FX by default, a B4J class does not have XUI by default).

If you want to remove both, it is better to specify all this in the description of the function.

---

You've synthesized the B4J version and I like it; I don't like direct and tripled Return because removing the return variable can make debugging less easy.
P.S.
Thinking better, since I'm just a little more awake now (it's sunrise), in this case an error could only be caused by LoadFont, so you can do without that variable.
But never do it again :mad:πŸ˜„, I mean no longer use that "Return technique" that is not at the bottom of the function; it is deprecable, in my opinion.

Changed.
 
Last edited:

TILogistic

Expert
Licensed User
Longtime User
No, it is required in B4i (Main module):
B4X:
#Region  Project Attributes
    #AppFont: D3-Biscuitism-Bold.ttf
#End Region
Take note: B4i doesn't like filename contains underscore "_", so please use filename with dash (hyphen) "-".
It is better use filename with dash for all 3 platforms.

To call the Sub, B4i doesn't require file extension:
B4X:
#If B4i
    Label1.Font = CreateB4XFont("D3-Biscuitism-Bold", 30, 30)
#Else
    Label1.Font = CreateB4XFont("D3_Biscuitism_Bold.ttf", 30, 30)
#End If

So, the Sub is simplified as below:
B4X:
'NativeFontSize is needed only for B4J or B4I.
Public Sub CreateB4XFont(FontFileName As String, FontSize As Float, NativeFontSize As Float) As B4XFont
    #If B4A
        Return xui.CreateFont(Typeface.LoadFromAssets(FontFileName), FontSize)
    #Else If B4i
        Return xui.CreateFont(Font.CreateNew2(FontFileName, NativeFontSize), FontSize)
    #Else    ' B4J
        Return xui.CreateFont(fx.LoadFont(File.DirAssets, FontFileName, NativeFontSize), FontSize)
    #End If
End Sub
?
 

LucaMs

Expert
Licensed User
Longtime User
?
Good "news", so you can download a font file and use it, at runtime.
The bad news is... why did you make me struggle when you could have published the snippet? πŸ˜„
 

aeric

Expert
Licensed User
Longtime User
and this is because there is that directive, otherwise it could not distinguish two files with identical name and different extension.

The need for that directive makes it impossible to load at runtime font files that are downloaded by the app-user; however I think this is a rather rare case.
I tried the whole morning and still can't get it work without the directive.

You have removed the local jfx declaration but instead it would be better to keep it and add xui, because the module to which the routine will be added does not necessarily have them (a B4XPage does not have FX by default, a B4J class does not have XUI by default).

If you want to remove both, it is better to specify all this in the description of the function.
Sorry, I didn't remove it but put it on top.
B4X:
#If B4J
Private fx As JFX
#End If

You've synthesized the B4J version and I like it; I don't like direct and tripled Return because removing the return variable can make debugging less easy.
P.S.
Thinking better, since I'm just a little more awake now (it's sunrise), in this case an error could only be caused by LoadFont, so you can do without that variable.
But never do it again :mad:πŸ˜„, I mean no longer use that "Return technique" that is not at the bottom of the function; it is deprecable, in my opinion.
Just a personal preference.

Good "news", so you can download a font file and use it, at runtime.
@oparra , I can't use your code for B4i.
I get the error:
Object was not initialized (UIFont)

B4X:
Application_Start
Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.
Application_Active
Error occurred on line: 60 (B4XMainPage)
Object was not initialized (UIFont)
Stack Trace: (
  CoreFoundation       F3021642-E3C0-33F8-9911-DD303A6056D0 + 1157612
  libobjc.A.dylib      objc_exception_throw + 56
  CoreFoundation       F3021642-E3C0-33F8-9911-DD303A6056D0 + 120016
  B4i Example          -[B4IObjectWrapper object] + 116
  B4i Example          -[b4i_b4xmainpage _createb4xfont::::] + 788
  B4i Example          -[b4i_b4xmainpage _button1_click:] + 368
  CoreFoundation       F3021642-E3C0-33F8-9911-DD303A6056D0 + 1175856
  CoreFoundation       F3021642-E3C0-33F8-9911-DD303A6056D0 + 8656
  B4i Example          +[B4I runDynamicMethod:method:throwErrorIfMissing:args:] + 1300
  B4i Example          -[B4IShell runMethod:] + 448
 B4i Example          -[B4IShell raiseEventImpl:method:args::] + 1648
 B4i Example          -[B4IShellBI raiseEvent:event:params:] + 1580
 B4i Example          __33-[B4I raiseUIEvent:event:params:]_block_invoke + 52
 libdispatch.dylib    AF27E74C-BE4A-3364-BB27-AED9916CE02D + 393880
 libdispatch.dylib    AF27E74C-BE4A-3364-BB27-AED9916CE02D + 397952
 libdispatch.dylib    AF27E74C-BE4A-3364-BB27-AED9916CE02D + 65628
 CoreFoundation       F3021642-E3C0-33F8-9911-DD303A6056D0 + 632288
 CoreFoundation       F3021642-E3C0-33F8-9911-DD303A6056D0 + 608904
 CoreFoundation       CFRunLoopRunSpecific + 572
 GraphicsServices     GSEventRunModal + 160
 UIKitCore            CC6E5AC7-8248-35F6-8B42-2E25C93DCF0A + 11723508
 UIKitCore            UIApplicationMain + 164
 B4i Example          main + 120
 libdyld.dylib        0B475C78-3C12-3121-B7F8-2B95B83DAF44 + 5480
)
 

aeric

Expert
Licensed User
Longtime User
It, for you lucky people πŸ˜„ :confused: who have B4I and especially expensive devices, seems to be an interesting question (open a new thread?)
No, I am not a lucky people. I purchase B4i with the donation from the members so I can also help the members. πŸ˜‹ (I purchased the license once and the renewal price has been much discounted)
 

LucaMs

Expert
Licensed User
Longtime User
No, I am not a lucky people. I purchase B4i with the donation from the members so I can also help the members. πŸ˜‹
I noticed only now that I received 3 donations that my email site had automatically moved to a different folder than "normal email", so I made a bad impression, just thanking today :(

But with those 3 donations I was able to pay the fee for my Internet connection!

Even if I could buy the B4I license, I certainly couldn't buy a Mac and an iOS!

:(

As I have already written, and I am not ashamed of it since this depends on various factors... (ok, synthesis), soon I will have to go to beg; but we are in 2022, so maybe it will be better if I publish an app to ask for it, at least I won't get cold on the street πŸ˜„:(:(:(
 

Sandman

Expert
Licensed User
Longtime User
Not exactly; having a single "exit point" is a known good habit, not my preference.
My post is (also) off topic, sorry about that. I just wanted to leave this here:

(I'd recommend opening a new thread in Chit Chat if you want to discuss this more. Also sorry about the Medium preview, I don't know how to disable it, the forum does it by itself.)
 
Top