2012-08-12 4 views
7

Ich bin auf der Suche nach einem einfachen Weg zu vergessen, dass ich eine WebView verwenden, um Text in meinem TextView zu haben. Hat jemand eine benutzerdefinierte Ansicht dafür erstellt? Ich bin mir sehr wohl bewusst, dass ich etwas tun kann:Begründen Sie Text in einer Android-App mit einem WebView, aber mit einer TextView-ähnlichen Oberfläche?

WebView view = new WebView(this);  
     view.loadData("my html with text justification","text/html","utf-8"); 

Aber es wird hässlich, wenn Sie die Größe festlegen möchten, die Farbe oder andere gemeinsame Eigenschaften des TextView. Es muss einen bequemeren Weg geben, es zu tun.

Antwort

19

Es ging mir auf die Nerven, ich gebe es zu. Ich mag die TextViews im Code wie TextViews aussehen, und selbst wenn ich eine WebView als Mittel zum Erreichen der Text-Align: gerechtfertigte Formatierung verwenden, möchte ich es nicht so betrachten.

Ich habe eine benutzerdefinierte Ansicht (hässlich, wahrscheinlich schlecht) erstellt, die die Methoden, die ich häufig verwende, aus der TextView implementiert und den Inhalt der WebView ändert, um diese Änderungen widerzuspiegeln. Ob es für jemand anderen oder eine potenzielle Gefahr nützlich ist, weiß ich wirklich nicht, für mich funktioniert es, ich habe es in mehreren Projekten verwendet und habe keine Probleme festgestellt. Die einzige kleine Unannehmlichkeit ist, dass ich davon ausgehe, dass es eine größere Maut ist, aber keine Sorge, wenn es nur ein oder zwei ist (korrigiere mich, wenn ich falsch liege).

Das Ergebnis ist folgendes:

enter image description here

und der Code es programmatisch für die Einstellung, da dies so einfach ist:

JustifiedTextView J = new JustifiedTextView(); 
        J.setText("insert your text here"); 

Natürlich wäre es dumm, es zu verlassen, wie Also habe ich auch die Methoden hinzugefügt, um die Schriftgröße und die Schriftfarbe zu ändern, für die ich hauptsächlich TextViews verwende. Bedeutung ich etwas tun kann:

JustifiedTextView J = new JustifiedTextView(); 
        J.setText("insert your text here"); 
        J.setTextColor(Color.RED); 
        J.setTextSize(30); 

und erhalten das folgende Ergebnis (Bilder werden abgeschnitten):

enter image description here

Aber dies uns nicht zu zeigen, wie es aussieht, ist es zu teile, wie du es gemacht hast!

Ich weiß, ich weiß. Hier ist der vollständige Code. Es behandelt auch Probleme beim Einstellen von transparentem Hintergrund und Laden von UTF-8-Strings in die Ansicht. Siehe die Kommentare in reloadData() für Details.

public class JustifiedTextView extends WebView{ 
    private String core  = "<html><body style='text-align:justify;color:rgba(%s);font-size:%dpx;margin: 0px 0px 0px 0px;'>%s</body></html>"; 
    private String textColor = "0,0,0,255"; 
    private String text  = ""; 
    private int textSize  = 12; 
    private int backgroundColor=Color.TRANSPARENT; 

    public JustifiedTextView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     this.setWebChromeClient(new WebChromeClient(){}); 
    } 

    public void setText(String s){ 
     this.text = s; 
     reloadData(); 
    } 

    @SuppressLint("NewApi") 
    private void reloadData(){ 

     // loadData(...) has a bug showing utf-8 correctly. That's why we need to set it first. 
     this.getSettings().setDefaultTextEncodingName("utf-8"); 

     this.loadData(String.format(core,textColor,textSize,text), "text/html","utf-8"); 

     // set WebView's background color *after* data was loaded. 
     super.setBackgroundColor(backgroundColor); 

     // Hardware rendering breaks background color to work as expected. 
     // Need to use software renderer in that case. 
     if(android.os.Build.VERSION.SDK_INT >= 11) 
      this.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null); 
    } 

    public void setTextColor(int hex){ 
     String h = Integer.toHexString(hex); 
     int a = Integer.parseInt(h.substring(0, 2),16); 
     int r = Integer.parseInt(h.substring(2, 4),16); 
     int g = Integer.parseInt(h.substring(4, 6),16); 
     int b = Integer.parseInt(h.substring(6, 8),16); 
     textColor = String.format("%d,%d,%d,%d", r, g, b, a); 
     reloadData(); 
    } 

    public void setBackgroundColor(int hex){ 
     backgroundColor = hex; 
     reloadData(); 
    } 

    public void setTextSize(int textSize){ 
     this.textSize = textSize; 
     reloadData(); 
    } 
} 
+1

