zoukankan      html  css  js  c++  java
  • 仿半塘图片加入标签功能

    模仿半塘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

  • 相关阅读:
    Linux 安装 PostgreSQL
    【Linux】ZeroMQ 在 centos下的安装
    Celery
    Django学习之完成数据库主从复制、读写分离和一主多从情况下的使用办法
    python异步编程之asyncio(百万并发)
    Python正则表达式中的re.S,re.M,re.I的作用
    云开发 :云原生(Cloud Native)
    极简Unity调用Android方法
    UnityShader快速上手指南(四)
    UnityShader快速上手指南(三)
  • 原文地址:https://www.cnblogs.com/jhcelue/p/7109962.html
Copyright © 2011-2022 走看看