小红点自定义View

  • 有段日子没写过自定义View了,一个小Demo,复习一下~
public class DragDotView extends View {

  /**
   * 文本内容
   */
  private String mTitleText;
  /**
   * 文本的颜色
   */
  private int mTitleTextColor;
  /**
   * 文本的大小
   */
  private int mTitleTextSize;

  /**
   * 背景色
   */
  private int mBackgroundColor;

  /**
   * 圆角大小
   */
  private int mCornerSize;

  /**
   * 绘制时控制文本绘制的范围
   */
  private Rect mTitleBound;

  /**
   * 边框宽度
   */
  private int mStockWidth;

  /**
   * 边框颜色
   */
  private int mStockColor;

  /**
   * 预期文字宽度
   */
  private int mDesiredWith;

  /**
   * 背景宽高
   */
  private int mBackgroundWidth;
  private int mBackgroundHeight;

  /**
   * 横向及纵向总padding(文字居中)(弃用Android:padding)
   */
  private int mVerticalTotalPadding;
  private int mHorizontalTotalPadding;

  /**
   * 实际宽高
   */
  private int mWidth;
  private int mHeight;

  private Paint mTitlePaint;
  private Paint mColorPaint;
  private Context mContext;

  /**
   * 默认属性
   */
  private final String DEFAULT_TITLE_TEXT = "";
  private final int DEFAULT_TEXT_COLOR = Color.WHITE;
  private final int DEFAULT_TEXT_SIZE = 12;
  private final int DEFAULT_BACKGROUND_COLOR = R.color.drag_dot_bg;
  private final int DEFAULT_RADIUS = Integer.MAX_VALUE;
  private final int DEFAULT_STOCK_WIDTH = R.dimen.dp1;
  private final int DEFAULT_STOCK_COLOR = R.color.drag_dot_stock;
  private final int DEFAULT_VERTICAL_TOTAL_PADDING = R.dimen.dp2;
  private final int DEFAULT_HORIZONTAL_TOTAL_PADDING = R.dimen.dp7;


  /**
   * 背景及边框
   */
  private RectF recStock;
  private RectF rec;


  public DragDotView(Context context) {
    this(context, null);
  }

  public DragDotView(Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public DragDotView(Context context,
      @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mContext = context;

    TypedArray a = context.getTheme()
        .obtainStyledAttributes(attrs, R.styleable.DragDotView, defStyleAttr, 0);

    // 文字内容
    if (TextUtils.isEmpty(a.getString(R.styleable.DragDotView_ddvText))) {
      mTitleText = DEFAULT_TITLE_TEXT;
    } else {
      mTitleText = a.getString(R.styleable.DragDotView_ddvText);
    }
    // 默认文字颜色设置为白色
    mTitleTextColor = a.getColor(R.styleable.DragDotView_ddvTextColor, DEFAULT_TEXT_COLOR);
    // 默认设置为12sp
    mTitleTextSize = a
        .getDimensionPixelSize(R.styleable.DragDotView_ddvTextSize, (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_SP, DEFAULT_TEXT_SIZE, getResources().getDisplayMetrics()));
    // 默认背景为红色
    mBackgroundColor = a.getColor(R.styleable.DragDotView_ddvBackground,
        getResources().getColor(DEFAULT_BACKGROUND_COLOR));
    // 默认为小圆点
    mCornerSize = a.getInteger(R.styleable.DragDotView_ddvCornerSize, DEFAULT_RADIUS);
    // 默认边框大小为1dp
    mStockWidth = a.getDimensionPixelSize(R.styleable.DragDotView_ddvStockWidth,
        DestinyUtil.getDP(context, DEFAULT_STOCK_WIDTH));
    // 默认边框颜色为白色
    mStockColor = a.getColor(R.styleable.DragDotView_ddvStockColor,
        getResources().getColor(DEFAULT_STOCK_COLOR));
    // 默认Padding
    mVerticalTotalPadding = a.getDimensionPixelSize(R.styleable.DragDotView_ddvVerticalTotalPadding,
        DestinyUtil.getDP(context, DEFAULT_VERTICAL_TOTAL_PADDING));
    mHorizontalTotalPadding = a
        .getDimensionPixelSize(R.styleable.DragDotView_ddvHorizontalTotalPadding,
            DestinyUtil.getDP(context, DEFAULT_HORIZONTAL_TOTAL_PADDING));

    a.recycle();

    initPaint();
  }

  /**
   * 初始化画笔
   */
  private void initPaint() {
    // 文字画笔
    mTitlePaint = new Paint();
    mTitlePaint.setTextSize(mTitleTextSize);
    mTitleBound = new Rect();
    mTitlePaint.getTextBounds(mTitleText, 0, mTitleText.length(), mTitleBound);
    // 背景画笔
    mColorPaint = new Paint();
    mColorPaint.setAntiAlias(true);
    // 背景及边框
    recStock = new RectF();
    rec = new RectF();
  }

  /**
   * 设置宽高总Padding(文字居中)
   *
   * @param verticalTotalPadding
   */
  public void setVerticalTotalPadding(int verticalTotalPadding) {
    this.mVerticalTotalPadding = verticalTotalPadding;
  }

  public void setHorizontalTotalPadding(int horizontalTotalPadding) {
    this.mHorizontalTotalPadding = horizontalTotalPadding;
  }


  /**
   * 更新Title内容
   */
  public void setTitleText(String text) {
    mTitleText = text;
    requestLayout();
    postInvalidate();
  }


  /**
   * 更新可见性
   */
  public void setVisible(boolean isVisible) {
    if (isVisible) {
      this.setVisibility(VISIBLE);
    } else {
      this.setVisibility(GONE);
    }
  }

  /**
   * 绑定在某一个View上(margin距离)
   */
  public void bindView(final View targetView, int marginLeft, int marginTop, int marginRight,
      int marginBottom) {
    // 从原父布局中删除
    if (getParent() != null) {
      ((ViewGroup) getParent()).removeView(this);
    }

    // 获取targetView的父布局
    ViewGroup parent = (ViewGroup) targetView.getParent();
    if (parent == null) {
      return;
    }
    int index = parent.indexOfChild(targetView);
    parent.removeView(targetView);

    // 容器大小为targetView大小
    FrameLayout container = new FrameLayout(mContext);
    ViewGroup.LayoutParams containerLayoutParams = targetView.getLayoutParams();
    container.setLayoutParams(containerLayoutParams);

    // 原targetView大小与容器一样大
    ViewGroup.LayoutParams targetLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT,
        LayoutParams.MATCH_PARENT);
    targetView.setLayoutParams(targetLayoutParams);
    container.addView(targetView);
    parent.addView(container, index);

    // 确定红点位置
    FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
        LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    layoutParams.setMargins(marginLeft, marginTop, marginRight, marginBottom);
    setLayoutParams(layoutParams);
    bringToFront();
    container.addView(this);
  }


  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    mTitlePaint.setTextSize(mTitleTextSize);
    mBackgroundHeight = mTitleTextSize + mVerticalTotalPadding ;
    mDesiredWith = (int) (mTitlePaint.measureText(mTitleText));
    // 宽度过小时默认宽高相同
    if (mDesiredWith + mHorizontalTotalPadding <= mBackgroundHeight) {
      mBackgroundWidth = mBackgroundHeight;
    } else {
      mBackgroundWidth = mDesiredWith + mHorizontalTotalPadding;
    }
    mWidth = mBackgroundWidth + mStockWidth;
    mHeight = mBackgroundHeight + mStockWidth;

    setMeasuredDimension(mWidth, mHeight);
  }

  @Override
  protected void onDraw(Canvas canvas) {
    // 画边框
    mColorPaint.setColor(mStockColor);
    recStock.set(0, 0, mWidth, mHeight);
    canvas.drawRoundRect(recStock, mCornerSize, mCornerSize, mColorPaint);

    // 画背景
    mColorPaint.setColor(mBackgroundColor);
    rec.set(mStockWidth, mStockWidth, mWidth - mStockWidth, mHeight - mStockWidth);
    canvas.drawRoundRect(rec, mCornerSize, mCornerSize, mColorPaint);

    // 画文字
    mTitlePaint.setColor(mTitleTextColor);
    Paint.FontMetricsInt fontMetrics = mTitlePaint.getFontMetricsInt();
    int baseline =
        ((mHeight - (fontMetrics.bottom - fontMetrics.top)) >> 1) - fontMetrics.top;
    canvas.drawText(mTitleText, (mWidth - mDesiredWith) >> 1, baseline, mTitlePaint);
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值