Android 原生 ImageSpan 垂直局中及左右边距问题解决

2021-05-06 15:31:01 浏览数 (1)

关于Android 原生 ImageSpan 无法设置垂直局中及左右边距问题,找了很多博客,均无效或者有 bug,只能自己动手了,代码经测试有效。

代码语言:javascript复制
package com.example.myapplication;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.style.ImageSpan;
import androidx.annotation.NonNull;

public class VerticalImageSpan extends ImageSpan {

    private final int marginLeft;
    private final int marginRight;

    public VerticalImageSpan(Drawable drawable) {
        this(drawable, 0, 0);
    }

    public VerticalImageSpan(@NonNull Drawable drawable, int marginLeft, int marginRight) {
        super(drawable);
        this.marginLeft = marginLeft;
        this.marginRight = marginRight;
    }

    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end,
                       Paint.FontMetricsInt fontMetricsInt) {
        Drawable drawable = getDrawable();
        Rect rect = drawable.getBounds();
        if (null != fontMetricsInt) {
            Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
            int fontHeight = fmPaint.descent - fmPaint.ascent;
            int drHeight = rect.bottom - rect.top;
            int centerY = fmPaint.ascent   fontHeight / 2;
            fontMetricsInt.ascent = centerY - drHeight / 2;
            fontMetricsInt.top = fontMetricsInt.ascent;
            fontMetricsInt.bottom = centerY   drHeight / 2;
            fontMetricsInt.descent = fontMetricsInt.bottom;
        }
        return marginLeft   rect.right   marginRight;
    }

    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end,
                     float x, int top, int y, int bottom, Paint paint) {
        Drawable drawable = getDrawable();
        canvas.save();
        Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
        x = marginLeft   x;
        int fontHeight = fmPaint.descent - fmPaint.ascent;
        int centerY = y   fmPaint.descent - fontHeight / 2;
        int transY = centerY - (drawable.getBounds().bottom - drawable.getBounds().top) / 2;
        canvas.translate(x, transY);
        drawable.draw(canvas);
        canvas.restore();
    }

}
代码语言:javascript复制
package com.example.myapplication;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.util.AttributeSet;
import androidx.appcompat.widget.AppCompatTextView;

public class SimpleTextView extends AppCompatTextView {

    private static final String TAG = "*";
    private int margin;

    public SimpleTextView(Context context) {
        super(context);
    }

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

    public SimpleTextView(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.SimpleTextView);
        margin = DpUtils.dip2px(context, 4);
        setTextContent(typedArray.getString(R.styleable.SimpleTextView_setText));
        typedArray.recycle();
    }

    public void setTextContent(Editable editable){
        if(!TextUtils.isEmpty(editable)){
            setTextContent(editable.toString());
        }
    }

    public void setTextContent(String content){
        if(!TextUtils.isEmpty(content)){
            SpannableString spannableString = new SpannableString(content   TAG);
            Drawable drawable = getResources().getDrawable(R.mipmap.icon_tips);
            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
            VerticalImageSpan imageSpan = new VerticalImageSpan(drawable, margin, 0);
            spannableString.setSpan(imageSpan, content.length(), content.length()   TAG.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
            setText(spannableString);
        }
    }



}
代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="SimpleTextView">
        <attr name="setText" format="string" />
    </declare-styleable>
</resources>
代码语言:javascript复制
package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatEditText;

import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private AppCompatEditText editText;
    private SimpleTextView simpleTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        editText = findViewById(R.id.editInput);
        simpleTextView = findViewById(R.id.textView);
        findViewById(R.id.btnTest).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if(v.getId() == R.id.btnTest){
            onBtnTestClick();
        }
    }

    private void onBtnTestClick() {
        simpleTextView.setTextContent(editText.getText());
    }

}
代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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=".MainActivity">

   <androidx.appcompat.widget.AppCompatEditText
       android:id="@ id/editInput"
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       app:layout_constraintLeft_toLeftOf="parent"
       app:layout_constraintRight_toRightOf="parent"
       app:layout_constraintTop_toTopOf="parent" />
    <androidx.appcompat.widget.AppCompatButton
        android:id="@ id/btnTest"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/editInput"
        android:text="测试按钮"/>

    <com.example.myapplication.SimpleTextView
        android:id="@ id/textView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:setText="Hello Worldsdfdsfsdfdsfdsdsfdsfsddsfdsdsfsdfdssdff!"
        android:textSize="16sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btnTest" />

    <androidx.appcompat.widget.AppCompatButton
        android:id="@ id/btnTest01"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textView"
        android:text="按钮01"/>
    <androidx.appcompat.widget.AppCompatButton
        android:id="@ id/btnTest02"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btnTest01"
        android:text="按钮02"/>
    <androidx.appcompat.widget.AppCompatButton
        android:id="@ id/btnTest03"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btnTest02"
        android:text="按钮03"/>
    <androidx.appcompat.widget.AppCompatButton
        android:id="@ id/btnTest04"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btnTest03"
        android:text="按钮04"/>

</androidx.constraintlayout.widget.ConstraintLayout>

0 人点赞