Justifying Text In Android
Solution 1:
I use the following code that answer with very people that need this subject and i create formula that support in every display.
publicclassTextJustify {
finalstaticStringSYSTEM_NEWLINE="\n";
finalstaticfloatCOMPLEXITY=5.12f; // Reducing this will increase// efficiency but will decrease// effectivenessfinalstaticPaintp=newPaint();
/* @author Mathew Kurian */publicstaticvoidrun(final TextView tv, float origWidth, int paddingLeft, int paddingRight, int marginLeft, int marginRight) {
origWidth-= paddingRight+marginRight+paddingLeft+marginLeft;
Strings= tv.getText().toString();
p.setTypeface(tv.getTypeface());
String[] splits = s.split(SYSTEM_NEWLINE);
floatwidth= origWidth - 5;
for (intx=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 (inty=0; y < microSplits.length - 1; y++)
microSplits[y] = justify(removeLast(microSplits[y], " "),
width, p);
StringBuildersmb_internal=newStringBuilder();
for (intz=0; z < microSplits.length; z++)
smb_internal.append(microSplits[z]
+ ((z + 1 < microSplits.length) ? SYSTEM_NEWLINE
: ""));
splits[x] = smb_internal.toString();
}
finalStringBuildersmb=newStringBuilder();
for (String cleaned : splits)
smb.append(cleaned + SYSTEM_NEWLINE);
tv.setGravity(Gravity.RIGHT);
tv.setText(smb);
}
privatestatic String wrap(String s, float width, Paint p) {
String[] str = s.split("\\s"); // regexStringBuildersmb=newStringBuilder(); // save memory
smb.append(SYSTEM_NEWLINE);
for (intx=0; x < str.length; x++) {
floatlength= 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, "");
}
privatestatic String removeLast(String s, String g) {
if (s.contains(g)) {
intindex= s.lastIndexOf(g);
intindexEnd= index + g.length();
if (index == 0)
return s.substring(1);
elseif (index == s.length() - 1)
return s.substring(0, index);
elsereturn s.substring(0, index) + s.substring(indexEnd);
}
return s;
}
privatestatic String justifyOperation(String s, float width, Paint p) {
floatholder= (float) (COMPLEXITY * Math.random());
while (s.contains(Float.toString(holder)))
holder = (float) (COMPLEXITY * Math.random());
Stringholder_string= Float.toString(holder);
floatlessThan= width;
inttimeOut=100;
intcurrent=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++;
}
Stringcleaned= s.replaceAll(holder_string, " ");
return cleaned;
}
privatestatic String justify(String s, float width, Paint p) {
while (p.measureText(s) < width) {
s = justifyOperation(s, width, p);
}
return s;
}
}
and for calling this you mus use following code, I tested for Persian language and in every display and device worked fine.
publicstaticfinalintFinallwidthDp=320 ;
publicstaticfinalintwidthJustify=223 ;
DisplayMetricsmetrics=newDisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
intwidthPixels= metrics.widthPixels;
floatscaleFactor= metrics.density;
floatwidthDp= widthPixels / scaleFactor;
TextViewtv= (TextView) findViewById(R.id.textView1);
ViewGroup.MarginLayoutParamslp1= (ViewGroup.MarginLayoutParams) tv.getLayoutParams();
tv.setText(text);
TextJustify.run(tv,widthDp / FinallwidthDp * widthJustify , tv.getPaddingLeft(),tv.getPaddingRight() , lp1.leftMargin, lp1.rightMargin);
this algorithm tested on various device and worked fine in normal activity (not dialog) and wrap-content
width for TextView
, and worked with every padding and margin.if not good for you, you can change widthJustify
until look good to you, I hope this useful.
for newly update see This
Solution 2:
LIBRARY: https://github.com/bluejamesbond/TextJustify-Android
SUPPORTS: Android 2.0 to 5.X; String/Spannables; RTL language support! NO WEBVIEW :)
SCREENSHOT
Solution 3:
Try this:
Add a TextViewJustify.java file in src folder.
TextViewJustify.java wil be like this
import android.graphics.Paint;
import android.view.Gravity;
import android.widget.TextView;
publicclassTextViewJustify {
/*
* PLEASE DO NOT REMOVE Coded by Mathew Kurian I wrote this code for a
* Google Interview for Internship. Unfortunately, I got too nervous during
* the interview that I messed, but anyhow that doesn't matter. I have
* resent my work in hopes that I might still get a position there. Thank
* you :DD
*/finalstaticStringSYSTEM_NEWLINE="\n";
finalstaticfloatCOMPLEXITY=5.12f; // Reducing this will increase// efficiency but will decrease// effectivenessfinalstaticPaintp=newPaint();
publicstaticvoidjustifyText(final TextView tv, finalfloat origWidth) {
Strings= tv.getText().toString();
p.setTypeface(tv.getTypeface());
String[] splits = s.split(SYSTEM_NEWLINE);
floatwidth= origWidth - 5;
for (intx=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 (inty=0; y < microSplits.length - 1; y++)
microSplits[y] = justify(removeLast(microSplits[y], " "),
width, p);
StringBuildersmb_internal=newStringBuilder();
for (intz=0; z < microSplits.length; z++)
smb_internal.append(microSplits[z]
+ ((z + 1 < microSplits.length) ? SYSTEM_NEWLINE
: ""));
splits[x] = smb_internal.toString();
}
finalStringBuildersmb=newStringBuilder();
for (String cleaned : splits)
smb.append(cleaned + SYSTEM_NEWLINE);
tv.setGravity(Gravity.LEFT);
tv.setText(smb);
}
privatestatic String wrap(String s, float width, Paint p) {
String[] str = s.split("\\s"); // regexStringBuildersmb=newStringBuilder(); // save memory
smb.append(SYSTEM_NEWLINE);
for (intx=0; x < str.length; x++) {
floatlength= 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, "");
}
privatestatic String removeLast(String s, String g) {
if (s.contains(g)) {
intindex= s.lastIndexOf(g);
intindexEnd= index + g.length();
if (index == 0)
return s.substring(1);
elseif (index == s.length() - 1)
return s.substring(0, index);
elsereturn s.substring(0, index) + s.substring(indexEnd);
}
return s;
}
privatestatic String justifyOperation(String s, float width, Paint p) {
floatholder= (float) (COMPLEXITY * Math.random());
while (s.contains(Float.toString(holder)))
holder = (float) (COMPLEXITY * Math.random());
Stringholder_string= Float.toString(holder);
floatlessThan= width;
inttimeOut=100;
intcurrent=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++;
}
Stringcleaned= s.replaceAll(holder_string, " ");
return cleaned;
}
privatestatic String justify(String s, float width, Paint p) {
while (p.measureText(s) < width) {
s = justifyOperation(s, width, p);
}
return s;
}
}
And use this class like this:
TextViewJustify.justifyText(your_text_view, 225f);
In my case it was 225f. change it according to your need.
Solution 4:
You can justify Text using WebView Simply
LinearLayout lv=(LinearLayout)dialog.findViewById(R.id.**yourId**);
String text1 = "<html><body>"
+ "<p align=\"justify\">"
+**your text**
+ "</p> "
+ "</body></html>";
WebView wv=new WebView(getApplicationContext());
wv.loadData(text1,"text/html","utf-8");
lv.removeAllViews();
lv.addView(wv);
Solution 5:
i made simple class. this can be used just like TextView
import android.content.Context;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.TextView;
/**
* text justifying
* you can just use like TextView
* @author hyunsikkim
*
*/publicclassJustifiedTextViewextendsTextView {
publicJustifiedTextView(Context context) {
super(context);
}
publicJustifiedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
privatevoidsetBreakText(String text) {
if(text == null) return;
StringbreakText= breakText(getPaint(), text,
getWidth()-this.getPaddingLeft()-this.getPaddingRight());
if(breakText.equals(getText()) == false) {
setText(breakText);
}
}
public String breakText(Paint textPaint, String strText, int breakWidth) {
StringBuildersb=newStringBuilder();
intendValue=0;
finalStringNEW_LINE="\n";
do{
endValue = textPaint.breakText(strText, true, breakWidth, null);
if(endValue > 0) {
/**
* handle if text contains NEW_LINE
*/finalintindex= strText.indexOf(NEW_LINE);
if(0<=index && index <= endValue) {
endValue = index + NEW_LINE.length();
}
finalStringsub= strText.substring(0, endValue);
sb.append(sub);
/**
* handle breaked text endWidth NEW_LINE
*/if(sub.endsWith(NEW_LINE) == false) {
if(strText.length() != endValue) {
sb.append(NEW_LINE);
}
}
strText = strText.substring(endValue);
}
} while(endValue > 0);
return sb.toString();
}
public String breakText(Paint textPaint, int id, int breakWidth) {
StringstrText= getResources().getString(id);
return breakText(textPaint, strText, breakWidth);
}
@OverrideprotectedvoidonTextChanged(CharSequence text, int start,
int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
/**
* this control changes from setText(Charsequence text)
*/if(getWidth() != 0) {
setBreakText(text.toString());
}
}
@OverrideprotectedvoidonSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
/**
* this help to break initial text.
*/if(w != oldw) {
setBreakText(getText().toString());
}
}
}
Post a Comment for "Justifying Text In Android"