Wenn wir webview Text nehmen wenig Zeit anzuzeigen verwenden. In meinem Fall wird zuerst das Hintergrundbild und nach 2 Sekunden die Textanzeige angezeigt. Wie von diesem Problem zu überwinden? –

+2

und ist es möglich, Schriftart zur Textansicht zu setzen? Danke – Igor

+0

Dies ist eine gute Lösung für Ansichten, die keine Speicher verwenden müssen, zum Beispiel seine nicht gute Idee mit einem Webview (this) in Listview es wird eine Menge Speicher verbrauchen und Ihre App wird eine Antwort langsamer als mit Textview. – superUser

2

Dies ist die gleiche JustifiedTextView Klasse von Juan gegeben (und bearbeitet von mir), aber erweitert mit benutzerdefinierten XML arbeiten Attribute Sie in Ihrem Layout XML-Dateien verwenden können. Selbst der Eclipse-Layout-Editor zeigt Ihre benutzerdefinierten Attribute in der Attributtabelle an, was cool ist. Ich gebe das in eine zusätzliche Antwort, falls Sie die Dinge sauber halten wollen und keine xml-Attribute benötigen.

public class JustifiedTextView extends WebView{ 
    private String core  = "<html><body style='text-align:justify;color:rgba(%s);font-size:%dpx;margin: 0px 0px 0px 0px;'>%s</body></html>"; 
    private String text; 
    private int textColor; 
    private int backgroundColor; 
    private int textSize; 

    public JustifiedTextView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(attrs); 
    } 

    public JustifiedTextView(Context context, AttributeSet attrs, int i) { 
     super(context, attrs, i); 
     init(attrs); 
    } 

    @SuppressLint("NewApi") 
    public JustifiedTextView(Context context, AttributeSet attrs, int i, boolean b) { 
     super(context, attrs, i, b); 
     init(attrs); 
    } 

    private void init(AttributeSet attrs) { 
     TypedArray a=getContext().obtainStyledAttributes(
       attrs, 
       R.styleable.JustifiedTextView); 

     text = a.getString(R.styleable.JustifiedTextView_text); 
     if(text==null) text=""; 
     textColor = a.getColor(R.styleable.JustifiedTextView_textColor, Color.BLACK); 
     backgroundColor = a.getColor(R.styleable.JustifiedTextView_backgroundColor, Color.TRANSPARENT); 
     textSize = a.getInt(R.styleable.JustifiedTextView_textSize, 12); 

     a.recycle(); 

     this.setWebChromeClient(new WebChromeClient(){}); 
     reloadData(); 
    } 

    public void setText(String s){ 
     if(s==null) 
      this.text=""; 
     else 
      this.text = s; 
     reloadData(); 
    } 

    @SuppressLint("NewApi") 
    private void reloadData(){ 

     if(text!=null) { 
      String data = String.format(core,toRgba(textColor),textSize,text); 
      Log.d("test", data); 
      this.loadDataWithBaseURL(null, data, "text/html","utf-8", null); 
     } 

     // set WebView's background color *after* data was loaded. 
     super.setBackgroundColor(backgroundColor); 

     // Hardware rendering breaks background color to work as expected. 
     // Need to use software renderer in that case. 
     if(android.os.Build.VERSION.SDK_INT >= 11) 
      this.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null); 
    } 

    public void setTextColor(int hex){ 
     textColor = hex; 
     reloadData(); 
    } 

    public void setBackgroundColor(int hex){ 
     backgroundColor = hex; 
     reloadData(); 
    } 

    public void setTextSize(int textSize){ 
     this.textSize = textSize; 
     reloadData(); 
    } 

    private String toRgba(int hex) { 
     String h = Integer.toHexString(hex); 
     int a = Integer.parseInt(h.substring(0, 2),16); 
     int r = Integer.parseInt(h.substring(2, 4),16); 
     int g = Integer.parseInt(h.substring(4, 6),16); 
     int b = Integer.parseInt(h.substring(6, 8),16); 
     return String.format("%d,%d,%d,%d", r, g, b, a); 
    } 
} 

Entweder fügen Sie diese als justified_text_view_attr.xml in Ihre res/Werte/Ordner oder es in Ihre bestehende attrs verschmelzen.xml:

<?xml version="1.0" encoding="utf-8"?>                    
<resources>                           
    <declare-styleable name="JustifiedTextView">                  
     <attr name="text" format="string" localization="suggested"/>             
     <attr name="textColor" format="color|reference" />               
     <attr name="backgroundColor" format="color|reference" />              
     <attr name="textSize" format="integer" min="1" />                
    </declare-styleable> 
</resources>       

Fühlen Sie sich frei zu bearbeiten, wenn Sie irgendwelche Fehler finden.

+0

Sehr schön @sulai –

+0

können Sie bitte eine Idee, wie Sie setTypeface() -Methode für Ihre benutzerdefinierte Ansicht implementieren ..? Danke – Droidman

+0

Da Schriftart ist definiert durch HTML in 'JustifiedTextView', müssen Sie' Typefaces' in entsprechende HTML-Tags oder CSS-Attribute zu übersetzen. Im Falle von 'Typeface.BOLD' (und ähnlich) ist dies einfach zu tun. Um den Schriftstil zu ändern, könnten Sie die angegebene Schriftfamilie verwenden und versuchen, das [css-Attribut 'font-family'] (http://de.selfhtml.org/css/eigenschaften/schrift.htm#font_family) zu verwenden, aber Beachten Sie, dass das Ergebnis vom normalen 'TextView.setTypeface()' abweichen kann. Im Falle einer Schriftart, die aus einer Datei erstellt wurde, ist es nicht möglich, sie in 'JustifiedTextView' zu laden. – sulai

6

Ohne webview Lösung ist: https://github.com/merterhk/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; 
       } 
     } 
} 
+3

Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz zur Verfügung zu stellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. – Szymon

+0

Quellcode hinzugefügt. – Merter

+0

Funktioniert es für RTL-Sprachen? –

0

Werfen Sie einen Blick auf diesen Link. Es verwendet ein WebView, um Ballen zu sein, um den Text einer CheckBox in Android vollständig zu rechtfertigen. Es kann auch genau so in TextView verwendet werden, da jede CheckBox tatsächlich eine TextView und eine Schaltfläche ist. http://www.collegemobile.com/2014/09/justify-text-android-checkbox/

0

Ich glaube diese einfachste Form. Und ich arbeitete perfekt

package domo.suichbt.util; 

import android.content.Context; 
import android.text.Html; 
import android.util.AttributeSet; 
import android.widget.TextView; 

public class JustifiedTextView extends TextView 
{ 
    private final String CORE_TEMPLATE = "<html><body style='text- 

align:justify;margin: 0px 0px 0px 0px;'>%s</body></html>"; 

public JustifiedTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 
    super(context, attrs, defStyleAttr, defStyleRes); 
    setText(Html.fromHtml(String.format(CORE_TEMPLATE,getText()))); 
} 

public JustifiedTextView(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    setText(Html.fromHtml(String.format(CORE_TEMPLATE,getText()))); 
} 

public JustifiedTextView(Context context) { 
    super(context); 
    setText(Html.fromHtml(String.format(CORE_TEMPLATE,getText()))); 
} 

public JustifiedTextView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    setText(Html.fromHtml(String.format(CORE_TEMPLATE,getText()))); 
} 
} 

Insert xml Beispiel

<domo.suichbt.util.JustifiedTextView 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/sw_titulo" 
    android:singleLine="false"> 
</domo.suichbt.util.JustifiedTextView> 
+2

Es funktioniert nicht. – Mbt925

2

In nur drei Schritten können Sie Ihre Web-Ansicht Text rechtfertigen kann.

1)

// Justify tag 
String justifyTag = "<html><body style='text-align:justify;'>%s</body></html>"; 

2)

// Concatenate your string with the tag to Justify it 
String dataString = String.format(Locale.US, justifyTag, "my html with text justification"); 

3)

// Load the data in the web view 
webView.loadDataWithBaseURL("", dataString, "text/html", "UTF-8", ""); 
Verwandte Themen