仿小米便簽圖文混排 EditText解決尾部插入文字bug

來源:互聯網
上載者:User

標籤:

一直想實現像小米便簽那樣的圖文混排效果,收集網上的辦法無非三種:
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(("<img " + path + " img>").length()+contentText.getText().length() > MAX_CONTENT){            Toast.makeText(getApplicationContext(), R.string.toast_reached_max_text, 2000).show();            return;        }        SpannableString ss = new SpannableString("<img " + path + " img>");        if (span == null)            throw new NullPointerException("span cant be null");        ss.setSpan(span, 0, ("<img " + path + " img>").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(("<img " + path + " img>").length()+contentText.getText().length() > MAX_CONTENT){            Toast.makeText(getApplicationContext(), R.string.toast_reached_max_text, 2000).show();            return;        }        SpannableString ss = new SpannableString("<img " + path + " img>");        // 不再用緩衝模式        // 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, ("<img " + path + " img>").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來源:http://www.baidufe.com/item/65fd7eba51123bbe80bc.html
一直沒能理解作者說的半形站位
我實現了一個方法,當游標到達圖片末尾,直接跳轉至正確位置
實現:http://mxw3755.iteye.com/admin/blogs/2164905
當游標嵌入spannableString的字元從末尾前一位,我們可以將游標位置+1,這樣游標會在兩張圖之間
3、如何儲存解析圖文混排的EditText

可以將ImageSpan的位置儲存到Arraylist中,怎麼儲存至資料庫請參考 http://mxw3755.iteye.com/admin/blogs/2165147

 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); 

 

仿小米便簽圖文混排 EditText解決尾部插入文字bug

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.