1. 程式人生 > >Android StaticLayout實現主流便籤內容生成長圖功能

Android StaticLayout實現主流便籤內容生成長圖功能

便籤記事本是使用者常用的一類手機軟體,目前各大主流手機均自帶此類的工具,並且功能逐漸完善,其中有一項功能——一鍵生成圖片分享比較吸引眼球,尤其是有些社交app在分享動態時有字數限制,如果將要發的內容生成圖片就可以解決這個困擾。對比了幾家主流手機的自帶便籤,三星不具備生成圖片功能,錘子、魅族、華為具備,但生成時有稍微卡頓,小米同樣具備,生成圖片時未出現明顯示卡頓。現在我們也嘗試實現此功能。

我們常用的方式是使用Canvas的drawText繪製文字,但它是不會自動換行的,即使一個很長很長的字串,drawText也只顯示一行,超出部分被隱藏在螢幕之外。可以逐個計算每個字元的寬度,通過一定的演算法將字串分割成多個部分,然後分別呼叫drawText一部分一部分的顯示, 但是這種顯示效率會很低。
StaticLayout是android中處理文字換行的一個工具類,StaticLayout已經實現了文字繪製換行處理。它跟TextView的效果是一樣的,其實TextView也是呼叫StaticLayout來實現換行的。
StaticLayout的建構函式有三個:

public StaticLayout(CharSequence source,
                    TextPaint paint,
                    int width,
                    Layout.Alignment align,
                    float spacingmult,
                    float spacingadd,
                    boolean includepad)
                   
public StaticLayout(CharSequence source,
                    int bufstart,
                    int bufend,
                    TextPaint paint,
                    int outerwidth,
                    Layout.Alignment align,
                    float spacingmult,
                    float spacingadd,
                    boolean includepad)
                   
public StaticLayout(CharSequence source,
                    int bufstart,
                    int bufend,
                    TextPaint paint,
                    int outerwidth,
                    Layout.Alignment align,
                    float spacingmult,
                    float spacingadd,
                    boolean includepad,
                    TextUtils.TruncateAt ellipsize,
                    int ellipsizedWidth)

實際上都是呼叫的第三個建構函式,下面是它的引數解釋:

1.需要分行的字串
2.需要分行的字串從第幾的位置開始
3.需要分行的字串到哪裡結束
4.畫筆物件
5.layout的寬度,字串超出寬度時自動換行。
6.layout的對其方式,有ALIGN_CENTER, ALIGN_NORMAL, ALIGN_OPPOSITE 三種。
7.相對行間距,相對字型大小,1.5f表示行間距為1.5倍的字型高度。
8.在基礎行距上新增多少
實際行間距等於這兩者的和。
9.引數未知
10.從什麼位置開始省略
11.超過多少開始省略
需要指出的是這個layout是預設畫在Canvas的(0,0)點的,如果需要調整位置只能在draw之前移Canvas的起始座標
canvas.translate(x,y);

生成長圖功能的實現:

    public static Bitmap getBitmap(Context context, EditText mEditText) {
        Editable editable = mEditText.getText();
        TextPaint textPaint = new TextPaint();
        textPaint.setARGB(0xFF, 0, 0, 0);
        textPaint.setTextSize(mEditText.getTextSize()
                - DisplayUtils.sp2px(context, 2));

        // 設定字型
        String fontPath = Cache.read_String(SharedPreferencesKey.KEY_FONT, "");
        if (!TextUtils.isEmpty(fontPath)) {
            File fontFile = new File(fontPath);
            if (fontFile.isFile() && fontFile.exists())
                textPaint.setTypeface(Typeface.createFromFile(fontFile));
        }
        ScreenInfo mScreenInfo = ScreenInfo.getInstance();

        float bitmapWidth = mScreenInfo.getWidthPixels()
                - DisplayUtils.dip2px(context, 10);
        float padding = DisplayUtils.dip2px(context, 15);

        StaticLayout layout = new StaticLayout(editable, textPaint,
                (int) (bitmapWidth - padding * 4), Alignment.ALIGN_NORMAL,
                1.2F, 0.0F, true);

        float bitmapHeight = layout.getHeight() + padding * 10;

        Bitmap bitmap = null;
        try {
            bitmap = Bitmap.createBitmap((int) bitmapWidth, (int) bitmapHeight,
                    Bitmap.Config.ARGB_8888);
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
            return null;
        }
        Canvas paper = new Canvas(bitmap);
        paper.drawColor(ColorSelectView.getColor(2));

        paper.translate(padding * 2, padding * 4);

        layout.draw(paper);

        paper.translate(-padding * 2, -padding * 4);

        Paint mPaint = new Paint(Paint.DITHER_FLAG);
        mPaint.setColor(Color.GRAY);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(DisplayUtils.dip2px(context, 0.5f));

        float offset = DisplayUtils.dip2px(context, 2);

        paper.drawRect(new Rect((int) (padding), (int) (padding * 2),
                (int) (bitmapWidth - padding),
                (int) (bitmapHeight - padding * 4)), mPaint);

        paper.drawRect(new Rect((int) (padding - offset),
                (int) (padding * 2 - offset), (int) (padding),
                (int) (padding * 2)), mPaint);

        paper.drawRect(new Rect((int) (bitmapWidth - padding),
                (int) (padding * 2 - offset),
                (int) (bitmapWidth - padding + offset), (int) (padding * 2)),
                mPaint);

        paper.drawRect(new Rect((int) (padding - offset),
                (int) (bitmapHeight - padding * 4), (int) (padding),
                (int) (bitmapHeight - padding * 4 + offset)), mPaint);

        paper.drawRect(new Rect((int) (bitmapWidth - padding),
                (int) (bitmapHeight - padding * 4), (int) (bitmapWidth
                        - padding + offset),
                (int) (bitmapHeight - padding * 4 + offset)), mPaint);

        paper.drawRect(new Rect((int) (padding + offset),
                (int) (padding * 2 + offset),
                (int) (bitmapWidth - padding - offset), (int) (bitmapHeight
                        - padding * 4 - offset)), mPaint);

        TextPaint fromTextPaint = new TextPaint();
        fromTextPaint.setColor(Color.GRAY);
        fromTextPaint.setTextSize(DisplayUtils.sp2px(context, 12));
        StaticLayout fromLayout = new StaticLayout(Cache.read_String(
                KEY_SHARE_TAIL, context.getString(R.string.share_image_info)),
                fromTextPaint, (int) (bitmapWidth - padding * 3.5),
                Alignment.ALIGN_NORMAL, 1.0F, 0.0F, true);
        paper.translate(padding, bitmapHeight - padding * 3);
        fromLayout.draw(paper);

        return bitmap;
    }

效果展示: