One, foreword

It is common in a design to have an indeterminate length of text followed or preceded by one or more tags. Look up a lot of information on the Internet, most of the implementation is achieved through rich text, can not meet the changing requirements, the label can be a picture, can also be different text, or a layout, sometimes add multiple labels. Then I thought of a solution. The whole part is broken down into multiple layouts, which can be combined freely to meet various needs, no matter how many tags are in front or behind.

Second, concrete implementation

2.1 When the text is limited to one line, the label is placed after the text

Renderings: less text like the first line, more text display not like two or three lines as ellipsis.

    1. Implementation method one, using linear layout implementation
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal">  <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" <TextView android:layout_width="wrap_content" android:layout_width="wrap_content" Android :layout_height="wrap_content" Android :background=" @yellow_ff9b52 "/> <TextView Android :layout_height="wrap_content" Android :layout_height="wrap_content" android:background="@color/blue_74D3FF"/> </LinearLayout>Copy the code
    1. Implementation method two, using constraint layout implementation
<androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/refund_name" android:layout_width="wrap_content" Android :layout_height="wrap_content" Android :layout_height="wrap_content" Android :singleLine="true" app:layout_constrainedWidth="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/refund_mark_num" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/refund_mark_num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/yellow_FF9B52" Android :gravity="center" app:layout_constrainedWidth="true" app:layout_constraintLeft_toRightOf="@+id/refund_name" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>Copy the code

2.2 The number of lines of text is limited or not limited, and the label is behind the text

Effect:

    1. Less text, just one line:

    1. Text display line half time effect

    1. When two lines of text cannot be displayed

    1. Implementation ideas:

For example, the image above restricts the display of text to two lines. The first line is a single TextView, and the second line is the same as the one line of text in 2.1 above. When the text is small, only one line is displayed, and the first line of TextView can be hidden. When the text is more than one line and less than two lines, or more than two lines, the first line of TextView is set to display one line, and the second line of TextView is set to display the rest of the text.

    1. The specific implementation code is as follows:

The XML file:

<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/white" android:background="@color/red" /> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/m15"> <TextView android:id="@+id/tv_rl_test_tagOne" android:layout_width="match_parent" android:layout_height="wrap_content" Android :textSize="13dp" android:textSize="13dp" Android :maxLines="1" Android :textSize="13dp" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/tv_rl_test_tagTwo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" App :layout_constrainedWidth="true" Android :textSize="13dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/tv_rl_test_twoTag" app:layout_constraintTop_toBottomOf="@+id/tv_rl_test_tagOne"  /> <TextView android:id="@+id/tv_rl_test_twoTag" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/yellow_FF9B52" android:layout_marginLeft="3dp" android:layout_marginTop="2dp" android:gravity="center" android:paddingLeft="3dp" android:paddingTop="1dp" Android :paddingRight="3dp" Android :paddingBottom="1dp" Android :text=" tag "Android :textSize="12dp" app:layout_constrainedWidth="true" app:layout_constraintLeft_toRightOf="@+id/tv_rl_test_tagTwo" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/tv_rl_test_tagOne" /> </androidx.constraintlayout.widget.ConstraintLayout>Copy the code

The activity:

// Data source to display String tagSrc = "Text is a way and tool for human beings to record and express information with ideograms for a long time. Modern writing is mostly a tool for recording language. Humans tend to have spoken language before written language, and many small languages have language but no writing. The different characters reflect the different ways and thinking of written expression of countries and nations. Writing introduced man into a civilized society with recorded history." ; TextView tvTagOnes = (TextView) findViewById(R.id.tv_rl_test_tagOne); TextView tvTagTwo = (TextView) findViewById(R.id.tv_rl_test_tagTwo); tvTagOnes.setText(tagSrc); tvTestOne.setText(tagSrc); Tvtagones.post (new Runnable() {@override public void run() {// Get the first textView to display String lineContent = Utils.INSTANCE.getTextLineContent(tvTagOnes, 0, tagSrc); LogUtils.e(tagSrc + "---------" + lineContent); If (textutils.equals (tagSrc,lineContent)){// you can display the full tvTagones.setvisibility (view.gone); tvTagTwo.setText(tagSrc); }else {// show incomplete, need branch tvtagones.setvisibility (view.visible); String srcTwoContent = tagSrc.substring(lineContent.length(), tagSrc.length()); tvTagTwo.setText(srcTwoContent); }}});Copy the code

Get what TextView displays:

/** * get textView line */ fun getTextLineContent(textView: textView? , line: Int, src: String?) : String { var result: String = "" if (textView == null || src.isNullOrEmpty()) { return result } LogUtils.e("$line--line-->${textView.lineCount}" ) if (line > textView.lineCount) { return result } val layout = textView.layout val sb = StringBuilder(src) LogUtils.e("--start-${layout.getLineStart(line)}----end---${layout.getLineEnd(line)}") return sb.subSequence(layout.getLineStart(line), layout.getLineEnd(line)).toString() }Copy the code

2.3 When the label is before the text

Effect:The implementation idea is the same as the above label after the text. The tag on the first line is a control, the text behind the tag is a separate TextView, and the second line is also a separate TextView. If you want to limit the number of lines of text, just restrict the second line of TextView. XML layout:

<! <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" Android :layout_height="wrap_content" android:textColor="@color/white" android:background="@color/red" /> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/m15"> <TextView android:id="@+id/tv_rl_test_tagFront" android:layout_width="wrap_content" android:layout_height="wrap_content" Android :background="@color/yellow_FF9B52" app:layout_constraintTop_toTopOf= app:layout_constraintStart_toStartOf="parent"/> <com.kiwilss.xview.widget.textview.AlignTextView android:id="@+id/tv_rl_test_frontOne" android:layout_width="0dp" android:layout_height="wrap_content" Android :text=" android:text=" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toEndOf="@+id/tv_rl_test_tagFront" android:maxLines="1" /> <com.kiwilss.xview.widget.textview.AlignTextView android:id="@+id/tv_rl_test_frontTwo" Android :layout_width="match_parent" Android :layout_height="wrap_content" Android :text=" match_parent" app:layout_constraintTop_toBottomOf="@+id/tv_rl_test_tagFront"/> </androidx.constraintlayout.widget.ConstraintLayout>Copy the code

The activity:

TextView tvFront = (TextView) findViewById(rI.d.tv_rl_test_tagfront); TextView tvFrontOne = findViewById(R.id.tv_rl_test_frontOne); TextView tvFrontTwo = findViewById(R.id.tv_rl_test_frontTwo); tvFrontOne.setText(tagSrc); Tvfrontone.post (new Runnable() {@override public void run() {// Get the first line of content String lineContent = Utils.INSTANCE.getTextLineContent(tvFrontOne, 0, tagSrc); If (textutils.equals (lineContent,tagSrc)){// show tvfronttwo-setvisibility (view.gone); }else {// you need multiple lines to show tvfronttwo-setvisibility (view.visible); String nextContent = tagSrc.substring(lineContent.length(), tagSrc.length()); tvFrontTwo.setText(nextContent); }}});Copy the code

Third, solve the alignment problem

As shown in the figure, the first line and the second line are not aligned. When using TextView, when the text is not displayed, it will automatically wrap the line, so it will not be aligned. Otherwise, it will not be beautiful. The solution is to align the text at both ends. The diagram below:There are many ways to achieve text alignment on the Internet, here is a custom View method, feel also can be, Chinese and English mixed can also be aligned: AlignTextView:

public class AlignTextView extends AppCompatTextView { private boolean alignOnlyOneLine; public AlignTextView(Context context) { this(context, null); } public AlignTextView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public AlignTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AlignTextView); alignOnlyOneLine = typedArray.getBoolean(R.styleable.AlignTextView_alignOnlyOneLine, false); typedArray.recycle(); setTextColor(getCurrentTextColor()); } @Override public void setTextColor(int color) { super.setTextColor(color); getPaint().setColor(color); } protected void onDraw(Canvas canvas) { CharSequence content = getText(); if (! (content instanceof String)) { super.onDraw(canvas); return; } String text = (String) content; Layout layout = getLayout(); for (int i = 0; i < layout.getLineCount(); ++i) { int lineBaseline = layout.getLineBaseline(i) + getPaddingTop(); int lineStart = layout.getLineStart(i); int lineEnd = layout.getLineEnd(i); If (alignOnlyOneLine && Layout.getLinecount () == 1) {String line = text.substring(lineStart, lineEnd); float width = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, getPaint()); this.drawScaledText(canvas, line, lineBaseline, width); } else if (I == layout.getLinecount () -1) {// Last line canvas.drawText(text.substring(lineStart), getPaddingLeft(), lineBaseline, getPaint()); break; } else {// String line = text.substring(lineStart, lineEnd); float width = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, getPaint()); this.drawScaledText(canvas, line, lineBaseline, width); } } } private void drawScaledText(Canvas canvas, String line, float baseLineY, float lineWidth) { if (line.length() < 1) { return; } float x = getPaddingLeft(); boolean forceNextLine = line.charAt(line.length() - 1) == 10; int length = line.length() - 1; if (forceNextLine || length == 0) { canvas.drawText(line, x, baseLineY, getPaint()); return; } float d = (getMeasuredWidth() - lineWidth - getPaddingLeft() - getPaddingRight()) / length; for (int i = 0; i < line.length(); ++i) { String c = String.valueOf(line.charAt(i)); float cw = StaticLayout.getDesiredWidth(c, this.getPaint()); canvas.drawText(c, x, baseLineY, this.getPaint()); x += cw + d; }}}Copy the code

Attrs: Used when displaying a single line, it feels useless.

<declare-styleable name="AlignTextView">
        <attr name="alignOnlyOneLine" format="boolean"/>
    </declare-styleable>
Copy the code

Iv. Other implementation methods

Found a lot of information, there are other ways to achieve online, each has advantages and disadvantages, can be used for reference.

TextView adds a tag to the end of text and supports wrap

Android TextView adds tags, one or more

How to add an icon after the ellipsis when TextView multi-line text exceeds

Android TextView text wraps followed by the implementation of an icon or other control

Android has multiple tabs before or after text

Android Journey: Suddenly want to play with the TextView before the tag method