最近项目开发,遇到这样一个dialog的需求,请看图:
这里有一个细节,如 2. 那条,如果文字长度超过一行,下一行文字是从序号后边对齐的。
要实现这种dialog,也厚很多种实现方式
应该大多数人都会的,就是麻烦一点。
相比第一种简单了很多,直接用 Html.fromHtml()
来包裹 html标签的内容就可以了。起初我用的是这种方式,测试后也没问题,但在魅族手机上发现, html 标签有的不识别(文字前边的序号没有出来),对开发者来说 android 的开源有时候也会带来麻烦。。只好重新研究实现方式了。
/**
* A paragraph style affecting the leading margin. There can be multiple leading
* margin spans on a single paragraph; they will be rendered in order, each
* adding its margin to the ones before it. The leading margin is on the right
* for lines in a right-to-left paragraph.
*
* LeadingMarginSpans should be attached from the first character to the last
* character of a single paragraph.
*/
这是 LeadingMarginSpan 的官方注释,大致意思就是 它可以影响一个段落的文字的起始 margin 值(原谅我的英语渣水平。。。)
ok,重点来了,下面就是自定义这货来实现 dialog 的有序列表了,好上代码:
public class NumberIndentSpan implements LeadingMarginSpan {
private int gapWidth;
private final int index;
public NumberIndentSpan(int index) {
this.index = index;
}
public int getLeadingMargin(boolean first) {
return gapWidth;
}
public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout l) {
if (first) {
Paint.Style orgStyle = p.getStyle();
p.setStyle(Paint.Style.FILL);
String text1 = index + ". ";
float width = p.measureText(text1);
gapWidth = (int) width;
com.orhanobut.logger.Logger.d(dir + "");
com.orhanobut.logger.Logger.d(width + "");
com.orhanobut.logger.Logger.d(x + "");
c.drawText(text1, x, baseline, p);
p.setStyle(orgStyle);
}
}
}
项目的设计是,api 成功后,返回一个 string 类型的集合,本地通过 dialog 去显示有序文本内容:
private void showSuccessTip(List completeStrs) {
SpannableStringBuilder completeStr = new SpannableStringBuilder();
completeStr.append("请留意:\n");
for (int i = 0; i < completeStrs.size(); i++) {
int contentStart = completeStr.length();
completeStr.append(completeStrs.get(i)).append("\n");
NumberIndentSpan numberIndentSpan = new NumberIndentSpan(i + 1);
completeStr.setSpan(numberIndentSpan, contentStart, completeStr.length(), 0);
}
这种方式我认为应该是最简单兼容性最好的方式了吧,
ok,今天就到这里了,如有不同意见欢迎拍砖~
更正一下一个内容
第三种自定义 LeadingMarginSpan,这种方法虽然实现了,但是发现控件测量字符串的宽度不准确了,靠近右边缘的字体有的被遮住半个,如图:
又研究了一下 LeadingMarginSpan 这个类,发现了一种神奇的东西 LeadingMarginSpan.Standard
Standard 类是 LeadingMarginSpan 的一个内部类,它有三个构造方法,如下:
/**
* Constructor taking separate indents for the first and subsequent
* lines.
*
* @param first the indent for the first line of the paragraph 段落第一行距离左边的间距
* @param rest the indent for the remaining lines of the paragraph 段落除第一行外剩下所有行距离左边的间距
*/
public Standard(int first, int rest) {
mFirst = first;
mRest = rest;
}
/**
* Constructor taking an indent for all lines.
* @param every the indent of each line
*/
public Standard(int every) {
this(every, every);
}
public Standard(Parcel src) {
mFirst = src.readInt();
mRest = src.readInt();
}
ok,我们用到的就是 Standard(int first, int rest)
,下边贴出使用方法:
private void showSuccessTip(List completeStrs) {
SpannableStringBuilder completeStr = new SpannableStringBuilder();
completeStr.append("请留意:\n");
for (int i = 0; i < completeStrs.size(); i++) {
int contentStart = completeStr.length();
String leadStr = (i + 1) + ". ";
completeStr.append(leadStr);
completeStr.append(completeStrs.get(i));
completeStr.append("\n");
int contentEnd = completeStr.length();
completeStr.setSpan(new LeadingMarginSpan.Standard(0, (int) mRightMenu.getPaint().measureText(leadStr))
, contentStart, contentEnd, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
MaterialDialogUtil.showSendSuccessTip(_mActivity, "提问成功", completeStr
, new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
pop();
}
});
}
这里不需要自定义什么类就完成了,无疑是最省事的,可见如果对 android 本身了解的不多,是要做多少无用功。。
以此自勉,继续奋进吧