关于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>