Android Question EditText - Justified Alignement

js486dog

Active Member
Licensed User
Longtime User
I can use Left, Right, Center Alignement in EditText.

Please, is there some possibility to use also Justified Alignement in EditText ?
 

Attachments

  • justified alignement.png
    justified alignement.png
    2.5 KB · Views: 398

emexes

Expert
Licensed User
I think the absence of reply is a clue to the answer.

True justification, which adjusts intercharacter spacing, not just interword spacing, is no easy task. And for single lines, it doesn't make sense, hence the reason that the last line of a justified paragraph is (usually) not just justified.
 
Upvote 0

js486dog

Active Member
Licensed User
Longtime User
I think the absence of reply is a clue to the answer.

True justification, which adjusts intercharacter spacing, not just interword spacing, is no easy task. And for single lines, it doesn't make sense, hence the reason that the last line of a justified paragraph is (usually) not just justified.

Thank you "emexes" for the answer.
I need - multiline text to be aligned on both sides of EditText.


I have found some solutions :

https://github.com/ufo22940268/android-justifiedtextview
https://github.com/navabi/JustifiedTextView
https://stackoverflow.com/questions/44368339/justifying-text-inside-a-textview-in-android
https://stackoverflow.com/questions/1292575/android-textview-justify-text

But I do not know how to implement them in B4A.
Please Is it possible to use the above solutions in B4A ?
 
Upvote 0

emexes

Expert
Licensed User
Please Is it possible to use the above solutions in B4A ?
I don't know. The second one looks plausible, but it'll take a more masterful wrapper than me to bring it to B4A.

It is somewhat foreboding that all those references refer to TextView, not EditText. Yes, I understand that Android's TextView supports editing, and had interword justification added a while back, but... posts by people trying to use both those features simultaneously do not instill optimism.

It sounds like you are heading towards wanting a WYSIWYG word processor, so I had a quick look at the add-on treasure map:

B4X Goodies

and these two looked promising:

https://www.b4x.com/android/forum/threads/richeditor-view.66319/

https://www.b4x.com/android/forum/threads/justifytextview-wrapper.55330/

but... no: richeditor seems to do alignment but not justification, and justifytextview seems to do (interword) justification but not editing.

A longer look covering less-obvious matches in the B4XGoodies list might uncover something that does both.

If you don't find that, then an alternative might be to superimpose a justifytextview on top of an EditText, where if you click (or long-click) on it, it "changes" to an EditText (by bringing the EditText to the top, or disabling/enabling appropriately) so that the user can edit the text, and then upon losing focus, reverts back to the justifytextview (with the newly-changed text loaded, obviously ;-)
 
Upvote 0

js486dog

Active Member
Licensed User
Longtime User
I don't know. The second one looks plausible, but it'll take a more masterful wrapper than me to bring it to B4A.

It is somewhat foreboding that all those references refer to TextView, not EditText. Yes, I understand that Android's TextView supports editing, and had interword justification added a while back, but... posts by people trying to use both those features simultaneously do not instill optimism.

It sounds like you are heading towards wanting a WYSIWYG word processor, so I had a quick look at the add-on treasure map:

B4X Goodies

and these two looked promising:

https://www.b4x.com/android/forum/threads/richeditor-view.66319/

https://www.b4x.com/android/forum/threads/justifytextview-wrapper.55330/

but... no: richeditor seems to do alignment but not justification, and justifytextview seems to do (interword) justification but not editing.

A longer look covering less-obvious matches in the B4XGoodies list might uncover something that does both.

If you don't find that, then an alternative might be to superimpose a justifytextview on top of an EditText, where if you click (or long-click) on it, it "changes" to an EditText (by bringing the EditText to the top, or disabling/enabling appropriately) so that the user can edit the text, and then upon losing focus, reverts back to the justifytextview (with the newly-changed text loaded, obviously ;-)

Thank you "emexes".

justifytextview would be fine for me but:
All Layout is scrollable in justifytextview (also buttons)
B4X:
sv.Panel.LoadLayout("Layout1")

Look also b4aexample.zip :
https://www.b4x.com/android/forum/threads/justifytextview-wrapper.55330/

And I do not know how to scroll only text in justifytextview and no buttons.
 
Upvote 0

js486dog

Active Member
Licensed User
Longtime User
I don't know. The second one looks plausible, but it'll take a more masterful wrapper than me to bring it to B4A.

It is somewhat foreboding that all those references refer to TextView, not EditText. Yes, I understand that Android's TextView supports editing, and had interword justification added a while back, but... posts by people trying to use both those features simultaneously do not instill optimism.

