Android TextView Justify Text
Frage
Wie bekommst du den Text von a? TextView
gerechtfertigt sein (mit Textspülung auf der linken und rechten Seite)?
Ich fand eine mögliche Lösung hier, aber es funktioniert nicht (auch wenn Sie vertikal in Center_vertical usw. wechseln).
Lösung
Ich glaube nicht, dass Android die volle Rechtfertigung unterstützt.
Update 2018-01-01: Android 8.0+ unterstützt Begründungsmodi mit TextView
.
Andere Tipps
Die @Commonsware -Antwort ist korrekt. Android unterstützt keine "vollständige Rechtfertigung" (oder einfach "Rechtfertigung", wie es manchmal mehrdeutig erwähnt wird).
Android unterstützt jedoch "Spülung links/rechter Textausrichtung". Siehe den Wikipedia -Artikel über Rechtfertigung für die Unterscheidung. Viele Menschen betrachten das Konzept der „Rechtfertigung“, die Volleinstellungs- und linke/rechte Textausrichtung zu erfassen. In dieser Antwort wird erklärt, wie die linke/rechte Textausrichtung erreicht werden kann.
Es ist möglich, eine bündige Ausrichtung des linken/rechten Textes zu erreichen (im Gegensatz zur vollständigen Begründung, wie die Frage stellt). Um zu demonstrieren, werde ich als Beispiel eine grundlegende 2-Spalte Form (Beschriftungen in der linken Spalte und in Textfeldern in der rechten Spalte) verwenden. In diesem Beispiel wird der Text in den Beschriftungen in der linken Spalte rechts ausgerichtet, sodass sie in der rechten Spalte gegen ihre Textfelder spülen.
Im XML -Layout können Sie die Textview -Elemente selbst (die linke Spalte) nach rechts ausrichten, indem Sie das folgende Attribut in allen Textviews hinzufügen:
<TextView
...
android:layout_gravity="center_vertical|end">
...
</TextView>
Wenn sich der Text jedoch in mehrere Zeilen umrundet, würde der Text immer noch links in der Textansicht ausgerichtet sein. Durch das Hinzufügen des folgenden Attributs wird der tatsächliche Text in der Textansicht nach rechts ausgerichtet (links) ausgerichtet:
<TextView
...
android:gravity="end">
...
</TextView>
Also die Schwere Attribut gibt an, wie Sie den Text in der Textansicht ausrichten können layout_gravity Gibt an, wie das Textview -Element selbst ausgerichtet ist.
Um Text in Android zu rechtfertigen, habe ich WebView verwendet
setContentView(R.layout.main);
WebView view = new WebView(this);
view.setVerticalScrollBarEnabled(false);
((LinearLayout)findViewById(R.id.inset_web_view)).addView(view);
view.loadData(getString(R.string.hello), "text/html; charset=utf-8", "utf-8");
und html.
<string name="hello">
<![CDATA[
<html>
<head></head>
<body style="text-align:justify;color:gray;background-color:black;">
Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Nunc pellentesque, urna
nec hendrerit pellentesque, risus massa
</body>
</html>
]]>
</string>
Ich kann Bilder noch nicht hochladen, um es zu beweisen, aber "es funktioniert für mich".
AKTUALISIERT
Wir haben dafür eine einfache Klasse erstellt. Derzeit gibt es zwei Methoden, um das zu erreichen, wonach Sie suchen. Beide erfordern Keine WebView und Unterstützt Spannables.
BIBLIOTHEK: https://github.com/bluejamesbond/textjustify-android
Unterstützung: Android 2.0 bis 5.x
KONFIGURATION
// Please visit Github for latest setup instructions.
BILDSCHIRMFOTO
TextView
in Android O
Bietet die vollständige Begründung (neue typografische Ausrichtung) selbst.
Sie müssen das nur tun,
textView.setJustificationMode(JUSTIFICATION_MODE_INTER_WORD);
Standard ist JUSTIFICATION_MODE_NONE
.
Sie können verwenden JustifiedTextView für Android Projekt in GitHub. Dies ist eine benutzerdefinierte Ansicht, die den berechtigten Text für Sie simuliert. Es unterstützt Android 2.0+ und rechts bis links.
Ich schreibe eine Widget -Basis auf native TextView, um dies zu tun.
Ich habe einen Weg gefunden, dieses Problem zu lösen, aber das ist vielleicht nicht sehr Anmut, aber der Effekt ist nicht schlecht.
Sein Prinzip ist es, die Räume jeder Zeile durch den Bildern der festen Breite zu ersetzen (die Farbe ist transparent).
public static void justify(final TextView textView) {
final AtomicBoolean isJustify = new AtomicBoolean(false);
final String textString = textView.getText().toString();
final TextPaint textPaint = textView.getPaint();
final SpannableStringBuilder builder = new SpannableStringBuilder();
textView.post(new Runnable() {
@Override
public void run() {
if (!isJustify.get()) {
final int lineCount = textView.getLineCount();
final int textViewWidth = textView.getWidth();
for (int i = 0; i < lineCount; i++) {
int lineStart = textView.getLayout().getLineStart(i);
int lineEnd = textView.getLayout().getLineEnd(i);
String lineString = textString.substring(lineStart, lineEnd);
if (i == lineCount - 1) {
builder.append(new SpannableString(lineString));
break;
}
String trimSpaceText = lineString.trim();
String removeSpaceText = lineString.replaceAll(" ", "");
float removeSpaceWidth = textPaint.measureText(removeSpaceText);
float spaceCount = trimSpaceText.length() - removeSpaceText.length();
float eachSpaceWidth = (textViewWidth - removeSpaceWidth) / spaceCount;
SpannableString spannableString = new SpannableString(lineString);
for (int j = 0; j < trimSpaceText.length(); j++) {
char c = trimSpaceText.charAt(j);
if (c == ' ') {
Drawable drawable = new ColorDrawable(0x00ffffff);
drawable.setBounds(0, 0, (int) eachSpaceWidth, 0);
ImageSpan span = new ImageSpan(drawable);
spannableString.setSpan(span, j, j + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
builder.append(spannableString);
}
textView.setText(builder);
isJustify.set(true);
}
}
});
}
Ich habe den Code auf GitHub gestellt:https://github.com/twiceyuan/textjustification
Überblick:
XML -Layout: Deklary WebView anstelle von TextView deklarieren
<WebView
android:id="@+id/textContent"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
Java -Code: Setzen Sie Textdaten auf WebView
WebView view = (WebView) findViewById(R.id.textContent);
String text;
text = "<html><body><p align=\"justify\">";
text+= "This is the text will be justified when displayed!!!";
text+= "</p></body></html>";
view.loadData(text, "text/html", "utf-8");
Dies kann Ihr Problem lösen. Es hat für mich voll funktioniert.
So habe ich es gemacht, ich denke die eleganteste Art und Weise, wie ich es konnte. Mit dieser Lösung sind die einzigen Dinge, die Sie in Ihren Layouts tun müssen,:
- Fügen Sie eine zusätzliche hinzu
xmlns
Erklärung - ändere dein
TextView
s Quelltext -Namespace von Android zu Ihrem neuen Namespace - Ersetzen Sie Ihre
TextView
s mitx.y.z.JustifiedTextView
Hier ist der Code. Arbeitet auf meinen Telefonen vollkommen gut (Galaxy Nexus Android 4.0.2, Galaxy Teos Android 2.1). Fühlen Sie sich natürlich frei, meinen Paketnamen durch Ihren zu ersetzen.
/assets/justified_textView.css:
body {
font-size: 1.0em;
color: rgb(180,180,180);
text-align: justify;
}
@media screen and (-webkit-device-pixel-ratio: 1.5) {
/* CSS for high-density screens */
body {
font-size: 1.05em;
}
}
@media screen and (-webkit-device-pixel-ratio: 2.0) {
/* CSS for extra high-density screens */
body {
font-size: 1.1em;
}
}
/res/values/attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="JustifiedTextView">
<attr name="text" format="reference" />
</declare-styleable>
</resources>
/res/layout/test.xml:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myapp="http://schemas.android.com/apk/res/net.bicou.myapp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<net.bicou.myapp.widget.JustifiedTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
myapp:text="@string/surv1_1" />
</LinearLayout>
</ScrollView>
/src/net/bicou/myapp/widget/justifiedTextView.java:
package net.bicou.myapp.widget;
import net.bicou.myapp.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.webkit.WebView;
public class JustifiedTextView extends WebView {
public JustifiedTextView(final Context context) {
this(context, null, 0);
}
public JustifiedTextView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public JustifiedTextView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
if (attrs != null) {
final TypedValue tv = new TypedValue();
final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.JustifiedTextView, defStyle, 0);
if (ta != null) {
ta.getValue(R.styleable.JustifiedTextView_text, tv);
if (tv.resourceId > 0) {
final String text = context.getString(tv.resourceId).replace("\n", "<br />");
loadDataWithBaseURL("file:///android_asset/",
"<html><head>" +
"<link rel=\"stylesheet\" type=\"text/css\" href=\"justified_textview.css\" />" +
"</head><body>" + text + "</body></html>",
"text/html", "UTF8", null);
setTransparentBackground();
}
}
}
}
public void setTransparentBackground() {
try {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
} catch (final NoSuchMethodError e) {
}
setBackgroundColor(Color.TRANSPARENT);
setBackgroundDrawable(null);
setBackgroundResource(0);
}
}
Wir müssen das Rendering auf Software einstellen, um transparentem Hintergrund zu Android 3+ zu erhalten. Daher der Versuch für ältere Versionen von Android.
Hoffe das hilft!
PS: Bitte nicht, dass es nützlich sein könnte, dies zu Ihrer gesamten Aktivität auf Android 3+ hinzuzufügen, um das erwartete Verhalten zu erhalten:
android:hardwareAccelerated="false"
Obwohl immer noch nicht vollständiger gerechtfertigter Text android:breakStrategy="balanced"
ab API 23 ab
http://developer.android.com/reference/android/widget/textview.html#attr_android:breakstrategy
Ich schreibe meine eigene Klasse, um dieses Problem zu lösen. Hier müssen Sie nur die statische Rechtfertigungsfunktion aufrufen, die zwei Argumente aufnimmt
- Text anzeigen Objekt
- Inhaltsbreite (Gesamtbreite Ihrer Textansicht)
//Hauptaktivität
package com.fawad.textjustification;
import android.app.Activity;
import android.database.Cursor;
import android.graphics.Point;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.Menu;
import android.widget.TextView;
public class MainActivity extends Activity {
static Point size;
static float density;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Display display = getWindowManager().getDefaultDisplay();
size=new Point();
DisplayMetrics dm=new DisplayMetrics();
display.getMetrics(dm);
density=dm.density;
display.getSize(size);
TextView tv=(TextView)findViewById(R.id.textView1);
Typeface typeface=Typeface.createFromAsset(this.getAssets(), "Roboto-Medium.ttf");
tv.setTypeface(typeface);
tv.setLineSpacing(0f, 1.2f);
tv.setTextSize(10*MainActivity.density);
//some random long text
String myText=getResources().getString(R.string.my_text);
tv.setText(myText);
TextJustification.justify(tv,size.x);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
// textUtificationClass
package com.fawad.textjustification;
import java.util.ArrayList;
import android.graphics.Paint;
import android.text.TextUtils;
import android.widget.TextView;
public class TextJustification {
public static void justify(TextView textView,float contentWidth) {
String text=textView.getText().toString();
Paint paint=textView.getPaint();
ArrayList<String> lineList=lineBreak(text,paint,contentWidth);
textView.setText(TextUtils.join(" ", lineList).replaceFirst("\\s", ""));
}
private static ArrayList<String> lineBreak(String text,Paint paint,float contentWidth){
String [] wordArray=text.split("\\s");
ArrayList<String> lineList = new ArrayList<String>();
String myText="";
for(String word:wordArray){
if(paint.measureText(myText+" "+word)<=contentWidth)
myText=myText+" "+word;
else{
int totalSpacesToInsert=(int)((contentWidth-paint.measureText(myText))/paint.measureText(" "));
lineList.add(justifyLine(myText,totalSpacesToInsert));
myText=word;
}
}
lineList.add(myText);
return lineList;
}
private static String justifyLine(String text,int totalSpacesToInsert){
String[] wordArray=text.split("\\s");
String toAppend=" ";
while((totalSpacesToInsert)>=(wordArray.length-1)){
toAppend=toAppend+" ";
totalSpacesToInsert=totalSpacesToInsert-(wordArray.length-1);
}
int i=0;
String justifiedText="";
for(String word:wordArray){
if(i<totalSpacesToInsert)
justifiedText=justifiedText+word+" "+toAppend;
else
justifiedText=justifiedText+word+toAppend;
i++;
}
return justifiedText;
}
}
// xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
>
<ScrollView
android:id="@+id/scrollView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</LinearLayout>
</ScrollView>
</RelativeLayout>
FILL_HORIZONTAL
ist äquivalent zu CENTER_HORIZONTAL
. Sie können diesen Code -Snippet im Quellcode von TextView sehen:
case Gravity.CENTER_HORIZONTAL:
case Gravity.FILL_HORIZONTAL:
return (mLayout.getLineWidth(0) - ((mRight - mLeft) -
getCompoundPaddingLeft() - getCompoundPaddingRight())) /
getHorizontalFadingEdgeLength();
Für dieses Problem gibt es eine benutzerdefinierte Ansicht. Diese benutzerdefinierte Textansicht ist Unterstützung für die berechtigte Textansicht.
Plünderung in diesem: JustifiedTextView
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.view.View;
public class JustifiedTextView extends View {
String text;
ArrayList<Line> linesCollection = new ArrayList<Line>();
TextPaint textPaint;
Typeface font;
int textColor;
float textSize = 42f, lineHeight = 57f, wordSpacing = 15f, lineSpacing = 15f;
float onBirim, w, h;
float leftPadding, rightPadding;
public JustifiedTextView(Context context, String text) {
super(context);
this.text = text;
init();
}
private void init() {
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
textColor = Color.BLACK;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (font != null) {
font = Typeface.createFromAsset(getContext().getAssets(), "font/Trykker-Regular.ttf");
textPaint.setTypeface(font);
}
textPaint.setColor(textColor);
int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
w = resolveSizeAndState(minw, widthMeasureSpec, 1);
h = MeasureSpec.getSize(widthMeasureSpec);
onBirim = 0.009259259f * w;
lineHeight = textSize + lineSpacing;
leftPadding = 3 * onBirim + getPaddingLeft();
rightPadding = 3 * onBirim + getPaddingRight();
textPaint.setTextSize(textSize);
wordSpacing = 15f;
Line lineBuffer = new Line();
this.linesCollection.clear();
String[] lines = text.split("\n");
for (String line : lines) {
String[] words = line.split(" ");
lineBuffer = new Line();
float lineWidth = leftPadding + rightPadding;
float totalWordWidth = 0;
for (String word : words) {
float ww = textPaint.measureText(word) + wordSpacing;
if (lineWidth + ww + (lineBuffer.getWords().size() * wordSpacing) > w) {// is
lineBuffer.addWord(word);
totalWordWidth += textPaint.measureText(word);
lineBuffer.setSpacing((w - totalWordWidth - leftPadding - rightPadding) / (lineBuffer.getWords().size() - 1));
this.linesCollection.add(lineBuffer);
lineBuffer = new Line();
totalWordWidth = 0;
lineWidth = leftPadding + rightPadding;
} else {
lineBuffer.setSpacing(wordSpacing);
lineBuffer.addWord(word);
totalWordWidth += textPaint.measureText(word);
lineWidth += ww;
}
}
this.linesCollection.add(lineBuffer);
}
setMeasuredDimension((int) w, (int) ((this.linesCollection.size() + 1) * lineHeight + (10 * onBirim)));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(0f, 10f, getMeasuredWidth(), 10f, textPaint);
float x, y = lineHeight + onBirim;
for (Line line : linesCollection) {
x = leftPadding;
for (String s : line.getWords()) {
canvas.drawText(s, x, y, textPaint);
x += textPaint.measureText(s) + line.spacing;
}
y += lineHeight;
}
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Typeface getFont() {
return font;
}
public void setFont(Typeface font) {
this.font = font;
}
public float getLineHeight() {
return lineHeight;
}
public void setLineHeight(float lineHeight) {
this.lineHeight = lineHeight;
}
public float getLeftPadding() {
return leftPadding;
}
public void setLeftPadding(float leftPadding) {
this.leftPadding = leftPadding;
}
public float getRightPadding() {
return rightPadding;
}
public void setRightPadding(float rightPadding) {
this.rightPadding = rightPadding;
}
public void setWordSpacing(float wordSpacing) {
this.wordSpacing = wordSpacing;
}
public float getWordSpacing() {
return wordSpacing;
}
public float getLineSpacing() {
return lineSpacing;
}
public void setLineSpacing(float lineSpacing) {
this.lineSpacing = lineSpacing;
}
class Line {
ArrayList<String> words = new ArrayList<String>();
float spacing = 15f;
public Line() {
}
public Line(ArrayList<String> words, float spacing) {
this.words = words;
this.spacing = spacing;
}
public void setSpacing(float spacing) {
this.spacing = spacing;
}
public float getSpacing() {
return spacing;
}
public void addWord(String s) {
words.add(s);
}
public ArrayList<String> getWords() {
return words;
}
}
}
Fügen Sie Ihrem SRC -Ordner die obige Klasse hinzu und verwenden Sie diesen Beispielcode, um Ihrem Layout hinzuzufügen:
JustifiedTextView jtv= new JustifiedTextView(getApplicationContext(), "Lorem ipsum dolor sit amet... ");
LinearLayout place = (LinearLayout) findViewById(R.id.book_profile_content);
place.addView(jtv);
Sehr einfach können wir das in der XML -Datei tun
<TextView
android:justificationMode="inter_word"
/>
Ich denke, es gibt zwei Optionen:
Verwenden Sie so etwas wie Pango, das sich darauf über den NDK spezialisiert hat, und rendern Sie Text zu einer OpenGL oder einer anderen Oberfläche.
Verwenden Paint.Measuretext () und Freunde, um die Wörterlängen zu bekommen und sie in einer benutzerdefinierten Ansicht manuell auf eine Leinwand zu legen.
Android unterstützt noch keine vollständige Rechtfertigung. Wir können WebView verwenden und HTML rechtfertigen, anstatt TextView zu verwenden. Es funktioniert so gut. Wenn ihr nicht klar habt, zögern Sie nicht, mich zu fragen :)
Probieren Sie diese Lösung im folgenden Link aus, erstellen Sie einfach diese Klasse im Projektordner und verwenden Sie sie. Es funktioniert gut für mich :)
Auf Android, links rechtfertigen Text und nicht die Hintergrundfarbe, versuchen Sie dies, es hat für mich funktioniert und konsistente Ergebnisse zu Android, FF, IE & Chrome erzielt, aber Sie müssen den Raum, der dazwischen für den Text übrig ist Bei der Berechnung der Polsterung.
<td style="font-family:Calibri,Arial;
font-size:15px;
font-weight:800;
background-color:#f5d5fd;
color:black;
border-style:solid;
border-width:1px;
border-color:#bd07eb;
padding-left:10px;
padding-right:1000px;
padding-top:3px;
padding-bottom:3px;
>
Der Hack ist der padding-right:1000px;
Das drückt den Text nach links.
Jeder Versuch, einen linken oder rechtfertigen Code in CSS oder HTML zu rechtfertigen oder zu rechtfertigen, führt zu einem Hintergrund, der nur halb Breite ist.
siehe hier im Github
Importieren Sie einfach die beiden Dateien "textyjustifyutils.java" und "textViewex.java" in Ihrem Projekt.
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 };
}
line += 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;
}
}
und
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);
}
}
}
Wenn Sie jetzt normale Textansicht verwenden wie:
<TextView
android:id="@+id/original"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lorum_ipsum" />
Einfach benutzen
<yourpackagename.TextViewEx
android:id="@+id/changed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lorum_ipsum" />
Definieren Sie eine Variable und setzen
TextViewEx changed = (TextViewEx) findViewById(R.id.changed);
changed.setText(getResources().getString(R.string.lorum_ipsum),true);
Für die HTML -Formatierung müssen Sie das Webkit nicht anrufen, Sie könnten verwenden Html.fromHtml(text)
den Job erledigen.
Quelle : http://developer.android.com/guide/topics/resources/string-resource.html
Sie müssen setzen
android:layout_height="wrap_content"
und
android:layout_centerInParent="true"
Versuchen Sie es zu verwenden RelativeLayout >
(Stellen Sie sicher android:layout_alignParentLeft="true"
und
android:layout_alignParentRight="true"
Zu den Elementen, die Sie von außen links und rechts möchten.
Schuld, gerechtfertigt!
Dies rechtfertigt Ihren Text aber nicht wirklich
android:gravity="center_horizontal"
ist die beste Wahl, die Sie haben.