您的位置:首页 > 移动开发 > Android开发

用最简单且兼容性最好的方式去实现dialog的有序列表

2017-06-14 10:49 267 查看

用最简单且兼容性最好的方式去实现dialog的有序列表

最近项目开发,遇到这样一个dialog的需求,请看图:



这里有一个细节,如 2. 那条,如果文字长度超过一行,下一行文字是从序号后边对齐的。

要实现这种dialog,也厚很多种实现方式

自定义 dialog 布局,把内容写死在里边

用 html 标签来完成这种布局

自定义 LeadingMarginSpan ,用 SpannableStringBuilder 拼接字符串来实现(本篇的主要内容)

第一种方式(自定义 dialog 布局)

应该大多数人都会的,就是麻烦一点。

第二种方式(html 标签)

相比第一种简单了很多,直接用
Html.fromHtml()
来包裹 html标签的内容就可以了。起初我用的是这种方式,测试后也没问题,但在魅族手机上发现, html 标签有的不识别(文字前边的序号没有出来),对开发者来说 android 的开源有时候也会带来麻烦。。只好重新研究实现方式了。

第三种方式(自定义 LeadingMarginSpan)

/**
* 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.
* <p>
* 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<String> 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

第四种方式(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<String> 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,
a4a6
contentEnd, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}

MaterialDialogUtil.showSendSuccessTip(_mActivity, "提问成功", completeStr
, new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
pop();
}
});
}


这里不需要自定义什么类就完成了,无疑是最省事的,可见如果对 android 本身了解的不多,是要做多少无用功。。

以此自勉,继续奋进吧
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息