1. 程式人生 > >Android之旅:突然想玩的TextView前面加標籤的方法

Android之旅:突然想玩的TextView前面加標籤的方法

前言

可能很多朋友在做設計稿的時候經常會遇到這種問題:
image.png

好好的textView前面加了個標籤…
這要是單行還好,直接一個drawable了事
但是多行…我可以自定義一個ShapeDrawable,實現drawableLeft,但是有個問題,如果是這樣的話,drawable是會隨字型居中的,那顯示效果就很怪異了!

思路

通過html

最簡單的方法肯定是通過html,不用計算什麼start,end,而且現成就有的樣式都可以 拿來用。
html樣式程式碼如下:
image.png

<font color="white" style="background:red;border-radius: 6px;font-size: 18px"
>
I love android </font>

然而…並不支援,貌似是textView不支援這個border-radius屬性…而我貧乏的html知識也只能記得這個屬性了。好吧,這條路gg。

通過span

這個是最靠譜的解決方法了吧,其實span可以幫我們解決幾乎所有關於textview的問題,可是貌似很多人(包括我)都不瞭解她。

具體可以瞭解下

程式碼實現:

自定義TextView

自定義了TextView 在其內部進行處理,免得每次都是一套function方法複製來複制去:

package com.example.ly.testdrawable;

import
android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.text.Spannable; import android.text.SpannableString; import android.text.style.ImageSpan; import android.util.AttributeSet; import android.util.Log; import
android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; import java.util.List; /** * Author: Ly * Data:2018/5/30-19:08 * Description: */ public class TagTextView extends android.support.v7.widget.AppCompatTextView { private StringBuffer content_buffer; private TextView tv_tag; private View view;//標籤佈局的最外層佈局 private Context mContext; //必須重寫所有的構造器,否則可能會出現無法inflate佈局的錯誤! public TagTextView(Context context) { super(context); mContext = context; } public TagTextView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; } public TagTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; } public void setContentAndTag(String content, List<String> tags) { content_buffer = new StringBuffer(); for (String item : tags) {//將每個tag的內容新增到content後邊,之後將用drawable替代這些tag所佔的位置 content_buffer.append(item); } content_buffer.append(content); SpannableString spannableString = new SpannableString(content_buffer); for (int i = 0; i < tags.size(); i++) { String item = tags.get(i); View view = LayoutInflater.from(mContext).inflate(R.layout.tag, null);//R.layout.tag是每個標籤的佈局 tv_tag = view.findViewById(R.id.tv_tag); tv_tag.setText(item); Bitmap bitmap = convertViewToBitmap(view); Drawable d = new BitmapDrawable(bitmap); d.setBounds(0, 0, tv_tag.getWidth(), tv_tag.getHeight());//缺少這句的話,不會報錯,但是圖片不回顯示 ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BOTTOM);//圖片將對齊底部邊線 int startIndex; int endIndex; startIndex = getLastLength(tags, i ); endIndex = startIndex + item.length(); Log.e("tag", "the start is" + startIndex + "the end is" + endIndex); spannableString.setSpan(span, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } setText(spannableString); setGravity(Gravity.CENTER_VERTICAL); } private static Bitmap convertViewToBitmap(View view) { view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); view.buildDrawingCache(); Bitmap bitmap = view.getDrawingCache(); return bitmap; } private int getLastLength(List<String> list, int maxLength) { int length = 0; for (int i = 0; i < maxLength; i++) { length += list.get(i).length(); } return length; } }

自定義一個標準的tag佈局:

面向xml程式設計,後期需要修改drawable樣式等可以通過這個xml做文章。

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <TextView
        android:id="@+id/tv_tag"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginBottom="2dp"
        android:layout_marginRight="5dp"
        android:background="@drawable/bg_blue_20"
        android:gravity="center_vertical"
        android:paddingBottom="2dp"
        android:paddingLeft="3dp"
        android:paddingRight="3dp"
        android:text="標籤"
        android:textColor="@android:color/white"
        android:textSize="12sp"/>
</LinearLayout>

具體使用(xml)

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.ly.testdrawable.MainActivity">

    <com.example.ly.testdrawable.TagTextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

</android.support.constraint.ConstraintLayout>

具體使用(java)

package com.example.ly.testdrawable;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TagTextView textView = findViewById(R.id.text);
        List<String> tags = new ArrayList<>();
        tags.add("置頂");
        tags.add("置頂1");
        tags.add("置頂2");
        textView.setContentAndTag("凌宇是個大帥逼",
                tags);
    }
}

效果如下

image.png