It sounds like you are heading towards wanting a WYSIWYG word processor, so I had a quick look at the add-on treasure map:

B4X Goodies

and these two looked promising:

https://www.b4x.com/android/forum/threads/richeditor-view.66319/

https://www.b4x.com/android/forum/threads/justifytextview-wrapper.55330/

but... no: richeditor seems to do alignment but not justification, and justifytextview seems to do (interword) justification but not editing.

A longer look covering less-obvious matches in the B4XGoodies list might uncover something that does both.

If you don't find that, then an alternative might be to superimpose a justifytextview on top of an EditText, where if you click (or long-click) on it, it "changes" to an EditText (by bringing the EditText to the top, or disabling/enabling appropriately) so that the user can edit the text, and then upon losing focus, reverts back to the justifytextview (with the newly-changed text loaded, obviously ;-)

Thank you "emexes".

justifytextview would be fine for me but:
All Layout is scrollable in justifytextview (also buttons)

And I do not know how to scroll only text in justifytextview and no buttons.

B4X:
#Region  Project Attributes
    #ApplicationLabel: LibEx
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
     Dim From As String
    Private MyView As JustifyTextView
    Dim sv As ScrollView
    Private btn1 As Button
    Private btn2 As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example
    sv.Initialize(1900dip)
    Activity.AddView(sv,0,0,100%x,300%y)
    sv.Panel.LoadLayout("Layout1")
    If File.Exists(File.DirInternal,"from.txt") = False Then
    File.Copy(File.DirAssets,"from.txt",File.DirInternal,"from.txt")
    End If
    From = File.ReadString(File.DirInternal, "from.txt")
    MyView.SetText(From,False)
    'MyView.TextSize = 10
    
    MyView.JustifyTextColor = Colors.Cyan
    MyView.setPadding(10,10,10,10)
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btn2_Click
    MyView.JustifyTextColor = Colors.Red
    MyView.SetText(From,False)
End Sub
Sub btn1_Click
    MyView.JustifyTextColor = Colors.Yellow
    MyView.SetText(From,True)
End Sub
 
Upvote 0

emexes

Expert
Licensed User
All Layout is scrollable in justifytextview (also buttons)
And I do not know how to scroll only text in justifytextview and no buttons.
Delete the buttons from the layout.
Delete the .Click Subs too if you wish (no matter if you leave them in, though, because the buttons that called them no longer exist)
In the Activity_Create Sub, change the MyView.SetText second parameter from False to True

I don't know what the file-copying is about, why it doesn't just read from the Dir.Assets version, but presumably there is a reason. You could experiment with simplifying that bit of the example too, if you wish. If it turns out there is a reason for the file copying, I'd be interested to know what it was.

:)
 
Upvote 0

js486dog

Active Member
Licensed User
Longtime User
Delete the buttons from the layout.
Delete the .Click Subs too if you wish (no matter if you leave them in, though, because the buttons that called them no longer exist)
In the Activity_Create Sub, change the MyView.SetText second parameter from False to True

I don't know what the file-copying is about, why it doesn't just read from the Dir.Assets version, but presumably there is a reason. You could experiment with simplifying that bit of the example too, if you wish. If it turns out there is a reason for the file copying, I'd be interested to know what it was.

:)
Thank you "emexies" for quick answer.

I understand almost all in the code above (SetText, LoadText, ColorText , Dir.Assets ... ).

Only one I do not understand:
I need to have also the buttons or labels or another features in the Layout. But not scrollable.
How to scroll only multiline text in justifytextview ?

How to escape :

B4X:
sv.Panel.LoadLayout("Layout1")

when there are also Buttons, Labels not only justifytextview in the Layout1 ?
 
Upvote 0

emexes

Expert
Licensed User
How to escape :
B4X:
sv.Panel.LoadLayout("Layout1")
when there are also Buttons, Labels not only justifytextview in the Layout1 ?
Yeah, it's an awkward example to branch out from.

What you would normally do is have all your fixed stuff on the layout, including the CLV view, and then add the JustifyTextView to the CLV. What I am mildly confused about is: doesn't the JustifyTextView already do scrolling itself? Presumably it does not, otherwise why does the example put it into a CLV?

Hang on, I'll give the thing a burl here.
 
Upvote 0

emexes

Expert
Licensed User
Yeah, it's an awkward example to branch out from ... Hang on, I'll give the thing a burl here.
Done.

Don't know why background of ScrollView won't change by code. If you work that out, let me know. In the meantime, change it in Designer.

