B4A Library [custom view] AutoTextSizeLabel

Status
Not open for further replies.
When you set the text of this custom label the text size is automatically modified to the largest possible size so that all the text is visible.

SS-2013-06-30_11.49.54.png


To use this view in your project, you should take the AutoTextSizeLabel class from the attached example and add it to your project. You should then add a Custom View with the designer and set its type to this class.

The following libraries are required:
- JavaObject
- StringUtils
 

Attachments

  • AutoTextSizeLabel.zip
    8.5 KB · Views: 2,217
Last edited:

chrjak

Active Member
Licensed User
Longtime User
I can't use the class. A project isn't necessary! All you'll see is nothing. because nothing changes

Please look at my code snippet in my project or in this thread! This would be soooo much easier :/
 

Andrew Gray

Member
Licensed User
Longtime User
On some devices, the following line in DesignerCreateView throws an error saying width and height must be > 0:

B4X:
bmp.InitializeMutable(1dip,1dip)

Changing the units to absolute pixels seems to fix this:

B4X:
bmp.InitializeMutable(1,1)
 

peacemaker

Expert
Licensed User
Longtime User
Under Android 2.3 - the multiline text is not shown well - only first line is visible :(
 

RodrigoVitachi

Member
Licensed User
Longtime User
I needed something different for the "multiplelines" option, based on lenght instead of looking for CRLF, so if anyone else needs to break lines based on lenght like me, just change this line.
Line 28 : From - Dim multipleLines As Boolean = mLbl.Text.Contains(CRLF)
Line 28: To - Dim multipleLines As Boolean = mLbl.Text.Length > 30
Where 30 is your lenght limit to start breaking lines.
 

BarryW

Active Member
Licensed User
Longtime User
When you set the text of this custom label the text size is automatically modified to the largest possible size so that all the text is visible.

SS-2013-06-30_11.49.54.png


To use this view in your project, you should take the AutoTextSizeLabel class from the attached example and add it to your project. You should then add a Custom View with the designer and set its type to this class.

The following libraries are required:
- Reflection
- StringUtils

How to add this view manually like Activity.AddView(AutoSizeText, 0, 0, 100dip, 100dip)... It seem not working... Also i tried to add this view on UltimateListView but its not working... Tnx
 

francoisg

Active Member
Licensed User
Longtime User
Hi,
I have created a custom view - works 100%
Now I want to compile it in a library and use it from there. The problem is that the class does not show up in the designer when I want to set the custom view type.

Do I need to do something special for using a custom view class in a library (By the way, I am using B4A version 5.5)?
 
Last edited:

francoisg

Active Member
Licensed User
Longtime User
Ok, problem solved, the DesignerCreateView sub was marked as private. My bad!!!! :oops:
Thank you Klaus for pointing me in the right direction!!!
 
Last edited:

Dave O

Well-Known Member
Licensed User
Longtime User
I'm showing a label that uses large text sizes (e.g. 150), and unfortunately the loop that determines the size takes too long to run - it makes the app freeze for several seconds. I assume that the MeasureStringWidth is relatively expensive when iterating like this.

I solved this by replacing the loop with a two-part calculation:
  1. Draw a sample string at a given font size, remembering its rendered width.
  1. Each time the text changes, calculate the actual string's font size by scaling it up/down according to how much longer the actual string is (# of characters) and how much wider the actual label width is.
This seems to work pretty well, and causes no perceptible pause. I suspect it's not as accurate as the looping method, but it's good enough for my use and much faster.

Here's the rough code in case you want to try it out:

B4X:
Sub Class_Globals
   ...
   Private baseTextWidth As Int
   Private const BASE_STRING As String = "234"
   Private const BASE_TEXT_SIZE As Int = 20
   ...
End Sub

Public Sub DesignerCreateView(base As Panel, lbl As Label, props As Map)
   ...
   baseTextWidth = calcBaseTextWidth(lbl.Typeface)
   setText(textLabel.Text)
End Sub

Sub calcBaseTextWidth(typefaceArg As Typeface) As Int
   Dim tempCanvas As Canvas
   tempCanvas.Initialize(basePanel)
   Return tempCanvas.MeasureStringWidth(BASE_STRING, typefaceArg, BASE_TEXT_SIZE)
End Sub

Public Sub setText(value As String)
   textLabel.Text = value
   Dim multipleLines As Boolean = textLabel.Text.Contains(CRLF)
   Dim size As Float
   If textLabel.Text = "" Then      'if blank, assume the same width as the base string, so it factors out
     size = BASE_TEXT_SIZE * (textLabel.Width / baseTextWidth)
   Else
     size = BASE_TEXT_SIZE * (BASE_STRING.Length / textLabel.Text.Length) * (textLabel.Width / baseTextWidth)
   End If
   size = Min(size, 200)                           'max font size of 200
   If CheckSize(size, multipleLines) Then size = size * 0.9     'if it wraps, reduce it a bit
   textLabel.TextSize = size
End Sub
 

Dave O

Well-Known Member
Licensed User
Longtime User
Just noticed that AutoSizeTextLabel doesn't have the same UI events (Click and LongClick) as the normal Label view.

Any plans to add these? Or should I just put a transparent panel on top and move on? :)
 

