Android-使用StaticLayout实现icon跟随TextView末尾效果
👉关于作者
已经工作三年的95后程序员,坐标上海。平时在公司写Android原生App,业余时间会抽空学习Java后端,目标是成为全栈工程师,志同道合的可以私我聊聊haha。加入CSDN快4年了,看了很多优秀作者的博客收获很多。后面的时间里,我也会整理一些工作中使用到的知识分享出来。我的座右铭:人生在勤,不索何获。大家一起努力加油吧
👉正文部分
1、StaticLayout基本使用
通过drawText方法绘制出的文字超过一行后不会自动换行,StaticLayout可以对文字进行换行;TextView也用了StaticLayout
1、使用
@Override
protected void onDraw(Canvas canvas) {
TextPaint tp = new TextPaint();
//Paint设置字体大小的单位时像素,要将dp转为px设置
tp.setTextSize(UiUtils.dip2px(mContext,20));
tp.setColor(Color.parseColor("#111111"));
tp.setFakeBoldText(true);
tp.setAntiAlias(true);
tp.setStyle(Paint.Style.FILL);
String text = "在Android开发中,Canvas.drawText不会换行,即使一个很长的字符串也只会显示一行,超出部分会隐藏在屏幕之外.StaticLayout是android中处理文字的一个工具类,StaticLayout 处理了文字换行的问题";
//执行该方法后绘制出的文本不会进行换行
// canvas.drawText(text,0,UiUtils.dip2px(mContext,200),tp);
StaticLayout staticLayout = new StaticLayout(text, tp, canvas.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false);
staticLayout.draw(canvas);
}
2、构造器
public StaticLayout(CharSequence source, TextPaint paint, int outerwidth,Alignment align,float spacingmult, float spacingadd,boolean includepad){
}
- source:文本
- paint:画笔
- outerWidth:一行的宽度
- align:文本对齐方式
- spacingmult:行间距
- spacingadd:在行间距的基础上增加的值
- includepad:略,设置false
2、使用StaticLayout实现icon跟随TextView末尾效果
在RelativeLayout中有一个TextView和ImageView,TextView会动态改变其内容,ImageView要始终跟着TextView的末尾处
1、效果图
2、XML代码
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<TextView
android:id="@+id/tv"
style="@style/style_title_light_black_size_14"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/follow_textview_demo"/>
<ImageView
android:id="@+id/iv"
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/question_gray_icon"/>
</RelativeLayout>
3、实现思路
1、如何获取TextView每一行文本的最右边位置
当TextView换行了,我们得知道TextView最底部的那一行的文本写到什么位置,这样ImageView可以跟着这个位置去显示。答案是用StaticLayout去获取,代码如下
//先要按照TextView的Style生成一个Paint
TextPaint tp = new TextPaint();
tp.setStyle(Paint.Style.FILL);
tp.setTextSize(UiUtils.dip2px(FollowTextViewDemoActivity.this,14));
tp.setColor(Color.parseColor("#111111"));
tp.setAntiAlias(true);
StaticLayout sl = new StaticLayout(tv.getText(), tp, tv.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false);
int lineBottom = sl.getLineBottom(sl.getLineCount() - 1);
float lineRight = sl.getLineRight(sl.getLineCount() - 1);
2、ImageView跟在TextView末尾会跑出屏幕外
ImageView跟在TextView末尾有两种情况:ImageView跟在TextView后面可以显示出来;ImageView跟在TextView后面不会显示出来。第一种,也就是TextView的文本没有占满屏幕宽度,ImageView可以在文本的末尾显示出来;第二种,TextView的文本几乎占满屏幕宽度,ImageView在文本后面显示,就跑出屏幕外了。第二种情况我们就要对TextView进行重新setText,将目前的文本以最后一个字符为分割线,中间加入换行符,这样原本会占满屏幕的TextView会重新换一行,此时ImageView再跟在后面就不会跑出屏幕了
StaticLayout sl;
TextPaint tp = new TextPaint();
tp.setStyle(Paint.Style.FILL);
tp.setTextSize(UiUtils.dip2px(FollowTextViewDemoActivity.this,14));
tp.setColor(Color.parseColor("#111111"));
tp.setAntiAlias(true);
tv.post(new Runnable() {
@Override
public void run() {
sl = new StaticLayout(tv.getText(), tp, tv.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false);
float lineRight = sl.getLineRight(sl.getLineCount() - 1);
//如果TextView最后一行文本的最右边+ImageView的marginLeft+ImageView的大小超出了屏幕宽度
if ((int)lineRight + UiUtils.dip2px(FollowTextViewDemoActivity.this,6)+ UiUtils.dip2px(FollowTextViewDemoActivity.this,16) > tv.getWidth()){
//将现有文本的最后一个字符前加入换行符,以使TextView最后一行再换一行出来,就解决上面ImageView超出屏幕宽度的问题
String text = tv.getText().toString();
String substring1 = text.substring(0, text.length() - 1);
String substring2 = text.substring(text.length() - 1);
text = String.format("%s\n%s",substring1,substring2);
tv.setText(text);
tv.post(new Runnable() {
@Override
public void run() {
//ImageView位置:底部和TextView底部同一位置,左边=TextView的最后一行文本的右边+ImageView的marginLeft
sl = new StaticLayout(tv.getText(), tp, tv.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false);
float lineRight = sl.getLineRight(sl.getLineCount() - 1);
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) iv.getLayoutParams();
lp.topMargin = tv.getHeight() - lp.height;
lp.leftMargin = (int)lineRight + UiUtils.dip2px(FollowTextViewDemoActivity.this,6);
Log.e("FollowTextViewDemo","topMargin:"+lp.topMargin+",leftMargin:"+lp.leftMargin);
iv.setLayoutParams(lp);
}
});
}else {
//ImageView位置:底部和TextView底部同一位置,左边=TextView的最后一行文本的右边+ImageView的marginLeft
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) iv.getLayoutParams();
lp.topMargin = tv.getHeight() - lp.height;
lp.leftMargin = (int)lineRight + UiUtils.dip2px(FollowTextViewDemoActivity.this,6);
Log.e("FollowTextViewDemo","topMargin:"+lp.topMargin+",leftMargin:"+lp.leftMargin);
iv.setLayoutParams(lp);
}
}
});
参考文章
android TextView文字换行内容末尾跟图标或其他View的实现