All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mapbox.mapboxsdk.annotations.Bubble Maven / Gradle / Ivy

There is a newer version: 9.2.1
Show newest version
package com.mapbox.mapboxsdk.annotations;

import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;

class Bubble extends Drawable {

  private RectF rect;
  private float arrowWidth;
  private float arrowHeight;
  private float arrowPosition;
  private float cornersRadius;
  private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
  private float strokeWidth;
  private Paint strokePaint;
  private Path strokePath;
  private Path path = new Path();

  Bubble(RectF rect, ArrowDirection arrowDirection, float arrowWidth, float arrowHeight, float arrowPosition,
         float cornersRadius, int bubbleColor, float strokeWidth, int strokeColor) {
    this.rect = rect;
    this.arrowWidth = arrowWidth;
    this.arrowHeight = arrowHeight;
    this.arrowPosition = arrowPosition;
    this.cornersRadius = cornersRadius;
    paint.setColor(bubbleColor);
    this.strokeWidth = strokeWidth;

    if (strokeWidth > 0) {
      strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
      strokePaint.setColor(strokeColor);
      strokePath = new Path();
      initPath(arrowDirection, path, strokeWidth);
      initPath(arrowDirection, strokePath, 0);
    } else {
      initPath(arrowDirection, path, 0);
    }
  }

  @Override
  protected void onBoundsChange(Rect bounds) {
    super.onBoundsChange(bounds);
  }

  @Override
  public void draw(Canvas canvas) {
    if (strokeWidth > 0) {
      canvas.drawPath(strokePath, strokePaint);
    }
    canvas.drawPath(path, paint);
  }

  @Override
  public int getOpacity() {
    return PixelFormat.TRANSLUCENT;
  }

  @Override
  public void setAlpha(int alpha) {
    paint.setAlpha(alpha);
  }

  @Override
  public void setColorFilter(ColorFilter cf) {
    paint.setColorFilter(cf);
  }

  @Override
  public int getIntrinsicWidth() {
    return (int) rect.width();
  }

  @Override
  public int getIntrinsicHeight() {
    return (int) rect.height();
  }

  private void initPath(ArrowDirection arrowDirection, Path path, float strokeWidth) {
    switch (arrowDirection.getValue()) {
      case ArrowDirection.LEFT:
        if (cornersRadius <= 0) {
          initLeftSquarePath(rect, path, strokeWidth);
          break;
        }

        if (strokeWidth > 0 && strokeWidth > cornersRadius) {
          initLeftSquarePath(rect, path, strokeWidth);
          break;
        }

        initLeftRoundedPath(rect, path, strokeWidth);
        break;
      case ArrowDirection.TOP:
        if (cornersRadius <= 0) {
          initTopSquarePath(rect, path, strokeWidth);
          break;
        }

        if (strokeWidth > 0 && strokeWidth > cornersRadius) {
          initTopSquarePath(rect, path, strokeWidth);
          break;
        }

        initTopRoundedPath(rect, path, strokeWidth);
        break;
      case ArrowDirection.RIGHT:
        if (cornersRadius <= 0) {
          initRightSquarePath(rect, path, strokeWidth);
          break;
        }

        if (strokeWidth > 0 && strokeWidth > cornersRadius) {
          initRightSquarePath(rect, path, strokeWidth);
          break;
        }

        initRightRoundedPath(rect, path, strokeWidth);
        break;
      case ArrowDirection.BOTTOM:
        if (cornersRadius <= 0) {
          initBottomSquarePath(rect, path, strokeWidth);
          break;
        }

        if (strokeWidth > 0 && strokeWidth > cornersRadius) {
          initBottomSquarePath(rect, path, strokeWidth);
          break;
        }

        initBottomRoundedPath(rect, path, strokeWidth);
        break;
    }
  }

  private void initLeftSquarePath(RectF rect, Path path, float strokeWidth) {
    path.moveTo(arrowWidth + rect.left + strokeWidth, rect.top + strokeWidth);
    path.lineTo(rect.width() - strokeWidth, rect.top + strokeWidth);

    path.lineTo(rect.right - strokeWidth, rect.bottom - strokeWidth);

    path.lineTo(rect.left + arrowWidth + strokeWidth, rect.bottom - strokeWidth);

    path.lineTo(rect.left + arrowWidth + strokeWidth, arrowHeight + arrowPosition - (strokeWidth / 2));
    path.lineTo(rect.left + strokeWidth + strokeWidth, arrowPosition + arrowHeight / 2);
    path.lineTo(rect.left + arrowWidth + strokeWidth, arrowPosition + (strokeWidth / 2));

    path.lineTo(rect.left + arrowWidth + strokeWidth, rect.top + strokeWidth);

    path.close();
  }