leitor79

Active Member
Licensed User
Longtime User
Hi,

I wanted to change the label for and edittext, since I'd like to use this for user input.

I've defined Private mLbl As EditText, and changed the declaration of Public Sub DesignerCreateView(Base As Panel, lbl As EditText, props As Map).

But I'm getting an error on line 23 of that sub: mLbl = lbl, immediatly when is called from Activity.Loadlayout:

B4X:
Public Sub DesignerCreateView(Base As Panel, lbl As EditText, props As Map)
   Dim bmp As Bitmap
   bmp.InitializeMutable(1dip,1dip)
   cvs.Initialize2(bmp)
   Base.AddView(lbl, 0, 0, Base.Width, Base.Height)
   Dim p As Panel
   p.Initialize("p")
   p.Color = Colors.Transparent
   Base.AddView(p, 1, 1, Base.Width, Base.Height)
   mLbl = lbl
   Dim r As Reflector
   r.Target = mLbl
   r.RunMethod4("setPadding", Array As Object(0,0,0,0), Array As String("java.lang.int", "java.lang.int", "java.lang.int", "java.lang.int"))
   r.RunMethod4("setIncludeFontPadding", Array As Object(False), Array As String("java.lang.boolean"))
   setText(mLbl.Text)
End Sub



Error occurred on line: 23 (AutoTextSizeLabel)
java.lang.IllegalArgumentException: invalid value for field
at java.lang.reflect.Field.setField(Native Method)
at java.lang.reflect.Field.set(Field.java:585)
at anywheresoftware.b4a.shell.Shell.setField(Shell.java:647)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
at eitorteam.privapp.perfil.afterFirstLayout(perfil.java:102)
at eitorteam.privapp.perfil.access$000(perfil.java:17)
at eitorteam.privapp.perfil$WaitForLayout.run(perfil.java:80)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5146)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:732)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
at dalvik.system.NativeStart.main(Native Method)

Maybe this could be done and i don't know the reason....

Thank you very much!
 

leitor79

Active Member
Licensed User
Longtime User
Hi Erel,

Yes, I've changed mLbl to an EditText. I've been making other changes so posting the actual code won't be valid. I'll copy the class with a new name and post the full code.

Thank you very much!
 

leitor79

Active Member
Licensed User
Longtime User
Here's the modified module, and here's the log:

com.myapp.autotextsizeedittext:_designercreateview, [[chat=null, config=null, cvs=anywheresoftware.b4a.objects.drawable.CanvasWrapper@4266d400
, dbutils=null, httputils2service=null, main=null
, mensajesdireccion=null, mensajesestado=null, mensajestipo=null
, mlbl=(EditText) Not initialized, mws=null, perfil=null
, register=null, starter=null, su=anywheresoftware.b4a.objects.StringUtils@4251ac38
, xmlviewex=null], (BALayout): Left=312, Top=324, Width=756, Height=138, Tag=, (TextView): Left=300, Top=300, Width=600, Height=60, Tag=, Text=, (MyMap) {defaultcolor=-984833, activity=anywheresoftware.b4a.BALayout{4247e108 V.E..... ......ID 0,0-1080,1845 #1}}]
Error occurred on line: 12 (AutoTextSizeEditText)
java.lang.IllegalArgumentException: argument 3 should have type anywheresoftware.b4a.objects.EditTextWrapper, got anywheresoftware.b4a.objects.LabelWrapper
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:697)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:339)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
at com.myapp.perfil.afterFirstLayout(perfil.java:102)
at com.myapp.perfil.access$000(perfil.java:17)
at com.myapp.perfil$WaitForLayout.run(perfil.java:80)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5146)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:732)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
at dalvik.system.NativeStart.main(Native Method)
** Activity (perfil) Resume **

Thank you very much!
 

Attachments

  • AutoTextSizeEditText.bas
    1.6 KB · Views: 338

leitor79

Active Member
Licensed User
Longtime User
It's like "props As Map" is sending properties related to labels and not related to edittexts. I don't know where to change that, If one can change it, since DesignerCreateview is called directly from LoadLayout, and there is no other files added to the project besides the class...
 
Status
Not open for further replies.
Top