Inter-paragraph spacing varies between justified/ragged modes. Again, why, dunno. Pretty certain that JustifyTextView has a 100% moneyback guarantee, you might have to look into that.

:)
 

Attachments

  • JustifyTextView.zip
    9.1 KB · Views: 214
Upvote 0

js486dog

Active Member
Licensed User
Longtime User
Done.

Don't know why background of ScrollView won't change by code. If you work that out, let me know. In the meantime, change it in Designer.

Inter-paragraph spacing varies between justified/ragged modes. Again, why, dunno. Pretty certain that JustifyTextView has a 100% moneyback guarantee, you might have to look into that.

:)
Well done "emexes".
Works fine.

I have done some little amendments.

I apologize for my demand:
Only two problems :

1)

How to solve programaticaly Panel Hight depends on load text size ?

sv.Panel.Height = 6000dip 'interior scroll panel height
6000 is a lot for from.txt for text size >18
3000 is small for from.txt for text size >18

2)

Gaps between text sections (CRLF) seems to be little large.
 

Attachments

  • JustifyTextView.zip
    286.7 KB · Views: 193
Upvote 0

emexes

Expert
Licensed User
I apologize for my demand:
Only two problems :
Great! :-/ (and thank you for preemptively softening the blow :) )

Good questions, too (sadly!)

1) How to solve programaticaly Panel Hight depends on load text size ?
My first tack here would be to calculate it based on average text size, eg:

NumCharsPerLine = MyView.Width / (TextSize * some_constant)
NumLines = MyText.Length / NumCharsPerLine
LineHeight = TextSize * another_constant
MyView.Height = NumLines * LineHeight

and then you can fold the constants and make it one calculation:

MyView.Height = NumLines * LineHeight
MyView.Height = (MyText.Length / NumCharsPerLine) * (TextSize * another_constant)
MyView.Height = (MyText.Length / (MyView.Width / (TextSize * some_constant)) * (TextSize * another_constant)
MyView.Height = MyText.Length / MyView.Width * TextSize / some_constant * TextSize * another_constant

MyView.Height = MyText.Length * TextSize * TextSize * amalgamated_constant / MyView.Width

Hopefully I haven't mucked that up. It looks right, because:

AverageCharArea = TextSize * TextSize * amalgamated_constant
Area = NumChars * AverageCharArea
Height = Area / Width

Probably best to add a bit of extra height, to allow for partial lines and/or text with lots of wide characters. Could either just add a fixed amount, or something based on TextSize, and/or increase amalgamated constant.

The second tack was going to be Snapshot the ScrollView Panel to an image, then scan the image pixels to find the bottom of the text, but... I was getting B4A and B4J mixed up, and I don't know how to do the Snapshot in B4A. If you find out, let me know. Or there is some multiline text height function, but I don't know how it will handle justified layout. Give it a go - worst that'll happen is it doesn't work.

2) Gaps between text sections (CRLF) seems to be little large.
Yeah, good luck with this. Maybe CharSequences that decrease the font size of blank lines between paragraphs. Probably won't work, but you never know your luck in the big city. Or maybe there is a Unicode smaller-than-usual line break, same as there are smaller-than-usual spaces.

(... wanders off to do internet search ...)

Check this out: http://www.unicode-symbol.com/u/008B.html

You can add it after each NewLine with:

MyView.SetText(MyText.Replace(Chr(10), Chr(10) & Chr(0x8B), False)

or maybe even replace the NewLines for the case where JustifyTextView is already adding blank space between paragraphs:

MyView.SetText(MyText.Replace(Chr(10), Chr(0x8B), True) 'I might have True and False around the wrong way (am away from test bench)

but no guarantees, I'm just tossing ideas into the mix that documention indicates should/could work.

:)
 
Upvote 0

js486dog

Active Member
Licensed User
Longtime User
Great! :-/ (and thank you for preemptively softening the blow :) )

Good questions, too (sadly!)


My first tack here would be to calculate it based on average text size, eg:

NumCharsPerLine = MyView.Width / (TextSize * some_constant)
NumLines = MyText.Length / NumCharsPerLine
LineHeight = TextSize * another_constant
MyView.Height = NumLines * LineHeight

and then you can fold the constants and make it one calculation:

MyView.Height = NumLines * LineHeight
MyView.Height = (MyText.Length / NumCharsPerLine) * (TextSize * another_constant)
MyView.Height = (MyText.Length / (MyView.Width / (TextSize * some_constant)) * (TextSize * another_constant)
MyView.Height = MyText.Length / MyView.Width * TextSize / some_constant * TextSize * another_constant

MyView.Height = MyText.Length * TextSize * TextSize * amalgamated_constant / MyView.Width

Hopefully I haven't mucked that up. It looks right, because:

AverageCharArea = TextSize * TextSize * amalgamated_constant
Area = NumChars * AverageCharArea
Height = Area / Width

Probably best to add a bit of extra height, to allow for partial lines and/or text with lots of wide characters. Could either just add a fixed amount, or something based on TextSize, and/or increase amalgamated constant.

The second tack was going to be Snapshot the ScrollView Panel to an image, then scan the image pixels to find the bottom of the text, but... I was getting B4A and B4J mixed up, and I don't know how to do the Snapshot in B4A. If you find out, let me know. Or there is some multiline text height function, but I don't know how it will handle justified layout. Give it a go - worst that'll happen is it doesn't work.


Yeah, good luck with this. Maybe CharSequences that decrease the font size of blank lines between paragraphs. Probably won't work, but you never know your luck in the big city. Or maybe there is a Unicode smaller-than-usual line break, same as there are smaller-than-usual spaces.

(... wanders off to do internet search ...)

Check this out: http://www.unicode-symbol.com/u/008B.html

You can add it after each NewLine with:

MyView.SetText(MyText.Replace(Chr(10), Chr(10) & Chr(0x8B), False)

or maybe even replace the NewLines for the case where JustifyTextView is already adding blank space between paragraphs:

MyView.SetText(MyText.Replace(Chr(10), Chr(0x8B), True) 'I might have True and False around the wrong way (am away from test bench)

but no guarantees, I'm just tossing ideas into the mix that documention indicates should/could work.

:)
Thank you very much "emexes".
I will try your suggestions.
 
Upvote 0

js486dog

Active Member
Licensed User
Longtime User
If you don't need the text to be editable then you can use BCTextEngine. It supports justification.
Thank you Erel for the answer.

I have tried it.
I can load text into BBCodeView.

But I do not know how to set programaticaly:

color
text size
text color
text justify alignement
padding
border color, border width, border radius

of BBCodeView ?

Please how can I do that ?

B4X:
Sub Globals
    Private MyText As String
    Private MyView As BBCodeView
    Private TextEngine As BCTextEngine
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout1")
    TextEngine.Initialize(Activity)

    If File.Exists(File.DirInternal,"from.txt") = False Then
        File.Copy(File.DirAssets,"from.txt",File.DirInternal,"from.txt")
    End If
    MyText = File.ReadString(File.DirInternal, "from.txt")
  
    MyView.mBase.Color = Colors.LightGray ' Error Type does not match
    MyView.mBase.TextSize = 18 ' Error Type does not match
    MyView.mBase.TextColor = Colors.Black ' Error Type does not match
    MyView.Padding.Left = 10 ' Error Type does not match
    MyView.Padding.right = 10 ' Error Type does not match
    MyView.mBase.SetColorAndBorder(Colors.Gray,1dip,Colors.Black,3dip) ' Without error but no effect
    'I DO NOT KNOW HOW TO SET JUSTIFY ALIGNEMENT ?

    MyView.Text = MyText  ' Works fine text is loaded


End Sub
 
Upvote 0

js486dog

Active Member
Licensed User
Longtime User
If you don't need the text to be editable then you can use BCTextEngine. It supports justification.
Erel,

I have found padding.
I can load text into BBCodeView.


But I do not know how to set programaticaly:

color
text size
text color
text justify alignement
border color, border width, border radius

of BBCodeView ?


B4X:
Sub Globals
    Private MyText As String
    Private MyView As BBCodeView
    Private TextEngine As BCTextEngine
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout1")
    TextEngine.Initialize(Activity)

    If File.Exists(File.DirInternal,"from.txt") = False Then
        File.Copy(File.DirAssets,"from.txt",File.DirInternal,"from.txt")
    End If
    MyText = File.ReadString(File.DirInternal, "from.txt")
  
    MyView.mBase.Color = Colors.LightGray ' ERROR Type does not match
    MyView.mBase.TextSize = 18 ' ERROR Type does not match
    MyView.mBase.TextColor = Colors.Black ' ERROR Type does not match
    MyView.mBase.SetColorAndBorder(Colors.Gray,1dip,Colors.Black,3dip) ' Without error but no effect
    'I DO NOT KNOW HOW TO SET TEXT JUSTIFY ALIGNEMENT ?

    MyView.Padding.Initialize(30dip, 30dip, 30dip, 30dip)
    MyView.Text = MyText


End Sub
 
Upvote 0
Top