高德地图-Android自定义气泡

作者: XJ_crazy | 来源:发表于2018-09-05 17:45 被阅读15次

    最近公司需求做一个气泡弹框,又不想让UI给切割.9图,咋办呢,自己动手呗,这么好的学习机会

    首先看一下最终的效果图,激励一下(Android小白第一个作品,不喜勿喷,谢谢)

    文章后有源码,可以依据源码一阅读。

    image.png

    讲一下解决思路:

    1.根据字串的长度获取气泡中间矩形的宽度

    2.根据矩形的高的一半作为半径,画圆弧

    3.设置气泡底部小三角形的底边长,画一个等腰直角三角形

    4.绘制文字,由于数字需要不一样的颜色,这里我将“距离你”,“米”,还有数字分别获取了宽度(绘制的时候起点坐标需要设置)

    接下来讲一下每一个步骤的主要技术

    准备工作:控件所在xml代码,宽和高均为wrap_content,这里注意,外层LinearLayout背景需要设置成透明#00000000,

                画笔模式设置为填充paint.setStyle(Paint.Style.FILL_AND_STROKE);
    
    image

    1.获取字串宽度使用paint的measureText方法,获取字串总长度textWidth,并在onMeasure方法中调用setMeasureDimension方法设置控件需要占据的长和宽。(不调用setMeasureDimension方法,将无法正常显示控件)

    image

    2.画圆弧,调用方法path.arcTo(rectF oval, float startAngle,float sweepAngle,boolean forceMoveTo)

    参数介绍:1.圆所在矩形 2.开始角度 3.弧的角度 4.是否将上次移动的终点与弧起点连接

    3.这一步其实没什么好讲的,计算好点的坐标,直接path.lineTo即可。

    4.这一步计算text的长度,进行绘制,这个难点不大。但是这里遇到了一个问题.

    即由字串起点x=width/2-textWdith/2,y=height/2-fontSize/2画出来的字串,始终没有完全居中。

    search之后发现,canvas.drawText(text, x, y, paint);中的y,其实是baseline在屏幕上的位置,而baseline却不是在字串的中间,这里需要经过处理

    image image

    到这里,基本是已经完成了气泡的绘制了,但是看上去太平面了,所以我们给它加上阴影效果

    this.setLayerType(View.LAYER_TYPE_SOFTWARE,paint);

    paint.setShadowLayer(10F,1F,1F,Color.GRAY);

    两行代码,so easy!!!

    当然要显示出阴影效果,那么必须在你绘制的图形边缘有一部分的空间,不然无法显示。

    最后给出我的源码:

    
    public class BubbleViewextends View {
    
        Paint paint;
    
        int textWidth;
    
        int rectHeight =80; //矩形高
    
        int circleR = rectHeight/2;//圆弧半径
    
        String textPre ="距离你";
    
        int textPreWidth;
    
        String textEnd ="米";
    
        int textNumWidth;
    
        String textNum ="";
    
        String text;
    
        private int fontSize =30;//字体大小
    
        private int padding =20;//内容边距
    
        private int bottomLine =26;//等腰直角三角形底边长
    
        int width;//view总宽
    
        int height = padding + rectHeight + bottomLine/2 + padding; //view总高
    
        private Path path;
    
        private String distance;
    
        public BubbleView(Context context) {
    
            super(context);
    
            init();
    
        }
    
        public BubbleView(Context context, @Nullable AttributeSet attrs) {
    
            super(context, attrs);
    
            init();
    
        }
    
        public BubbleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    
            super(context, attrs, defStyleAttr);
    
            init();
    
        }
    
        public void init() {
    
            resetPaint();
    
            this.setLayerType(View.LAYER_TYPE_SOFTWARE,paint);
    
            paint.setShadowLayer(10F,1F,1F,Color.GRAY);
    
            text = textPre + textNum + textEnd;
    
            textWidth = (int) paint.measureText(text);
    
            textPreWidth = (int) paint.measureText(textPre);
    
            textNumWidth = (int) paint.measureText(textNum);
    
            path =new Path();
    
        }
    
        public String getDistance(){
    
            return distance;
    
        }
    
        public void setText(String textNum){
    
            this.textNum = textNum;
    
            init();
    
            invalidate();
    
        }
    
        public void resetPaint() {
    
            //初始化画笔
    
            paint =new Paint();
    
            //设置抗锯齿
    
            paint.setAntiAlias(true);
    
            //设置填充
    
            paint.setStyle(Paint.Style.FILL_AND_STROKE);
    
            //设置防抖动
    
            paint.setDither(true);
    
            paint.setTextSize(fontSize);
    
        }
    
        @Override
    
        protected void onDraw(Canvas canvas) {
    
            super.onDraw(canvas);
    
            init();
    
            drawRect(canvas);
    
        }
    
        private void drawRect(Canvas canvas) {
    
            paint.setColor(Color.parseColor("#ffffff"));
    
            RectF rectF =new RectF(padding, padding, padding + circleR*2, padding + circleR*2);
    
            path.arcTo(rectF, 270, -180,false);
    
            path.lineTo(width/2 - bottomLine/2, padding + circleR*2);
    
            path.lineTo(width/2, padding + circleR*2 + bottomLine/2);
    
            path.lineTo(width/2 + bottomLine/2, padding + circleR*2);
    
            path.lineTo(padding + circleR + textWidth, padding + circleR *2);
    
            RectF rectF1 =new RectF(padding + circleR + textWidth - circleR, padding, padding + circleR + textWidth + circleR, padding + circleR*2);
    
            path.arcTo(rectF1, 90, -180,false);
    
            path.lineTo(padding + circleR, padding);
    
            canvas.drawPath(path, paint);
    
            resetPaint();
    
            paint.setColor(Color.parseColor("#333333"));
    
            Rect bounds =new Rect();
    
            paint.getTextBounds(text, 0, text.length(), bounds);
    
            Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
    
            int baseline = (height - bottomLine/2 - fontMetrics.descent + fontMetrics.ascent) /2 - fontMetrics.ascent;
    
            canvas.drawText(textPre, width/2-textWidth/2, baseline, paint);
    
            canvas.drawText(textEnd, width/2-textWidth/2 + textPreWidth + textNumWidth, baseline, paint);
    
            resetPaint();
    
            paint.setColor(Color.parseColor("#ff9500"));
    
            canvas.drawText(textNum, width/2-textWidth/2 + textPreWidth, baseline, paint);
    
        }
    
        @Override
    
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            width = padding + circleR + textWidth + circleR + padding;
    
            setMeasuredDimension(width, height);
    
        }
    
    }
    

    相关文章

      网友评论

      • XJ_crazy:我的这个自定义view中,onDraw被无限调用了,问题是今天打印日志的时候才发现的,没有找到问题出处,求大佬给点思路
        Euterpe:@七分執 ondraw方法尽量不要new对象。还有三个构造方法,第一个用this调用第二个,第二个用this调用第三个,在第三个里面初始化各种对象。

      本文标题:高德地图-Android自定义气泡

      本文链接:https://www.haomeiwen.com/subject/dkqzwftx.html