如何调整文本以不显示空格。我已经看到许多应用程序可以完美显示文本而没有任何间隙。
这是我用来生成此输出的XML。
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/text"
android:id="@+id/title"
android:autoLink="all"
android:autoSizeTextType="uniform"
android:linksClickable="true"
android:text="Description Of the News"
android:textColor="#000000"
android:textSize="20sp"
android:lineHeight="5dp"
android:padding="12dp"
/>
我尝试过autosize
,但这也不是完美的选择。
答案 0 :(得分:1)
它称为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"));
}
答案 1 :(得分:1)
仅 Android 8.0及更高版本支持justification modes with TextView。
有关更多信息(或其他在Android中实现它的方法),请参考以下答案:Android TextView Justify Text
希望这对您有所帮助。 :)
答案 2 :(得分:1)
Frank Cheng已针对较旧的android版本回答了这个问题。从android oreo起,您可以使用合理的文本视图来优化应用程序。
答案 3 :(得分:0)
感谢所有回答问题的人。
此库JustifiedTextView解决了我的问题。它几乎完美。
答案 4 :(得分:-1)
您可以像这样使用android:justificationMode =“ inter_word”
<TextView
android:id="@+id/productdetailTv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:ellipsize="end"
android:fontFamily="@font/montserrat_regular"
android:maxLines="30"
android:justificationMode="inter_word"
android:text="@string/_fdg_dfg_df_dfg_dfsg_dfg_fgdfsgdfsg_dfg_dfsg_dfsg_sdfdsf_sdfdsf_dsf_dsf"
android:textColor="#524E4E"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />