Его называют Justified textview
, который автоматически корректирует текст (Justify)
Пример
Создайте этот класс JustifiedTextView
в своем проекте
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
public class JustifiedTextView extends View {
private Context mContext;
private XmlToClassAttribHandler mXmlParser;
private TextPaint textPaint;
private int lineSpace=0;
private int lineHeight;
private int textAreaWidth;
private int measuredViewHeight,measuredViewWidth;
private String text;
private List<String> lineList=new ArrayList<String>();
/**
* when we want to draw text after view created to avoid loop in drawing we use this boolean
*/
boolean hasTextBeenDrown=false;
public JustifiedTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
constructor(context,attrs);
}
public JustifiedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
constructor(context,attrs);
}
public JustifiedTextView(Context context) {
super(context);
constructor(context,null);
}
private void constructor(Context context, AttributeSet attrs) {
mContext=context;
mXmlParser=new XmlToClassAttribHandler(mContext,attrs);
initTextPaint();
if (attrs!=null){
String text;
int textColor;
int textSize;
int textSizeUnit;
text=mXmlParser.getTextValue();
textColor=mXmlParser.getColorValue();
textSize=mXmlParser.getTextSize();
textSizeUnit=mXmlParser.gettextSizeUnit();
setText(text);
setTextColor(textColor);
if (textSizeUnit==-1)
setTextSize(textSize);
else
setTextSize(textSizeUnit, textSize);
// setText(XmlToClassAttribHandler.GetAttributeStringValue(mContext, attrs, namespace, key, ""));
}
ViewTreeObserver observer=getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (hasTextBeenDrown)
return;
hasTextBeenDrown=true;
setTextAreaWidth(getWidth()-(getPaddingLeft()+getPaddingRight()));
calculate();
}
});
}
private void calculate() {
setLineHeight(getTextPaint());
lineList.clear();
lineList=divideOriginalTextToStringLineList(getText());
setMeasuredDimentions(lineList.size(),getLineHeight(),getLineSpace());
measure(getMeasuredViewWidth(),getMeasuredViewHeight());
}
private void initTextPaint(){
textPaint=new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
textPaint.setTextAlign(Align.RIGHT);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (getMeasuredViewWidth()>0){
requestLayout();
setMeasuredDimension(getMeasuredViewWidth(),getMeasuredViewHeight());
}
else{
super.onMeasure(widthMeasureSpec, heightMeasureSpec );
}
invalidate();
}
private int rowIndex=0,colIndex=0;
@Override
protected void onDraw(Canvas canvas) {
rowIndex=getPaddingTop();
if (getAlignment()==Align.RIGHT)
colIndex=getPaddingLeft()+getTextAreaWidth();
else
colIndex=getPaddingLeft();
for (int i=0;i<lineList.size();i++){
rowIndex+=getLineHeight()+getLineSpace();
canvas.drawText(lineList.get(i), colIndex,rowIndex , getTextPaint());
}
}
/***
* this method get the string and divide it to a list of StringLines according to textAreaWidth
* @param originalText
* @return
*/
private List<String> divideOriginalTextToStringLineList(String originalText) {
List<String> listStringLine=new ArrayList<String>();
String line="";
float textWidth;
String[] listParageraphes = originalText.split("\n");
for(int j=0;j<listParageraphes.length;j++)
{
String[] arrayWords = listParageraphes[j].split(" ");
for (int i=0;i<arrayWords.length;i++){
line += arrayWords[i]+" ";
textWidth = getTextPaint().measureText(line);
//if text width is equal to textAreaWidth then just add it to ListStringLine
if (getTextAreaWidth()==textWidth){
listStringLine.add(line);
line="";//make line clear
continue;
}
//else if text width excite textAreaWidth then remove last word and justify the StringLine
else if (getTextAreaWidth()<textWidth){
int lastWordCount=arrayWords[i].length();
//remove last word that cause line width to excite textAreaWidth
line=line.substring(0, line.length()-lastWordCount-1);
// if line is empty then should be skipped
if (line.trim().length()==0)
continue;
//and then we need to justify line
line=justifyTextLine(textPaint,line.trim(),getTextAreaWidth());
listStringLine.add(line);
line="";
i--;
continue;
}
//if we are now at last line of paragraph then just add it
if (i==arrayWords.length-1){
listStringLine.add(line);
line="";
}
}
}
return listStringLine;
}
/**
* this method add space in line until line width become equal to textAreaWidth
* @param lineString
* @param lineWidth
* @param textAreaWidth
* @return
*/
private String justifyTextLine(TextPaint textPaint,String lineString, int textAreaWidth) {
int gapIndex=0;
float lineWidth=textPaint.measureText(lineString);
while (lineWidth<textAreaWidth && lineWidth>0){
gapIndex=lineString.indexOf(" ", gapIndex+2);
if (gapIndex==-1){
gapIndex=0;
gapIndex=lineString.indexOf(" ", gapIndex+1);
if (gapIndex==-1)
return lineString;
}
lineString=lineString.substring(0, gapIndex)+ " " +lineString.substring(gapIndex+1, lineString.length());
lineWidth=textPaint.measureText(lineString);
}
return lineString;
}
/***
* this method calculate height for a line of text according to defined TextPaint
* @param textPaint
*/
private void setLineHeight(TextPaint textPaint) {
Rect bounds=new Rect();
String sampleStr="این حسین کیست که عالم همه دیوانه اوست";
textPaint.getTextBounds(sampleStr, 0,sampleStr.length(), bounds);
setLineHeight(bounds.height());
}
/***
* this method calculate view's height according to line count and line height and view's width
* @param lineListSize
* @param lineHeigth
* @param lineSpace
*/
public void setMeasuredDimentions(int lineListSize,int lineHeigth, int lineSpace){
int mHeight=lineListSize*(lineHeigth+lineSpace)+lineSpace;
mHeight+=getPaddingRight()+getPaddingLeft();
setMeasuredViewHeight(mHeight);
setMeasuredViewWidth(getWidth());
}
private int getTextAreaWidth() {
return textAreaWidth;
}
private void setTextAreaWidth(int textAreaWidth) {
this.textAreaWidth = textAreaWidth;
}
private int getLineHeight() {
return lineHeight;
}
private int getMeasuredViewHeight() {
return measuredViewHeight;
}
private void setMeasuredViewHeight(int measuredViewHeight) {
this.measuredViewHeight = measuredViewHeight;
}
private int getMeasuredViewWidth() {
return measuredViewWidth;
}
private void setMeasuredViewWidth(int measuredViewWidth) {
this.measuredViewWidth = measuredViewWidth;
}
private void setLineHeight(int lineHeight) {
this.lineHeight = lineHeight;
}
public String getText() {
return text;
}
/***
* Sets the string value of the JustifiedTextView. JustifiedTextView does not accept HTML-like formatting.
* Related XML Attributes
* -noghteh:text
* @param text
*/
public void setText(String text) {
this.text = text;
calculate();
invalidate();
}
public void setText(int resid) {
setText(mContext.getResources().getString(resid));
}
public Typeface getTypeFace() {
return getTextPaint().getTypeface();
}
public void setTypeFace(Typeface typeFace) {
getTextPaint().setTypeface(typeFace);
}
public float getTextSize() {
return getTextPaint().getTextSize();
}
public void setTextSize(int unit,float textSize) {
textSize=TypedValue.applyDimension(unit, textSize, mContext.getResources().getDisplayMetrics());
setTextSize(textSize);
}
private void setTextSize(float textSize) {
getTextPaint().setTextSize(textSize);
calculate();
invalidate();
}
public TextPaint getTextPaint() {
return textPaint;
}
public void setTextPaint(TextPaint textPaint) {
this.textPaint = textPaint;
}
/***
* set text color
* @param textColor
*/
public void setTextColor(int textColor) {
getTextPaint().setColor(textColor);
invalidate();
}
/***
* define space between lines
* @param lineSpace
*/
public void setLineSpacing(int lineSpace) {
this.lineSpace = lineSpace;
invalidate();
}
/***
*
* @return text color
*/
public int getTextColor() {
return getTextPaint().getColor();
}
/***
* space between lines - default is 0
* @return
*/
public int getLineSpace() {
return lineSpace;
}
/***
* get text alignment
* @return
*/
public Align getAlignment() {
return getTextPaint().getTextAlign();
}
/***
* Align text according to your language
* @param align
*/
public void setAlignment(Align align) {
getTextPaint().setTextAlign(align);
invalidate();
}
}
Использование: - XML-файл
<classpackage.JustifiedTextView
android:id="@+id/activity_main_jtv_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:padding="25dp"
xmlns:noghteh=""
noghteh:text="Justfied textview"
noghteh:textColor="@color/text"
noghteh:textSize="18sp"
>
</classpackage.JustifiedTextView>
Использование Java во время выполнения
private JustifiedTextView mJTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mJTv=(JustifiedTextView) findViewById(R.id.activity_main_jtv_text);
mJTv.setText(getResources().getString(R.string.test));
mJTv.setTextSize(TypedValue.COMPLEX_UNIT_SP,20);
mJTv.setLineSpacing(15);
mJTv.setBackgroundColor(Color.RED);
mJTv.setAlignment(Align.LEFT);
mJTv.setTypeFace(Typeface.createFromAsset(getAssets(), "fonts/naskh_bold.ttf"));
}