天天看点

android 可移动的标签

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

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

android 可移动的标签

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

首先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 / ;
    setMeasuredDimension(width, height);


}
           

绘制细线

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

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

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

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

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

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

}
           

设置文字

这里只提供在java代码中设置文字, 个人觉得这样比在xml中更灵活些. 所以提供了可直接设置文字的可变数组(仅支持1-3个文字标签)
/**
 * 设置文字
 *
 * @param str 要显示的文字
 */
public void setText(String... str) {
    if (str.length > ) {
        mStrs[] = str[];
        mStrs[] = str[];
        mStrs[] = str[];
    } else {
        this.mStrs = str;
    }
    invalidate();
}
           

绘制文字

刚开始是想直接drawTextonPath, 原点在左, 文字在右,倒是好绘制. 但是反过来, 原点在右,文字在左就不好搞了,最终换成直接绘制文字.
/**
 * 绘制文字
 *
 * @param canvas
 */
private void drawText(Canvas canvas) {
    if (mStrs.length == ) return;

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

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

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

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

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

继续阅读