前言
最近开发需求,就是名称后面加一个查看按钮。显示条件是文字只允许一行,超出部分显示省略号,并且右边紧挨着一个图标。点击条件是只有图标可以点击。先看效果图。
一、效果图
效果1:
效果2:
二、踩坑
因为想着条件是图标要单独点击,第一想到的就是使用ImageView实现。
踩坑1:
一开始,采用的方案是TextView+ImageView的方式,如下:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_resume_details_list_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
tools:text="xxxxxxxxxxx" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="xxx"
/>
</LinearLayout>
效果:文字超出一行时却是出现省略号,但就会把图标挤出屏幕外。
结果: 看不见图标了。 失败!
踩坑2:
我使用 weight 权重方式,这样就能保证文字超出一行时,能让图标留在屏幕内。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_resume_details_list_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:layout_weight="1"
android:ellipsize="end"
tools:text="xxxxxxxxxxx" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="xxx"
/>
</LinearLayout>
效果:文字超出一行显示省略号,图标也存在。 ✅ 文字不足一行,图标不跟随文字。❌
结果:失败! 图标位置固定在最后面了。
踩坑3:
同事建议使用约束布局-ConstraintLayout-实现 。一顿代码撸起来。。。。。
结果:图标要么依然挤出屏幕,要么固定在右边。
此时 陷入沉思。。。。
三、解决方案
我突然想到,使用TextView会经常使用到android:drawableLeft="@drawable/ic_launcher"这些类似的属性。
试了一下,果然好使!效果杠杠的!✅
但是,结合需求的实际情况:1、动态显示图标;2、图标可点击。
1、动态显示图标
而面对这些情况下,第一步就是需要动态在代码中设置文本周围的图标。
setCompoundDrawables(left, top, right, bottom);setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
setCompoundDrawables 画的drawable的宽高是按drawable.setBound()设置的宽高,使用之前必须使用Drawable.setBounds设置Drawable的长宽。
Drawable drawable= getResources().getDrawable(R.drawable.xxx);
drawable.setBounds(0, 0, 20, 20);
txtView.setCompoundDrawables(drawable,null,null,null);
setCompoundDrawablesWithIntrinsicBounds画的drawable的宽高是按drawable固定的宽高。
public void setCompoundDrawablesWithIntrinsicBounds (Drawable left,
Drawable top, Drawable right, Drawable bottom)
一般,建议使用setCompoundDrawablesWithIntrinsicBounds,这样你即无需设置Drawables的bounds了。
2、图标可点击。
textview.getCompoundDrawables() 获取是一个drawable 数组。即上面设置的图标数组,而索引0,1,2,3,对应着左,上,右,下 这4个位置的图标,如果没有就为null。
判断点击的是图标:
获取点击的X坐标值,比(TextView最右边界减去drwable边界宽度)大就可以判断点击在Drawable上。
比如,textview 宽度 =100;drawble宽度 = 20; 点击在80 -100 之间即可。
mCompanyName.setOnTouchListener((v, event) -> {
Drawable rightDrawable=mCompanyName.getCompoundDrawables()[2];
if(rightDrawable!=null&&event.getRawX()>=(mCompanyName.getRight()-rightDrawable.getBounds().width())){
ToastUtils.showShort("ok");
}
return false;
});
四、解决案例代码
<TextView
android:id="@+id/tv_resume_details_experience_company_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="#05081A"
android:textSize="16dp"
android:textStyle="bold"
tools:text="北京新知百略科技有限公司北京新知百北京新知百略科技有限公司北京新知百" />
if (!companyNo.isEmpty()){
mCompanyName.setCompoundDrawablesWithIntrinsicBounds(null, null, mContext.getResources().getDrawable(R.drawable.xxx), null);
mCompanyName.setOnTouchListener((v, event) -> {
Drawable rightDrawable= holder.mCompanyName.getCompoundDrawables()[2];
if(rightDrawable!=null&&event.getRawX()>=( holder.mCompanyName.getRight()-rightDrawable.getBounds().width())){
//点击成功
}
return false;
});
}else{
holder.mCompanyName.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
}
五、补充 SpannableString
/**
* 初始化举报区域显示
*/
private void initReportZone() {
String tip = "[icon] 提醒:以担保或任何理由索取财物,抵押证照,均涉嫌违法,请提高警惕! 点击举报 [arrow]";
SpannableString spannable = new SpannableString(tip);
//waring 图标
Drawable warningDrawable = CommonUtils.getContext().getResources().getDrawable(R.drawable.icon_position_warning);
warningDrawable.setBounds(0, 0, warningDrawable.getIntrinsicWidth(), warningDrawable.getIntrinsicHeight());
CenterAlignImageSpan warningSpan = new CenterAlignImageSpan(warningDrawable, ImageSpan.ALIGN_BASELINE);
int warningStartIndex = tip.indexOf("[icon]");
spannable.setSpan(warningSpan, warningStartIndex, warningStartIndex + "[icon]".length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
//粗体
int boldStartIndex = tip.indexOf("提醒:");
int boldEndIndex = boldStartIndex + "提醒:".length();
spannable.setSpan(new ForegroundColorSpan(CommonUtils.getContext().getResources().getColor(R.color.color_282b2d)), boldStartIndex, boldEndIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new AbsoluteSizeSpan(12, true), boldStartIndex, boldEndIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new StyleSpan(Typeface.BOLD), boldStartIndex, boldEndIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//点击区域
spannable.setSpan(new ClickableSpan() {
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(0XFF626970);
ds.setUnderlineText(false);
}
@Override
public void onClick(@NonNull View widget) {
reportPosition();
}
}, tip.indexOf("点击举报"), tip.indexOf("点击举报") + "点击举报".length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
//最末端的箭头icon
Drawable drawableArrowRight = ContextCompat.getDrawable(CommonUtils.getContext(), (R.drawable.position_detail_arrow_right));
drawableArrowRight.setBounds(0, 0, drawableArrowRight.getIntrinsicWidth(), drawableArrowRight.getIntrinsicHeight());
CenterAlignImageSpan arrowRightSpan = new CenterAlignImageSpan(drawableArrowRight, ImageSpan.ALIGN_BASELINE);
spannable.setSpan(arrowRightSpan, tip.indexOf("[arrow]"), tip.indexOf("[arrow]") + "[arrow]".length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
tv_report.setText(spannable);
tv_report.setMovementMethod(LinkMovementMethod.getInstance());
}