仿半塘图片添加标签功能

来源:互联网 发布:ubuntu安装tomcat 编辑:程序博客网 时间:2024/05/29 17:02

模仿半塘app的图片添加标签功能,刚开始反编译了半塘的代码,结果代码太多了,用一些三方的东西,觉的比较麻烦,这里自己写了一下实现,感觉和半塘的没啥区别(自我感觉良好,嘿嘿)

一、半塘功能实现步骤
选择要处理的图片
标签处理
添加一个标签
添加两个标签

二、半塘实现分析

功能分析
- 本地相册选择
- 添加图片
- 添加标签
- 标签移动
- 标签动画切换
- 图片生成

实现说明
(1) 标签类型有两种 第一种是单个标签 第二种是两个标签
(2) 第一种标签的包含:原点和文字
(3) 第二步标签包含:原点、文字和横线
(4) 原点的位置是点击的位置
(5) 文字有两种样式,一种是向左的,一种是向右的(对应实现)
(6) 横线有四种样式
横向的四种样式,对应实现

三、实现

(1)类结构图
实现的类结构图
(2)代码结构
实现的代码结构图
(3)具体实现

圆点的实现

public class LabelRoundDot extends Drawable{    private Paint mPaint;    private Bitmap mBitmap;    private RectF rectF;    public LabelRoundDot(Bitmap bitmap) {        mBitmap = bitmap;        BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);        mPaint = new Paint();        mPaint.setAntiAlias(true);        mPaint.setShader(bitmapShader);    }    @Override    public void setBounds(int left, int top, int right, int bottom)    {        super.setBounds(left, top, right, bottom);        rectF = new RectF(left, top, right, bottom);    }    @Override    public void draw(Canvas canvas) {        canvas.drawRoundRect(rectF, 30, 30, mPaint);    }    @Override    public int getIntrinsicWidth()    {        return mBitmap.getWidth();    }    @Override    public int getIntrinsicHeight()    {        return mBitmap.getHeight();    }    @Override    public void setAlpha(int alpha)    {        mPaint.setAlpha(alpha);    }    @Override    public void setColorFilter(ColorFilter cf)    {        mPaint.setColorFilter(cf);    }    @Override    public int getOpacity()    {        return PixelFormat.TRANSLUCENT;    }}

文字的实现
初始化

 public LabelTextView(String labelText, int textType){        this.labelText = labelText;        this.currentType = textType;        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mPaint.setTextSize(TEXT_SIZE);        initLabel();    }  private void initLabel(){        Rect mBounds = new Rect();        mPaint.getTextBounds(this.labelText, 0, this.labelText.length(), mBounds);        this.labelTextHeight = mBounds.height() + VIEW_PADDING;        this.labelTextWidth = labelTextHeight/2 +(mBounds.width()<6? 6:mBounds.width()) + VIEW_PADDING;        Log.i(TAG, "initLabel labelTextHeight = " + labelTextHeight + " labelTextWidth = " + labelTextWidth);    }

画第一种类型

private void drawFrist(Canvas canvas){        mPaint.setStrokeWidth(3);        mPaint.setColor(Color.parseColor("#99000000"));        //画半圆        RectF oval = new RectF(0, 0, labelTextHeight, labelTextHeight);        canvas.drawArc(oval, 270, -180, true, mPaint);        Rect targetRect = new Rect(labelTextHeight/2, 0, labelTextWidth - VIEW_PADDING, labelTextHeight);        canvas.drawRect(targetRect, mPaint);        //画三角形        Path path = new Path();        path.moveTo(labelTextWidth - VIEW_PADDING, 0);// 此点为多边形的起点        path.lineTo(labelTextWidth, labelTextHeight/2);        path.lineTo(labelTextWidth - VIEW_PADDING, labelTextHeight);        path.close(); // 使这些点构成封闭的多边形        canvas.drawPath(path, mPaint);        //写文字        mPaint.setColor(Color.parseColor("#ffffff"));        Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();        int baseline = (targetRect.bottom + targetRect.top - fontMetrics.bottom - fontMetrics.top) / 2;        // 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX()        mPaint.setTextAlign(Paint.Align.CENTER);        canvas.drawText(labelText, targetRect.centerX(), baseline, mPaint);    }

画第二种类型

 private void drawSecond(Canvas canvas){        Log.i(TAG, "onDrawSecond ---------");        mPaint.setStrokeWidth(3);        mPaint.setColor(Color.parseColor("#99000000"));        //画半圆        RectF oval = new RectF(labelTextWidth - labelTextHeight, 0, labelTextWidth, labelTextHeight);        canvas.drawArc(oval,90, -180, true, mPaint);        //画矩形        Rect targetRect = new Rect(VIEW_PADDING, 0, labelTextWidth-labelTextHeight/2, labelTextHeight);        canvas.drawRect(targetRect, mPaint);        //画三角形        Path path = new Path();        path.moveTo(VIEW_PADDING, 0);// 此点为多边形的起点        path.lineTo(0, labelTextHeight/2);        path.lineTo(VIEW_PADDING, labelTextHeight);        path.close(); // 使这些点构成封闭的多边形        canvas.drawPath(path, mPaint);        //写文字        mPaint.setColor(Color.parseColor("#ffffff"));        Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();        int baseline = (targetRect.bottom + targetRect.top - fontMetrics.bottom - fontMetrics.top) / 2;        // 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX()        mPaint.setTextAlign(Paint.Align.CENTER);        canvas.drawText(labelText, targetRect.centerX(), baseline, mPaint);    }

线条的实现
初始化

    public LabelLineView (int type){        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mPaint.setStrokeWidth(3);        mPaint.setColor(Color.parseColor("#99000000"));        labelHeight = slashHeight;        labelWidth = slashWidth + straightLine;        this.currentType = type;        Log.i(TAG, "onDrawFirst  labelHeight = " + labelHeight + " labelWidth = " + labelWidth);    }

四种类型

    /**     *     * @param canvas     */    private void drawFrist(Canvas canvas){        //画第一条直线        int lineSx = 0;        int lineSy = 0;        int lineEx = straightLine;        int lineEy = 0;        canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线        lineSx = straightLine;        lineSy = 0;        lineEx = labelWidth;        lineEy = labelHeight;        canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线    }    /**     *     * @param canvas     */    private void drawSecond(Canvas canvas){        //画第一条直线        int lineSx = 0;        int lineSy = labelHeight;        int lineEx = straightLine;        int lineEy = labelHeight;        canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线        lineSx = straightLine;        lineSy = labelHeight;        lineEx = labelWidth;        lineEy = 0;        canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线    }    private void drawThird(Canvas canvas){        int lineSx = 0;        int lineSy = labelHeight;        int lineEx = slashWidth;        int lineEy = 0;        canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线        lineSx = slashWidth;        lineSy = 0;        lineEx = labelWidth;        lineEy = 0;        canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线    }    private void drawFourth(Canvas canvas){        //画第一条直线        int lineSx = 0;        int lineSy = 0;        int lineEx = slashWidth;        int lineEy = slashHeight;        canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线        lineSx = slashWidth;        lineSy = slashHeight;        lineEx = labelWidth;        lineEy = labelHeight;        canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线    }

LabelViewListener标签的实现监听
包含:标签的位置、切换样式、显示和隐藏动画、更新坐标(中心)、更新内容、判断是否点击到中心等方法。

只有一个内容的标签
有两种绘制模式,包含原点和文字,记录中心位置和当前的模式
包含绘制两种模式的方法、显示和隐藏的动画、提供view的大小和位置等。
第一种模式

    /**     * 绘制第一模式     *     * @param canvas     */    private void onDrawFirst(Canvas canvas) {        Log.i(TAG, "onDrawFirst ---------");        canvas.drawBitmap(Utils.drawableToBitmap(labelTextView),4,0,mPaint);        //画原点        int xBmp = labelViewWidth-originPic.getWidth();        int yBmp = (labelViewHeight-originPic.getWidth())/2;        canvas.drawBitmap(originPic, xBmp, yBmp, null);        Log.i(TAG, "onDrawFirst xBmp = " + xBmp + " yBmp = " + yBmp);    }

第二种模式

    /**     * 绘制第二模式     *     * @param canvas     */    private void onDrawSecond(Canvas canvas) {        Log.i(TAG, "onDrawSecond ---------");        canvas.drawBitmap(Utils.drawableToBitmap(labelTextView), originPic.getWidth()-4, 0, mPaint);        //画原点        int xBmp = 0;        int yBmp = (labelViewHeight-originPic.getWidth())/2;        canvas.drawBitmap(originPic, xBmp, yBmp, null);        Log.i(TAG, "onDrawFirst xBmp = " + xBmp + " yBmp = " + yBmp);    }

显示动画

    @Override    public ValueAnimator getLabelShowAnim() {        ValueAnimator anim = null;        if (currentType == FRIST_MODEL) {            anim = ValueAnimator.ofInt(labelViewWidth, 0);        } else if (currentType == SECOND_MODEL) {            anim = ValueAnimator.ofInt(0, labelViewWidth);        }        if (anim == null) {            return null;        }        anim.setDuration(500);        return anim;    }

隐藏动画

    @Override    public ValueAnimator getLabelHideAnim() {        ValueAnimator anim = null;        if (currentType == FRIST_MODEL) {            anim = ValueAnimator.ofInt(0, labelViewWidth);        } else if (currentType == SECOND_MODEL) {            anim = ValueAnimator.ofInt(labelViewWidth, 0);        }        if (anim == null) {            return null;        }        anim.setDuration(500);        return anim;    }

有两个内容的标签
包含圆点、线条和文字
有四种绘制模式

第一种模式

    /**     * 绘制第一模式     *     * @param canvas     */    private void onDrawFirst(Canvas canvas) {        Log.i(TAG, "onDrawFirst ---------");        //上面的文字        canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewFirst),                labelViewWidth-originPic.getWidth()-labelLineViewFirst.getIntrinsicWidth()-labelTextViewFirst.getIntrinsicWidth(),                0,mPaint);        //上面的线条        canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewFirst),                labelViewWidth-originPic.getWidth()-labelLineViewFirst.getIntrinsicWidth(),                labelTextViewFirst.getIntrinsicHeight()/2,                mPaint);        //下面的文字        canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewSecond),                labelViewWidth - originPic.getWidth() - labelLineViewSecond.getIntrinsicWidth() - labelTextViewSecond.getIntrinsicWidth(),                labelViewHeight - labelTextViewSecond.getIntrinsicHeight(),                mPaint);        //下面的线条        canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewSecond),                labelViewWidth - originPic.getWidth() - labelLineViewSecond.getIntrinsicWidth(),                labelTextViewFirst.getIntrinsicHeight() / 2 + labelLineViewFirst.getIntrinsicHeight(),                mPaint);        //画原点        int xBmp = labelViewWidth - originPic.getWidth();        int yBmp = (labelViewHeight - originPic.getWidth()) / 2;        canvas.drawBitmap(originPic, xBmp, yBmp, null);        Log.i(TAG, "onDrawFirst xBmp = " + xBmp + " yBmp = " + yBmp);    }

第二种模式

    /**     * 绘制第二模式     *     * @param canvas     */    private void onDrawSecond(Canvas canvas) {        Log.i(TAG, "onDrawSecond ---------");        //上面条线        canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewFirst),                originPic.getWidth(),                labelTextViewFirst.getIntrinsicHeight()/2,                mPaint);        //上面文字        canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewFirst),               originPic.getWidth()+labelLineViewFirst.getIntrinsicWidth(),                0,                mPaint);        //下面线条        canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewSecond),                originPic.getWidth(),                labelTextViewFirst.getIntrinsicHeight()/2+labelLineViewFirst.getIntrinsicHeight(),                mPaint);        //下面文字        canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewSecond),                originPic.getWidth()+labelLineViewSecond.getIntrinsicWidth(),                labelViewHeight - labelTextViewSecond.getIntrinsicHeight(),                mPaint);        //画原点        int xBmp = 0;        int yBmp = (labelViewHeight-originPic.getWidth())/2;        canvas.drawBitmap(originPic, xBmp, yBmp, null);        Log.i(TAG, "onDrawSecond xBmp = " + xBmp + " yBmp = " + yBmp);    }

第二种模式

    /**     * 第三种绘制     */    private void onDrawThird(Canvas canvas){        Log.i(TAG, "onDrawSecond ---------");        //左边的文字        canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewFirst),                0,                0,                mPaint);        //上面条线        canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewFirst),                labelTextViewFirst.getIntrinsicWidth(),                labelTextViewFirst.getIntrinsicHeight()/2,                mPaint);        //画原点        int xBmp = labelTextViewFirst.getIntrinsicWidth()+labelLineViewFirst.getIntrinsicWidth();        int yBmp = (labelViewHeight-originPic.getHeight())/2;        canvas.drawBitmap(originPic, xBmp, yBmp, null);        Log.i(TAG, "onDrawSecond xBmp = " + xBmp + " yBmp = " + yBmp);        //下面线条        canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewSecond),                labelTextViewFirst.getIntrinsicWidth()+labelLineViewFirst.getIntrinsicWidth()+originPic.getWidth(),                labelViewHeight/2,                mPaint);        //下面文字        canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewSecond),                labelViewWidth - labelTextViewSecond.getIntrinsicWidth(),                labelViewHeight - labelTextViewSecond.getIntrinsicHeight(),                mPaint);    }

第四种模式

    /**     * 第四种绘制     */    private void onDrawFourth(Canvas canvas){        Log.i(TAG, "onDrawFourth ---------");        //左边文字        canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewFirst),                0,                labelViewHeight-labelTextViewFirst.getIntrinsicHeight(),                mPaint);        //左边条线        canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewFirst),                labelTextViewFirst.getIntrinsicWidth(),                labelViewHeight-labelTextViewFirst.getIntrinsicHeight()/2-labelLineViewFirst.getIntrinsicHeight(),                mPaint);        //画原点        int xBmp = labelTextViewFirst.getIntrinsicWidth()+labelLineViewFirst.getIntrinsicWidth();        int yBmp = (labelViewHeight-originPic.getWidth())/2;        canvas.drawBitmap(originPic, xBmp, yBmp, null);        Log.i(TAG, "onDrawSecond xBmp = " + xBmp + " yBmp = " + yBmp);        //右边线条        canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewSecond),                labelTextViewFirst.getIntrinsicWidth()+labelLineViewFirst.getIntrinsicWidth()+originPic.getWidth(),                labelTextViewSecond.getIntrinsicHeight()/2,                mPaint);        //右边文字        canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewSecond),                labelViewWidth-labelTextViewSecond.getIntrinsicWidth(),                0,                mPaint);    }

以上大致说了一下思路
这是代码链接
https://github.com/gyh/GCustomView

2 0