博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
仿小米便签图文混排 EditText解决尾部插入文字bug
阅读量:6112 次
发布时间:2019-06-21

本文共 4718 字,大约阅读时间需要 15 分钟。

一直想实现像小米便签那样的图文混排效果,收集网上的办法无非三种:

1、自定义布局,每张图片是一个ImageView,插入图片后插入EditText,缺点是实现复杂,不能像小米便签那样同时选中图片和文字
2、通过Html.fromHtml(source),可以将图片加载写进ImageGetter,实现后无bug,但是只能显示Html,当EditText setText后,想取出之前的HTML格式
     图片得到的是一个obj的字符,查看了很多博客,包括stackoverflow也没给出办法从editable中解析出spanned对象。若谁有方法希望不吝啬告诉我。
3、通过ImageSpan和SpannableString,这是我实现的方法,而且较为理想,不但可以写入EditText,也可以从EditText中解析出图文混排排版。

1、插入图片到光标位置

/**     * 将图片路径映射到Bitmap,再通过SpannableString 和 ImageSpan显示到EditText     */    private void setImageView() {        // 如果EditText中已经有相同资源的ImageSpan,则不再读取图片        ImageSpan imageSpan = getImageSpanFromExistence(imagePath);        if (imageSpan != null) {            insertIntoEditor(imageSpan, imagePath);            return;        }         if (imagePath != null && (!imagePath.equals("null"))                && (!"".equals(imagePath))) {            insertIntoEditor(imagePath);            /*             * 不再用缓存模式             */        }    } /**     * 从当前的EditText获取ImageSpan,如果存在则返回否则返回Null     *     * @return     */    private ImageSpan getImageSpanFromExistence(String source) {        Editable edit = contentText.getText();        ImageSpan[] spans = edit.getSpans(0, edit.length(), ImageSpan.class);        for (ImageSpan ip : spans) {            int start = edit.getSpanStart(ip);            int end = edit.getSpanEnd(ip);            String path = edit.toString().substring(start, end);            path = path.substring(5, path.length() - 5);             if (source.equals(path)) {                Logg.D("find existed ImageSpan");                return new ImageSpan(ip.getDrawable(), ImageSpan.ALIGN_BASELINE);            }        }        return null;    } /**     * 向光标位置插入ImageSpan,针对EditText已经有ImageSpan的情况     *     * @param ip     *            ImageSpan     * @param path     *            路径     */    private void insertIntoEditor(ImageSpan span, String path) {        if(("").length()+contentText.getText().length() > MAX_CONTENT){            Toast.makeText(getApplicationContext(), R.string.toast_reached_max_text, 2000).show();            return;        }        SpannableString ss = new SpannableString("");        if (span == null)            throw new NullPointerException("span cant be null");        ss.setSpan(span, 0, ("").length(),                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);        Editable et = contentText.getText();// 先获取Edittext中的内容        int start = contentText.getSelectionStart();        et.insert(start, ss);// 设置ss要添加的位置        contentText.setSelection(start + ss.length());// 设置Edittext中光标在最后面显示        Logg.D("insertIntoEditor by using existed ImageSpan");    } /**     * 向光标位置插入ImageSpan,针对EditText没有图片的情况     *     * @param path     *            图片路径     */    private void insertIntoEditor(String path) {        if(("").length()+contentText.getText().length() > MAX_CONTENT){            Toast.makeText(getApplicationContext(), R.string.toast_reached_max_text, 2000).show();            return;        }        SpannableString ss = new SpannableString("");        // 不再用缓存模式        // Bitmap bm = mEditorHelper.getImage(path);        Bitmap bm = PictureHelper.getImageFromPath(imagePath,                screenWidth * 0.7F, screenWidth * 0.7F, false, 100,                Editor.this, imgPadding, false);        if (bm == null) {            throw new NullPointerException("bm cant be null");        }         ImageSpan span = new ImageSpan(this, bm, ImageSpan.ALIGN_BASELINE);        ss.setSpan(span, 0, ("").length(),                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);        Editable et = contentText.getText();// 先获取Edittext中的内容        int start = contentText.getSelectionStart();        et.insert(start, ss);// 插入图片到光标处//        contentText.setSelection(start + ss.length());// 设置Edittext中光标在最后面显示        Logg.D("insertIntoEditor by loading new");    }

以上插入图片前会查找edittext有没有相同地址的ImageSpan,如果有则不再读取新的Bitmap,直接复用drawable

2、解决尾部插入Bug\

Bug来源:

一直没能理解作者说的半角站位
我实现了一个方法,当光标到达图片末尾,直接跳转至正确位置
实现:
当光标嵌入spannableString的字符从末尾前一位,我们可以将光标位置+1,这样光标会在两张图之间
3、如何保存解析图文混排的EditText

可以将ImageSpan的位置保存到Arraylist中,怎么保存至数据库请参考

 android 图文结合,使用SpannableString和ImageSpan类

    Drawable drawable = getResources().getDrawable(id);         drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());         //需要处理的文本,[smile]是需要被替代的文本         SpannableString spannable = new SpannableString(getText().toString()+"[smile]");         //要让图片替代指定的文字就要用ImageSpan         ImageSpan span = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);         //开始替换,注意第2和第3个参数表示从哪里开始替换到哪里替换结束(start和end)        //最后一个参数类似数学中的集合,[5,12)表示从5到12,包括5但不包括12         spannable.setSpan(span, getText().length(),getText().length()+"[smile]".length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);           setText(spannable);

 

转载地址:http://lzcka.baihongyu.com/

你可能感兴趣的文章
十分钟学会写shell脚本
查看>>
POJ1651Multiplication Puzzle[区间DP]
查看>>
Spring MVC 学习总结(一)——MVC概要与环境配置
查看>>
VBA -excel --遍历行
查看>>
数制和码制(后期可能有更新)
查看>>
Gradle sync failed: Failed to find Build Tools revision 26.0.2的解决办法
查看>>
Web前端知识体系
查看>>
洪涝有源淹没算法及淹没结果分析【转】
查看>>
delphi ios info.plist
查看>>
《C# 6.0 本质论》 阅读笔记
查看>>
PHP 返回JSON
查看>>
libsecp256k1 与 openssl ecdsa
查看>>
expectFAQ(附一个python批量任务脚本)--持续更新
查看>>
如何打开C++的RTTI机制
查看>>
AgileEAS.NET SOA 中间件平台工作流系统介绍
查看>>
完全背包题目:
查看>>
【读书笔记】《产品经理手册》
查看>>
阴影效果片段代码
查看>>
android XMl 解析神奇xstream 一: 解析android项目中 asset 文件夹 下的 aa.xml 文件
查看>>
秋叶PPT-三分钟教程
查看>>