好记性不如烂笔头。生活中多做笔记,不仅可以方便自己,还可以方便他人。
背景
以往,绝大多数的,我们的ListPreference的summary和entries都是纯文字的,这没啥可说的,简单方便嘛。突然有一天,产品经理跟我说,这个加上个图片会更生动好看一点。作为“”开发汪”,面对新的东西,内心是“”鸡冻”澎湃的,立马拍拍胸口“包在我身上”。
正文
看到这样的样式,第一想法是重写view替换其中的布局,挺简单的嘛,不就是绘制一下文字跟图片而已,位置随便来,想怎么搞就怎么搞。于是我着手看源码,寻找布局,找接口。看到 setDialogLayoutResource 时心中暗想“这不是挺简单的嘛”。然而问题来了,我得替换整个布局,前提是不能修改整个弹框的风格,因为这个ListPreference得跟其他的看起来一个风格,如果把布局写得一模一样也不是不行,但感觉有点小题大作了。
我的目标很明确,只是插入一个图标而已,仅此而已啊!
前面的方法不实际,于是我继续google,百度。找着找着,我突然想起,做到文字中插入图片的还有一个办法,那就是 SpannableString。于是我赶紧看回ListPreference的源码,重点来了。
ListPreference的setSummary方法:
/**
* Sets the summary for this Preference with a CharSequence.
* If the summary has a
* {@linkplain java.lang.String#format String formatting}
* marker in it (i.e. "%s" or "%1$s"), then the current entry
* value will be substituted in its place when it's retrieved.
*
* @param summary The summary for the preference.
*/
@Override
public void setSummary(CharSequence summary) {
super.setSummary(summary);
if (summary == null && mSummary != null) {
mSummary = null;
} else if (summary != null && !summary.equals(mSummary)) {
mSummary = summary.toString();
}
}
ListPreference的setEntries方法:
/**
* Sets the summary for this Preference with a CharSequence.
* If the summary has a
* {@linkplain java.lang.String#format String formatting}
* marker in it (i.e. "%s" or "%1$s"), then the current entry
* value will be substituted in its place when it's retrieved.
*
* @param summary The summary for the preference.
*/
@Override
public void setSummary(CharSequence summary) {
super.setSummary(summary);
if (summary == null && mSummary != null) {
mSummary = null;
} else if (summary != null && !summary.equals(mSummary)) {
mSummary = summary.toString();
}
}
从上面的两个方法看,文字的传入都是CharSequence类型,再看看SpannableString,刚好是实现了CharSequence接口。
好了,思路有了,说干就干。
代码非常的简单,就那么几句,上图:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
SpannableString[] entries = new SpannableString[] {
createEntrie("左边"),
createEntrie("左边")
};
String[] entryValues = new String[] {
"1",
"2"
};
mTestListPreference = (TestListPreference) findPreference("test_list_preference");
mTestListPreference.setEntries(entries);
mTestListPreference.setEntryValues(entryValues);
mTestListPreference.setSummary(createEntrie("summary"));
mTestListPreference.setOnPreferenceChangeListener(mOnPreferenceChangeListener);
}
public SpannableString createEntrie(String str) {
Resources res = getResources();
String replacedStr = "image";
final SpannableString spannableString = new SpannableString(str + replacedStr + "右边");
Drawable drawable = res.getDrawable(R.drawable.ic_launcher);
drawable.setBounds(0, 0,
res.getDimensionPixelSize(R.dimen.entrie_drawable_right),
res.getDimensionPixelSize(R.dimen.entrie_drawable_bottom));
CenteredImageSpan span = new CenteredImageSpan(drawable);
spannableString.setSpan(span, str.length(), str.length() + replacedStr.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
return spannableString;
}
创建好SpannableString之后,我们就可以插入图片了,位置可以随便插。这里以插入中间为例。上面的“image”就是我要替换为图片的字符串,我们要插入的是图片,所以只能通过ImageSpan,注意setSpan的时候start和end的位置要算对。
细心的你会发现,我上面用的TestListPreference,并不是ListPreference,为啥?因为我重写了ListPreference,为啥要重写?因为我发现,ListPreference的mSummary是String类型,这样的话,我们的的summary就无法插入图片了,所以重写了setSummary方法和getSummary方法:
public class TestListPreference extends ListPreference {
public CharSequence mSummary;
public TestListPreference(Context context) {
super(context);
}
public TestListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public TestListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public TestListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public CharSequence getSummary() {
return mSummary;
}
@Override
public void setSummary(CharSequence summary) {
super.setSummary(summary);
if (summary == null && mSummarymary != null) {
mSummary = null;
} else if (summary != null && !summary.equals(mSummary)) {
mSummary = summary;
}
}
}
好了,成功的在summary和entries中插入图片,来看看成果:
然而,你会发现,图片的位置水平方向没有居中,偏下沉了,所以我们还要调整一下。
继承ImageSpan,我们重写draw方法:
public class CenteredImageSpan extends ImageSpan {
public CenteredImageSpan(Drawable d) {
super(d);
}
@Override
public void draw(Canvas canvas, CharSequence text,
int start, int end, float x,
int top, int y, int bottom, Paint paint) {
Drawable b = getDrawable();
Paint.FontMetricsInt fm = paint.getFontMetricsInt();
int transY = (y + fm.descent + y + fm.ascent) / 2
- b.getBounds().bottom / 2;
canvas.save();
canvas.translate(x, transY);
b.draw(canvas);
canvas.restore();
}
}
代码比较简单,我就直接全部贴出来了。
OK,我们再来看看效果:
好了,全部完成了。
结尾
东西比较简单,内容也不多,但还是写出来,喜欢就拿去呗,反正又不要钱,而且我也是参考了网上很多的资料。