您好我已经创建了自定义视图"数字栏"这工作正常。我只想在每个指标上添加标签。我尝试了但是当我绘制文本时它是不可见的,因为视图没有达到高度。请查看下面的图片,谢谢。
查看onDraw源代码
protected void onDraw(Canvas canvas) {
int indicatorWidthHeight = Utils.dpToPx(getContext(), indicatorSize);
indicatorRadius = indicatorWidthHeight / 2;
int cx = indicatorWidthHeight / 2;
int cy = indicatorWidthHeight / 2;
int totalIndicators = 5;
int totalLines = totalIndicators - 1;
int lineWidth = (getMeasuredWidth() - (indicatorWidthHeight * totalIndicators)) / totalLines;
linePaint.setStrokeWidth(Utils.dpToPx(getContext(), lineHeight));
for (int i = 0; i < circles.length; i++) {
if (selected >= i) {
indicatorPaint.setColor(selectedBackgroundColor);
textPaint.setColor(selectedTextColor);
} else {
indicatorPaint.setColor(backgroundColor);
textPaint.setColor(textColor);
}
if (selected >= i + 1) {
linePaint.setColor(selectedBackgroundColor);
} else {
linePaint.setColor(backgroundColor);
}
int nCx = cx + (lineWidth + indicatorRadius * 2) * i;
circles[i].setRadius(indicatorRadius);
circles[i].setX(nCx);
circles[i].setY(cy);
canvas.drawCircle(nCx, cy, indicatorRadius, indicatorPaint);
String text = "" + (i+1);
textPaint.getTextBounds(text, 0, text.length(), rect);
canvas.drawText(text, nCx, cy+rect.height()/2, textPaint);
// Draw lines one less than circles
if (i != circles.length - 1) {
int startX = nCx + indicatorRadius;
int stopX = nCx + indicatorRadius + lineWidth;
lines[i].setStartX(startX);
lines[i].setStartY(cy);
lines[i].setStopX(stopX);
lines[i].setStopY(cy);
canvas.drawLine(startX, cy, stopX, cy, linePaint);
}
}
}
查看完整源代码
public class NumberBar extends View {
public static final int DEFAULT_TEXT_SIZE = 16;
public static final int DEF_INDICATOR_SIZE = 20;
Rect rect = new Rect();
Circle[] circles = new Circle[5];
Line[] lines = new Line[4];
private int backgroundColor, textColor, selectedBackgroundColor, selectedTextColor, indicatorSize, lineHeight, selected;
private Paint indicatorPaint;
private Paint textPaint;
private Paint linePaint;
private int indicatorRadius;
private boolean enabled = true;
public NumberBar(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NumberBar, 0, 0);
try {
backgroundColor = typedArray.getInteger(R.styleable.NumberBar_backgroundColor, Color.parseColor("#eeeeee"));
selectedBackgroundColor = typedArray.getInteger(R.styleable.NumberBar_selectedBackgroundColor, Color.parseColor("#0171fe"));
textColor = typedArray.getInteger(R.styleable.NumberBar_textColor, Color.parseColor("#c8c8c8"));
selectedTextColor = typedArray.getInteger(R.styleable.NumberBar_selectedTextColor, Color.parseColor("#ffffff"));
indicatorSize = typedArray.getInteger(R.styleable.NumberBar_indicatorSize, DEF_INDICATOR_SIZE);
lineHeight = typedArray.getInteger(R.styleable.NumberBar_lineHeight, 3);
selected = typedArray.getInteger(R.styleable.NumberBar_selected, 0);
enabled = typedArray.getBoolean(R.styleable.NumberBar_enabled, true);
} finally {
typedArray.recycle();
}
for (int i = 0; i < circles.length; i++) {
circles[i] = new Circle();
}
for (int i = 0; i < lines.length; i++) {
lines[i] = new Line();
}
indicatorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
indicatorPaint.setStyle(Paint.Style.FILL);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setTextSize(Utils.spToPx(getContext(), DEFAULT_TEXT_SIZE));
linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
linePaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
int indicatorWidthHeight = Utils.dpToPx(getContext(), indicatorSize);
indicatorRadius = indicatorWidthHeight / 2;
int cx = indicatorWidthHeight / 2;
int cy = indicatorWidthHeight / 2;
int totalIndicators = 5;
int totalLines = totalIndicators - 1;
int lineWidth = (getMeasuredWidth() - (indicatorWidthHeight * totalIndicators)) / totalLines;
linePaint.setStrokeWidth(Utils.dpToPx(getContext(), lineHeight));
for (int i = 0; i < circles.length; i++) {
if (selected >= i) {
indicatorPaint.setColor(selectedBackgroundColor);
textPaint.setColor(selectedTextColor);
} else {
indicatorPaint.setColor(backgroundColor);
textPaint.setColor(textColor);
}
if (selected >= i + 1) {
linePaint.setColor(selectedBackgroundColor);
} else {
linePaint.setColor(backgroundColor);
}
int nCx = cx + (lineWidth + indicatorRadius * 2) * i;
circles[i].setRadius(indicatorRadius);
circles[i].setX(nCx);
circles[i].setY(cy);
canvas.drawCircle(nCx, cy, indicatorRadius, indicatorPaint);
String text = "" + (i+1);
textPaint.getTextBounds(text, 0, text.length(), rect);
canvas.drawText(text, nCx, cy+rect.height()/2, textPaint);
// Draw lines one less than circles
if (i != circles.length - 1) {
int startX = nCx + indicatorRadius;
int stopX = nCx + indicatorRadius + lineWidth;
lines[i].setStartX(startX);
lines[i].setStartY(cy);
lines[i].setStopX(stopX);
lines[i].setStopY(cy);
canvas.drawLine(startX, cy, stopX, cy, linePaint);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!enabled) {
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
handleDownTouch(event.getX(), event.getY());
break;
}
return true;
}
private void handleDownTouch(float eventX, float eventY) {
for (int i = 0; i < circles.length; i++) {
if (isCircleClicked(eventX, eventY, circles[i])) { // Toast.makeText(NumberBar.this.getContext(), "Circle Clicked: " + i, Toast.LENGTH_SHORT).show();
this.selected = i;
invalidate();
return;
}
}
for (int i = 0; i < lines.length; i++) {
if (inLine(lines[i].getStartPoint(), lines[i].getStopPoint(), new Point((int)eventX, (int)eventY))) {
this.selected = i+1;
invalidate();
return; // Toast.makeText(NumberBar.this.getContext(), "Line: " + i, Toast.LENGTH_SHORT).show();
}
}
}
// is BC inline with AC or visa-versa
public boolean inLine(Point A, Point B, Point C) {
int offset = 5;
return C.x >= A.x && C.x <= B.x && (C.y <= (B.y-lineHeight+ offset) || C.y <= (B.y-lineHeight- offset));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Don't measure width its most or which user will give
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int height;
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(indicatorSize, heightSize);
} else {
//Be whatever you want
height = indicatorSize;
}
//MUST CALL THIS
setMeasuredDimension(widthSize, height);
setMeasuredDimension(getMeasuredWidth(), Utils.dpToPx(getContext(), indicatorSize));
}
private boolean isCircleClicked(float ex, float ey, Circle circle) {
return Math.sqrt((circle.getX() - ex) * (circle.getX() - ex) + (circle.getY() - ey) * (circle.getY() - ey)) < circle.getRadius()+4;
}
public int getBackgroundColor() {
return backgroundColor;
}
@Override
public void setBackgroundColor(int backgroundColor) {
this.backgroundColor = backgroundColor;
invalidate();
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
invalidate();
}
public int getSelectedBackgroundColor() {
return selectedBackgroundColor;
}
public void setSelectedBackgroundColor(int selectedBackgroundColor) {
this.selectedBackgroundColor = selectedBackgroundColor;
invalidate();
}
public int getSelectedTextColor() {
return selectedTextColor;
}
public void setSelectedTextColor(int selectedTextColor) {
this.selectedTextColor = selectedTextColor;
invalidate();
}
public int getIndicatorSize() {
return indicatorSize;
}
public void setIndicatorSize(int indicatorSize) {
this.indicatorSize = indicatorSize;
invalidate();
requestLayout();
}
public int getLineHeight() {
return lineHeight;
}
public void setLineHeight(int lineHeight) {
this.lineHeight = lineHeight;
invalidate();
requestLayout();
}
public int getSelected() {
return selected;
}
public void setSelected(int selected) {
this.selected = selected;
invalidate();
}
private class Circle {
int x, y;
int radius;
public Circle() {
}
public Circle(int x, int y, int radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
}
class Line {
Point startPoint = new Point();
Point stopPoint = new Point();
public int getStartX() {
return startPoint.x;
}
public void setStartX(int startX) {
this.startPoint.x = startX;
}
public int getStartY() {
return startPoint.y;
}
public void setStartY(int startY) {
this.startPoint.y = startY;
}
public int getStopX() {
return stopPoint.x;
}
public void setStopX(int stopX) {
this.stopPoint.x = stopX;
}
public int getStopY() {
return stopPoint.y;
}
public void setStopY(int stopY) {
this.stopPoint.y = stopY;
}
public Point getStartPoint() {
return startPoint;
}
public Point getStopPoint() {
return stopPoint;
}
}
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
} }