ListPreference的summary和entries中插入图片

好记性不如烂笔头。生活中多做笔记,不仅可以方便自己,还可以方便他人。

背景

以往,绝大多数的,我们的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,我们再来看看效果:

这里写图片描述

好了,全部完成了。

结尾

东西比较简单,内容也不多,但还是写出来,喜欢就拿去呗,反正又不要钱,而且我也是参考了网上很多的资料。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值