  private void initLeftRoundedPath(RectF rect, Path path, float strokeWidth) {
    path.moveTo(arrowWidth + rect.left + cornersRadius + strokeWidth, rect.top + strokeWidth);
    path.lineTo(rect.width() - cornersRadius - strokeWidth, rect.top + strokeWidth);
    path.arcTo(new RectF(rect.right - cornersRadius, rect.top + strokeWidth, rect.right - strokeWidth,
      cornersRadius + rect.top), 270, 90);

    path.lineTo(rect.right - strokeWidth, rect.bottom - cornersRadius - strokeWidth);
    path.arcTo(new RectF(rect.right - cornersRadius, rect.bottom - cornersRadius,
      rect.right - strokeWidth, rect.bottom - strokeWidth), 0, 90);

    path.lineTo(rect.left + arrowWidth + cornersRadius + strokeWidth, rect.bottom - strokeWidth);

    path.arcTo(new RectF(rect.left + arrowWidth + strokeWidth, rect.bottom - cornersRadius,
      cornersRadius + rect.left + arrowWidth, rect.bottom - strokeWidth), 90, 90);

    path.lineTo(rect.left + arrowWidth + strokeWidth, arrowHeight + arrowPosition - (strokeWidth / 2));

    path.lineTo(rect.left + strokeWidth + strokeWidth, arrowPosition + arrowHeight / 2);

    path.lineTo(rect.left + arrowWidth + strokeWidth, arrowPosition + (strokeWidth / 2));

    path.lineTo(rect.left + arrowWidth + strokeWidth, rect.top + cornersRadius + strokeWidth);

    path.arcTo(new RectF(rect.left + arrowWidth + strokeWidth, rect.top + strokeWidth, cornersRadius
      + rect.left + arrowWidth, cornersRadius + rect.top), 180, 90);

    path.close();
  }

  private void initTopSquarePath(RectF rect, Path path, float strokeWidth) {
    path.moveTo(rect.left + arrowPosition + strokeWidth, rect.top + arrowHeight + strokeWidth);

    path.lineTo(rect.left + arrowPosition + (strokeWidth / 2), rect.top + arrowHeight + strokeWidth);
    path.lineTo(rect.left + arrowWidth / 2 + arrowPosition, rect.top + strokeWidth + strokeWidth);
    path.lineTo(rect.left + arrowWidth + arrowPosition - (strokeWidth / 2), rect.top + arrowHeight + strokeWidth);
    path.lineTo(rect.right - strokeWidth, rect.top + arrowHeight + strokeWidth);

    path.lineTo(rect.right - strokeWidth, rect.bottom - strokeWidth);

    path.lineTo(rect.left + strokeWidth, rect.bottom - strokeWidth);

    path.lineTo(rect.left + strokeWidth, rect.top + arrowHeight + strokeWidth);

    path.lineTo(rect.left + arrowPosition + strokeWidth, rect.top + arrowHeight + strokeWidth);

    path.close();
  }

  private void initTopRoundedPath(RectF rect, Path path, float strokeWidth) {
    path.moveTo(rect.left + Math.min(arrowPosition, cornersRadius) + strokeWidth, rect.top + arrowHeight
      + strokeWidth);
    path.lineTo(rect.left + arrowPosition + (strokeWidth / 2), rect.top + arrowHeight + strokeWidth);
    path.lineTo(rect.left + arrowWidth / 2 + arrowPosition, rect.top + strokeWidth + strokeWidth);
    path.lineTo(rect.left + arrowWidth + arrowPosition - (strokeWidth / 2), rect.top + arrowHeight + strokeWidth);
    path.lineTo(rect.right - cornersRadius - strokeWidth, rect.top + arrowHeight + strokeWidth);

    path.arcTo(new RectF(rect.right - cornersRadius,
        rect.top + arrowHeight + strokeWidth, rect.right - strokeWidth, cornersRadius + rect.top + arrowHeight),
      270, 90);
    path.lineTo(rect.right - strokeWidth, rect.bottom - cornersRadius - strokeWidth);

    path.arcTo(new RectF(rect.right - cornersRadius, rect.bottom - cornersRadius,
      rect.right - strokeWidth, rect.bottom - strokeWidth), 0, 90);
    path.lineTo(rect.left + cornersRadius + strokeWidth, rect.bottom - strokeWidth);

    path.arcTo(new RectF(rect.left + strokeWidth, rect.bottom - cornersRadius,
      cornersRadius + rect.left, rect.bottom - strokeWidth), 90, 90);

    path.lineTo(rect.left + strokeWidth, rect.top + arrowHeight + cornersRadius + strokeWidth);

    path.arcTo(new RectF(rect.left + strokeWidth, rect.top + arrowHeight + strokeWidth, cornersRadius
      + rect.left, cornersRadius + rect.top + arrowHeight), 180, 90);

    path.close();
  }

  private void initRightSquarePath(RectF rect, Path path, float strokeWidth) {
    path.moveTo(rect.left + strokeWidth, rect.top + strokeWidth);
    path.lineTo(rect.width() - arrowWidth - strokeWidth, rect.top + strokeWidth);

    path.lineTo(rect.right - arrowWidth - strokeWidth, arrowPosition + (strokeWidth / 2));
    path.lineTo(rect.right - strokeWidth - strokeWidth, arrowPosition + arrowHeight / 2);
    path.lineTo(rect.right - arrowWidth - strokeWidth, arrowPosition + arrowHeight - (strokeWidth / 2));

    path.lineTo(rect.right - arrowWidth - strokeWidth, rect.bottom - strokeWidth);

    path.lineTo(rect.left + strokeWidth, rect.bottom - strokeWidth);
    path.lineTo(rect.left + strokeWidth, rect.top + strokeWidth);

    path.close();
  }

