Android 解決圖文混排,圖片和文字居中對齊問題(ImageSpan)
阿新 • • 發佈:2019-02-10
一. 概述
眾所周知,Android圖文混排可以通過SpannableString來實現,通過在相應位置使用ImageSpan替換即可,但是使用過的人會發現,imageSpan只提供了兩種對齊方式,如下所示:
/**
底部對齊
*/
public static final int ALIGN_BOTTOM = 0;
/**
基線對齊
*/
public static final int ALIGN_BASELINE = 1;
但是在大多數時候,我們希望實現圖片的中點和文字的中點對齊(視覺設計師肯定會給到這樣的要求),那麼該怎麼辦呢?
二. 圖文混排,圖片居中對齊方案
方案1:
一個比較簡單解決方案就是讓圖片和文字的高度保持一致,這樣就變相居中對齊了,那麼有一些朋友為難了,視覺給的圖片的高度比字型的高度小,這腫麼辦? 這個問題很好解決,讓視覺給你切大一點的圖片,即在原來的圖片上多切一些透明的白邊。(是不是恍然大悟?哈哈)
plus:圖片比文字高的情況根本不需要居中對齊。
方案2:
程式設計師肯定有程式設計師的方案,那就是擴充套件繼承ImageSpan,重寫它的onDraw()方法。這個方案本人蔘考了網上的一些解決方案,但是都有侷限性,有些方案只要設定的TextView行間距或者padding就不能正常工作了。
這篇部落格的方案,在設定了行間距的時候,就出現問題了。但是這篇部落格把字型繪製的原理說的很清楚了,建議大家先讀這篇部落格,再來理解本人的做法。
程式碼展示
好了,直接上程式碼,這是自定義ImageSpan的程式碼,非常少。主要的原理是把圖片繪製在字型的descent線和ascent的中點位置。還是那句話,先看上面那篇部落格。
public class CenterAlignImageSpan extends ImageSpan {
public CenterAlignImageSpan(Drawable drawable) {
super(drawable);
}
public CenterAlignImageSpan(Bitmap b) {
super(b);
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom,
@NonNull Paint paint) {
Drawable b = getDrawable();
Paint.FontMetricsInt fm = paint.getFontMetricsInt();
int transY = (y + fm.descent + y + fm.ascent) / 2 - b.getBounds().bottom / 2;//計算y方向的位移
canvas.save();
canvas.translate(x, transY);//繪製圖片位移一段距離
b.draw(canvas);
canvas.restore();
}
}
使用和執行效果
在佈局檔案裡放置一個TextView,設定其行間距。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context="com.example.hzwangqinwei.test.MainActivity"
>
<TextView
android:id="@+id/test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#aeae34"
android:gravity="center"
android:lineSpacingExtra="40dp"
android:textSize="70dp"
/>
</LinearLayout>
activity裡的程式碼如下展示:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.test);
SpannableString sp = new SpannableString("圖文混排測排測試圖文混排測試圖文混排測試圖文混排測試圖");
//獲取一張圖片
Drawable drawable = getDrawable(R.drawable.star);
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
//居中對齊imageSpan
CenterAlignImageSpan imageSpan = new CenterAlignImageSpan(drawable);
sp.setSpan(imageSpan, 0, 1, ImageSpan.ALIGN_BASELINE);
//普通imageSpan 做對比
ImageSpan imageSpan2 = new ImageSpan(drawable);
sp.setSpan(imageSpan2, 3, 4, ImageSpan.ALIGN_BASELINE);
tv.setText(sp);
}
}
執行效果,第二張圖片是普通的ImageSpan的效果,這裡加入進來是做一個對比。