Justify TextView

1798 views.

How can i justify the text in Android?

Add Comment
1 Answer(s)
917 views.

First Add this dependcy in your gradle  

dependencies 
{
compile 'com.uncopt:android.justified:1.0'
}

 

 

 

Add below two java file with same name

 

TextJustifyUtils .Java

 

 
package androindin.learnandroid;android.graphics.Paint;
import android.view.Gravity;
import android.widget.TextView;
 
public class TextJustifyUtils {
// Please use run(...) instead
public static void justify(TextView textView) {
Paint paint = new Paint();
 
String[] blocks;
float spaceOffset = 0;
float textWrapWidth = 0;
 
int spacesToSpread;
float wrappedEdgeSpace;
String block;
String[] lineAsWords;
String wrappedLine;
String smb = "";
Object[] wrappedObj;
 
// Pull widget properties
paint.setColor(textView.getCurrentTextColor());
paint.setTypeface(textView.getTypeface());
paint.setTextSize(textView.getTextSize());
 
textWrapWidth = textView.getWidth();
spaceOffset = paint.measureText(" ");
blocks = textView.getText().toString().split("((?<=\n)|(?=\n))");
 
if (textWrapWidth < 20) {
return;
}
 
for (int i = 0; i < blocks.length; i++) {
block = blocks[i];
 
 
if (block.length() == 0) {
continue;
} else if (block.equals("\n")) {
smb += block;
continue;
}
 
block = block.trim();
 
if (block.length() == 0)
continue;
 
wrappedObj = TextJustifyUtils.createWrappedLine(block, paint,
spaceOffset, textWrapWidth);
wrappedLine = ((String) wrappedObj[0]);
wrappedEdgeSpace = (Float) wrappedObj[1];
lineAsWords = wrappedLine.split(" ");
spacesToSpread = (int) (wrappedEdgeSpace != Float.MIN_VALUE ? wrappedEdgeSpace
/ spaceOffset
: 0);
 
for (String word : lineAsWords) {
smb += word + " ";
 
if (--spacesToSpread > 0) {
smb += " ";
}
}
 smb = smb.trim();
 
if (blocks[i].length() > 0) {
blocks[i] = blocks[i].substring(wrappedLine.length());
 
if (blocks[i].length() > 0) {
smb += "\n";
}
 
i--;
}
}
 
textView.setGravity(Gravity.LEFT);
textView.setText(smb);
}
 protected static Object[] createWrappedLine(String block, Paint paint,
 float spaceOffset, float maxWidth) {
float cacheWidth = maxWidth;
float origMaxWidth = maxWidth;
 
String line = "";
 
for (String word : block.split("\\s")) {
cacheWidth = paint.measureText(word);
maxWidth -= cacheWidth;
 
if (maxWidth <= 0) {
return new Object[] { line, maxWidth + cacheWidth + spaceOffset };
}
 += word + " ";
maxWidth -= spaceOffset;
 
 
 
 
 
 
 
}
 
 
 
 
 
 
 
if (paint.measureText(block) <= origMaxWidth) {
return new Object[] { block, Float.MIN_VALUE };
}
 
 
 
 
 
 
 
return new Object[] { line, maxWidth };
}
 
 
 
 
 
 
 
final static String SYSTEM_NEWLINE = "\n";
final static float COMPLEXITY = 5.12f; // Reducing this will increase
// efficiency but will decrease
// effectiveness
final static Paint p = new Paint();
 
 
 
 
 
 
 
public static void run(final TextView tv, float origWidth) {
String s = tv.getText().toString();
p.setTypeface(tv.getTypeface());
String[] splits = s.split(SYSTEM_NEWLINE);
float width = origWidth - 5;
for (int x = 0; x < splits.length; x++)
if (p.measureText(splits[x]) > width) {
splits[x] = wrap(splits[x], width, p);
String[] microSplits = splits[x].split(SYSTEM_NEWLINE);
for (int y = 0; y < microSplits.length - 1; y++)
microSplits[y] = justify(removeLast(microSplits[y], " "),
width, p);
StringBuilder smb_internal = new StringBuilder();
for (int z = 0; z < microSplits.length; z++)
smb_internal.append(microSplits[z]
+ ((z + 1 < microSplits.length) ? SYSTEM_NEWLINE
: ""));
splits[x] = smb_internal.toString();
}
final StringBuilder smb = new StringBuilder();
for (String cleaned : splits)
smb.append(cleaned + SYSTEM_NEWLINE);
tv.setGravity(Gravity.LEFT);
tv.setText(smb);
}
 
 
 
 
 
 
 
private static String wrap(String s, float width, Paint p) {
String[] str = s.split("\\s"); // regex
StringBuilder smb = new StringBuilder(); // save memory
smb.append(SYSTEM_NEWLINE);
for (int x = 0; x < str.length; x++) {
float length = p.measureText(str[x]);
String[] pieces = smb.toString().split(SYSTEM_NEWLINE);
try {
if (p.measureText(pieces[pieces.length - 1]) + length > width)
smb.append(SYSTEM_NEWLINE);
} catch (Exception e) {
}
smb.append(str[x] + " ");
}
return smb.toString().replaceFirst(SYSTEM_NEWLINE, "");
}
 
 
 
 
 
 
 
private static String removeLast(String s, String g) {
if (s.contains(g)) {
int index = s.lastIndexOf(g);
int indexEnd = index + g.length();
if (index == 0)
return s.substring(1);
else if (index == s.length() - 1)
return s.substring(0, index);
else
return s.substring(0, index) + s.substring(indexEnd);
}
return s;
}
 
 
 
 
 
 
 
private static String justifyOperation(String s, float width, Paint p) {
float holder = (float) (COMPLEXITY * Math.random());
while (s.contains(Float.toString(holder)))
holder = (float) (COMPLEXITY * Math.random());
String holder_string = Float.toString(holder);
float lessThan = width;
int timeOut = 100;
int current = 0;
while (p.measureText(s) < lessThan && current < timeOut) {
s = s.replaceFirst(" ([^" + holder_string + "])", " "
+ holder_string + "$1");
lessThan = p.measureText(holder_string) + lessThan
- p.measureText(" ");
current++;
}
String cleaned = s.replaceAll(holder_string, " ");
return cleaned;
}
 
 
 
 
 
 
 
private static String justify(String s, float width, Paint p) {
while (p.measureText(s) < width) {
s = justifyOperation(s, width, p);
}
return s;
}
}
 
 
 
 
 
 
 

 

 

 

TextViewEx.Java

 

 

 

 
 
 
 
 
 
 
package androindin.learnandroid;
 
 
 
 
 
 
 
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Paint.Align;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.widget.TextView;
import android.util.AttributeSet;
 
 
 
 
 
 
 
public class TextViewEx extends TextView {
 private Paint paint = new Paint();
 
 
 
 
 
 
 
private String[] blocks;
 private float spaceOffset = 0;
 private float horizontalOffset = 0;
 private float verticalOffset = 0;
 private float horizontalFontOffset = 0;
 private float dirtyRegionWidth = 0;
 private boolean wrapEnabled = false;
 int left, top, right, bottom = 0;
 private Align _align = Align.LEFT;
 private float strecthOffset;
 private float wrappedEdgeSpace;
 private String block;
 private String wrappedLine;
 private String[] lineAsWords;
 private Object[] wrappedObj;
 
 
 
 
 
 
 
private Bitmap cache = null;
 private boolean cacheEnabled = false;
 
 
 
 
 
 
 
public TextViewEx(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 // set a minimum of left and right padding so that the texts are not too
 // close to the side screen
 // this.setPadding(10, 0, 10, 0);
 }
 
 
 
 
 
 
 
public TextViewEx(Context context, AttributeSet attrs) {
 super(context, attrs);
 // this.setPadding(10, 0, 10, 0);
 }
 
 
 
 
 
 
 
public TextViewEx(Context context) {
 super(context);
 // this.setPadding(10, 0, 10, 0);
 }
 
 
 
 
 
 
 
@Override
 public void setPadding(int left, int top, int right, int bottom) {
 // TODO Auto-generated method stub
 super.setPadding(left + 10, top, right + 10, bottom);
 }
 
 
 
 
 
 
 
@Override
 public void setDrawingCacheEnabled(boolean cacheEnabled) {
 this.cacheEnabled = cacheEnabled;
 }
 
 
 
 
 
 
 
public void setText(String st, boolean wrap) {
 wrapEnabled = wrap;
 super.setText(st);
 }
 
 
 
 
 
 
 
public void setTextAlign(Align align) {
 _align = align;
 }
 
 
 
 
 
 
 
@SuppressLint("NewApi")
 @Override
 protected void onDraw(Canvas canvas) {
 // If wrap is disabled then,
 // request original onDraw
 if (!wrapEnabled) {
 super.onDraw(canvas);
 return;
 }
 
 
 
 
 
 
 
// Active canas needs to be set
 // based on cacheEnabled
 Canvas activeCanvas = null;
 
 
 
 
 
 
 
// Set the active canvas based on
 // whether cache is enabled
 if (cacheEnabled) {
 
 
 
 
 
 
 
if (cache != null) {
 // Draw to the OS provided canvas
 // if the cache is not empty
 canvas.drawBitmap(cache, 0, 0, paint);
 return;
 } else {
 // Create a bitmap and set the activeCanvas
 // to the one derived from the bitmap
 cache = Bitmap.createBitmap(getWidth(), getHeight(),
 Config.ARGB_4444);
 activeCanvas = new Canvas(cache);
 }
 } else {
 // Active canvas is the OS
 // provided canvas
 activeCanvas = canvas;
 }
 
 
 
 
 
 
 
// Pull widget properties
 paint.setColor(getCurrentTextColor());
 paint.setTypeface(getTypeface());
 paint.setTextSize(getTextSize());
 paint.setTextAlign(_align);
 paint.setFlags(Paint.ANTI_ALIAS_FLAG);
 
 
 
 
 
 
 
// minus out the paddings pixel
 dirtyRegionWidth = getWidth() - getPaddingLeft() - getPaddingRight();
 int maxLines = Integer.MAX_VALUE;
 int currentapiVersion = android.os.Build.VERSION.SDK_INT;
 if (currentapiVersion >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
 maxLines = getMaxLines();
 }
 int lines = 1;
 blocks = getText().toString().split("((?<=\n)|(?=\n))");
 verticalOffset = horizontalFontOffset = getLineHeight() - 0.5f; // Temp
 // fix
 spaceOffset = paint.measureText(" ");
 
 
 
 
 
 
 
for (int i = 0; i < blocks.length && lines <= maxLines; i++) {
 block = blocks[i];
 horizontalOffset = 0;
 
 
 
 
 
 
 
if (block.length() == 0) {
 continue;
 } else if (block.equals("\n")) {
 verticalOffset += horizontalFontOffset;
 continue;
 }
 
 
 
 
 
 
 
block = block.trim();
 
 
 
 
 
 
 
if (block.length() == 0) {
 continue;
 }
 
 
 
 
 
 
 
wrappedObj = TextJustifyUtils.createWrappedLine(block, paint,
 spaceOffset, dirtyRegionWidth);
 
 
 
 
 
 
 
wrappedLine = ((String) wrappedObj[0]);
 wrappedEdgeSpace = (Float) wrappedObj[1];
 lineAsWords = wrappedLine.split(" ");
 strecthOffset = wrappedEdgeSpace != Float.MIN_VALUE ? wrappedEdgeSpace
 / (lineAsWords.length - 1)
 : 0;
 
 
 
 
 
 
 
for (int j = 0; j < lineAsWords.length; j++) {
 String word = lineAsWords[j];
 if (lines == maxLines && j == lineAsWords.length - 1) {
 activeCanvas.drawText("...", horizontalOffset,
 verticalOffset, paint);
 
 
 
 
 
 
 
} else if (j == 0) {
 // if it is the first word of the line, text will be drawn
 // starting from right edge of textview
 if (_align == Align.RIGHT) {
 activeCanvas.drawText(word, getWidth()
 - (getPaddingRight()), verticalOffset, paint);
 // add in the paddings to the horizontalOffset
 horizontalOffset += getWidth() - (getPaddingRight());
 } else {
 activeCanvas.drawText(word, getPaddingLeft(),
 verticalOffset, paint);
 horizontalOffset += getPaddingLeft();
 }
 
 
 
 
 
 
 
} else {
 activeCanvas.drawText(word, horizontalOffset,
 verticalOffset, paint);
 }
 if (_align == Align.RIGHT)
 horizontalOffset -= paint.measureText(word) + spaceOffset
 + strecthOffset;
 else
 horizontalOffset += paint.measureText(word) + spaceOffset
 + strecthOffset;
 }
 
 
 
 
 
 
 
lines++;
 
 
 
 
 
 
 
if (blocks[i].length() > 0) {
 blocks[i] = blocks[i].substring(wrappedLine.length());
 verticalOffset += blocks[i].length() > 0 ? horizontalFontOffset
 : 0;
 i--;
 }
 }
 
 
 
 
 
 
 
if (cacheEnabled) {
 // Draw the cache onto the OS provided
 // canvas.
 canvas.drawBitmap(cache, 0, 0, paint);
 }
 }
}
 
 
 
 
 
 
 

 

 

 

After Add Textview in xml like below (add your package name before “.TextViewEx”)

 

 

 

<androindin.learnandroid.TextViewEx
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/chap1_tv11"
android:textColor="@color/title"
android:textSize="14sp"
android:paddingTop="5dp"
android:breakStrategy="balanced"
/>

 

 

 

 

 

 

 

Adding text resource to Textview in Java file

 

 

 

 

 

 

 

Sub_chap1.java

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
 
 
 
 
 
 
package androindian.chapone;
 
 
 
 
 
 
 
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
 
 
 
 
 
 
 
import androindin.learnandroid.R;
import androindin.learnandroid.TextViewEx;
 
 
 
 
 
 
 
public class Sub_chap1 extends AppCompatActivity{
 
 
 
 
 
 
 
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sub_chap1);
 
 
 
 
 
 
 
TextViewEx textViewEx=(TextViewEx)findViewById(R.id.chap1_tv11);
textViewEx.setText(getResources().getString(R.string.intro_MobileAppDev),true);
}
}
 
 
 
 
 
 
 

 

Srting Resource

 

 

 

<string name="intro_MobileAppDev">Mobile OS are keep on introducing from Palm OS in 1996 to Windows pocket PC in 2000 then to Blackberry OS and Android.One of the most popular used mobile OS now days are ANDROID. There are around 2.0 lack+ games, application and widgets available on the market for Android users. Android is a powerful Operating System supporting a large number of applications in Smart Phones. These applications make life more comfortable and advanced for the users.  Android is a Linux-based operating system designed for mobile devices such as smartphones and tablet computers. The Android is a light weight OS and can easily embedded into different hardware devices like networking equipment, smart TV systems including set top boxes and built in systems and various devices like as house hold appliances and wrist watches</string>
Answered on July 5, 2016.
Add Comment

Your Answer

By posting your answer, you agree to the privacy policy and terms of service.