android 可移动的标签

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhihui_520/article/details/79915888

虽说可移动的标签没什么难度可言, 但对于些自定义view相对薄弱的来讲, 还是有点意义的, 比如说我.

先看下我这边的效果图吧.

lableView

整个绘制过程相对比较简单.

首先onMessage中测量要具体显示的位置, 或者说能显示的大小是多少

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width, height;
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);

    if (widthMode == MeasureSpec.EXACTLY) {
        width = Math.max(widthSize, mixWidth); //widthSize > mixWidth ? widthSize : mixWidth;
    } else {
        width = getPaddingLeft() + mixWidth + getPaddingRight();
    }

    if (heightMode == MeasureSpec.EXACTLY) {
        height = Math.max(heightSize, mixHeight);//heightSize > mixHeight ? heightSize : mixHeight;
    } else {
        height = getPaddingTop() + mixHeight + getPaddingBottom();
    }
    mCircleY = height / 2;
    setMeasuredDimension(width, height);


}

绘制细线

/**
 * 绘制细线
 *
 * @param canvas
 */
private void drawLine(Canvas canvas) {
    if (mStrs.length == 0) return;
    mLinePaint.setStyle(Paint.Style.STROKE);
    reSetPath();

    if (mCircleX > getMeasuredHeight() / 2) { // 原点在右侧, 文字需要在左
        asLeft = -1;
        lineStartX = mCircleX - mRadius * 0.6f;
    } else {
        asLeft = 1;
        lineStartX = mCircleX + mRadius * 0.6f;
    }

    if (mStrs.length == 1) {
        mPath[0].rLineTo((mTextPaint.measureText(mStrs[0]) + disGap / 2) * asLeft + disGap, 0);
        canvas.drawPath(mPath[0], mLinePaint);
    } else if (mStrs.length == 2) {
        mPath[0].lineTo(lineStartX + disGap * asLeft, mCircleY - disGap);
        mPath[0].rLineTo((mTextPaint.measureText(mStrs[0]) + disGap / 2) * asLeft, 0);
        canvas.drawPath(mPath[0], mLinePaint);

        mPath[1].lineTo(lineStartX + disGap * asLeft, mCircleY + disGap);
        mPath[1].rLineTo((mTextPaint.measureText(mStrs[1]) + disGap / 2) * asLeft, 0);
        canvas.drawPath(mPath[1], mLinePaint);
    } else {
        mPath[0].lineTo(lineStartX + disGap * asLeft, mCircleY - disGap);
        mPath[0].rLineTo((mTextPaint.measureText(mStrs[0]) + disGap / 2) * asLeft, 0);
        canvas.drawPath(mPath[0], mLinePaint);

        mPath[1].rLineTo((mTextPaint.measureText(mStrs[1]) + disGap * 1.5f) * asLeft, 0);
        canvas.drawPath(mPath[1], mLinePaint);

        mPath[2].lineTo(lineStartX + disGap * asLeft, mCircleY + disGap);
        mPath[2].rLineTo((mTextPaint.measureText(mStrs[2]) + disGap / 2) * asLeft, 0);
        canvas.drawPath(mPath[2], mLinePaint);
    }

}

设置文字

这里只提供在java代码中设置文字, 个人觉得这样比在xml中更灵活些. 所以提供了可直接设置文字的可变数组(仅支持1-3个文字标签)

/**
 * 设置文字
 *
 * @param str 要显示的文字
 */
public void setText(String... str) {
    if (str.length > 3) {
        mStrs[0] = str[0];
        mStrs[1] = str[1];
        mStrs[2] = str[2];
    } else {
        this.mStrs = str;
    }
    invalidate();
}

绘制文字

刚开始是想直接drawTextonPath, 原点在左, 文字在右,倒是好绘制. 但是反过来, 原点在右,文字在左就不好搞了,最终换成直接绘制文字.

/**
 * 绘制文字
 *
 * @param canvas
 */
private void drawText(Canvas canvas) {
    if (mStrs.length == 0) return;

    if (asLeft > 0) {   // 原点在左侧, 文字需要在右
        mTextPaint.setTextAlign(Paint.Align.LEFT);
    } else {
        mTextPaint.setTextAlign(Paint.Align.RIGHT);
    }

    if (mStrs.length == 1) {
        canvas.drawText(mStrs[0], lineStartX + disGap * asLeft, mCircleY - mLineDisText, mTextPaint);
    } else if (mStrs.length == 2) {
        canvas.drawText(mStrs[0], lineStartX + disGap * asLeft, mCircleY - disGap - mLineDisText, mTextPaint);
        canvas.drawText(mStrs[1], lineStartX + disGap * asLeft, mCircleY + disGap - mLineDisText, mTextPaint);
    } else {
        canvas.drawText(mStrs[0], lineStartX + disGap * asLeft, mCircleY - disGap - mLineDisText, mTextPaint);
        canvas.drawText(mStrs[1], lineStartX + disGap * asLeft, mCircleY - mLineDisText, mTextPaint);
        canvas.drawText(mStrs[2], lineStartX + disGap * asLeft, mCircleY + disGap - mLineDisText, mTextPaint);
    }
}

到此一个普通的带标签的view已经绘制好了, 再加些动画就更好看些了

/**
 * 初始化动画
 */
private void initAnim() {
    mAnimator = ObjectAnimator.ofFloat(this, "progress", 0.6f, 1);
    mAnimator.setDuration(1000);
    mAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
    // 无限循环
    mAnimator.setRepeatCount(ValueAnimator.INFINITE);
    // 重复模式, RESTART: 重新开始 REVERSE:恢复初始状态再开始
    mAnimator.setRepeatMode(ValueAnimator.REVERSE);
}

整个过程就是这样,具体详细代码, 可前往Github查看全部代码

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页