  private void initRightRoundedPath(RectF rect, Path path, float strokeWidth) {
    path.moveTo(rect.left + cornersRadius + strokeWidth, rect.top + strokeWidth);
    path.lineTo(rect.width() - cornersRadius - arrowWidth - strokeWidth, rect.top + strokeWidth);
    path.arcTo(new RectF(rect.right - cornersRadius - arrowWidth,
      rect.top + strokeWidth, rect.right - arrowWidth - strokeWidth, cornersRadius + rect.top), 270, 90);

    path.lineTo(rect.right - arrowWidth - strokeWidth, arrowPosition + (strokeWidth / 2));
    path.lineTo(rect.right - strokeWidth - strokeWidth, arrowPosition + arrowHeight / 2);
    path.lineTo(rect.right - arrowWidth - strokeWidth, arrowPosition + arrowHeight - (strokeWidth / 2));
    path.lineTo(rect.right - arrowWidth - strokeWidth, rect.bottom - cornersRadius - strokeWidth);

    path.arcTo(new RectF(rect.right - cornersRadius - arrowWidth, rect.bottom - cornersRadius,
      rect.right - arrowWidth - strokeWidth, rect.bottom - strokeWidth), 0, 90);
    path.lineTo(rect.left + arrowWidth + strokeWidth, rect.bottom - strokeWidth);

    path.arcTo(new RectF(rect.left + strokeWidth, rect.bottom - cornersRadius,
      cornersRadius + rect.left, rect.bottom - strokeWidth), 90, 90);

    path.arcTo(new RectF(rect.left + strokeWidth, rect.top + strokeWidth, cornersRadius
      + rect.left, cornersRadius + rect.top), 180, 90);
    path.close();
  }

  private void initBottomSquarePath(RectF rect, Path path, float strokeWidth) {
    path.moveTo(rect.left + strokeWidth, rect.top + strokeWidth);
    path.lineTo(rect.right - strokeWidth, rect.top + strokeWidth);
    path.lineTo(rect.right - strokeWidth, rect.bottom - arrowHeight - strokeWidth);

    path.lineTo(rect.left + arrowWidth + arrowPosition - (strokeWidth / 2), rect.bottom - arrowHeight - strokeWidth);
    path.lineTo(rect.left + arrowPosition + arrowWidth / 2, rect.bottom - strokeWidth - strokeWidth);
    path.lineTo(rect.left + arrowPosition + (strokeWidth / 2), rect.bottom - arrowHeight - strokeWidth);
    path.lineTo(rect.left + arrowPosition + strokeWidth, rect.bottom - arrowHeight - strokeWidth);

    path.lineTo(rect.left + strokeWidth, rect.bottom - arrowHeight - strokeWidth);
    path.lineTo(rect.left + strokeWidth, rect.top + strokeWidth);
    path.close();
  }

  private void initBottomRoundedPath(RectF rect, Path path, float strokeWidth) {
    path.moveTo(rect.left + cornersRadius + strokeWidth, rect.top + strokeWidth);
    path.lineTo(rect.width() - cornersRadius - strokeWidth, rect.top + strokeWidth);
    path.arcTo(new RectF(rect.right - cornersRadius,
      rect.top + strokeWidth, rect.right - strokeWidth, cornersRadius + rect.top), 270, 90);

    path.lineTo(rect.right - strokeWidth, rect.bottom - arrowHeight - cornersRadius - strokeWidth);
    path.arcTo(new RectF(rect.right - cornersRadius, rect.bottom - cornersRadius - arrowHeight,
      rect.right - strokeWidth, rect.bottom - arrowHeight - strokeWidth), 0, 90);

    path.lineTo(rect.left + arrowWidth + arrowPosition - (strokeWidth / 2), rect.bottom - arrowHeight - strokeWidth);
    path.lineTo(rect.left + arrowPosition + arrowWidth / 2, rect.bottom - strokeWidth - strokeWidth);
    path.lineTo(rect.left + arrowPosition + (strokeWidth / 2), rect.bottom - arrowHeight - strokeWidth);
    path.lineTo(rect.left + Math.min(cornersRadius, arrowPosition) + strokeWidth, rect.bottom - arrowHeight
      - strokeWidth);

    path.arcTo(new RectF(rect.left + strokeWidth, rect.bottom - cornersRadius - arrowHeight,
      cornersRadius + rect.left, rect.bottom - arrowHeight - strokeWidth), 90, 90);
    path.lineTo(rect.left + strokeWidth, rect.top + cornersRadius + strokeWidth);
    path.arcTo(new RectF(rect.left + strokeWidth, rect.top + strokeWidth, cornersRadius
      + rect.left, cornersRadius + rect.top), 180, 90);
    path.close();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy