如何在可绘制图层列表的一侧使用图像
How can I use an image on the side of a drawable layer list
我的 UI 设计师想出了这样的进度条设计:
数字应该是进度和最大值。
圆形图像将会改变。在某些设计上,1500 旁边还有一张图片。
每当我尝试在 layer-list
上执行此操作时,我总是以可绘制对象中间的图像结束。理想情况下,我更喜欢使用矢量图形,但如果需要我可以使用 png。我什至还没有考虑将数字放在那里。
那么如何实现呢?
谢谢。
在我看来,使用 canvas 对于这种情况似乎更容易。这是我现在可以想出的一个简短示例:
public class Loading extends View {
private final static float VIEW_HEIGHT = 80;
private RectF viewRectangle;
private RectF progressRectangle;
private float cornersRadius;
private Paint progressBarPaint;
private Paint progressTextPaint;
private Paint containerBarPaint;
private Paint containerTextPaint;
private final int progressMaxValue = 1500;
private float containerTextY;
private float containerTextX;
private final float whiteCircleRadius = 14;
private final float progressTextPadding = 16;
private float progress;
public Loading(Context context) {
super(context);
progress = 0.5f;
progressTextPaint = new Paint(LINEAR_TEXT_FLAG|SUBPIXEL_TEXT_FLAG|ANTI_ALIAS_FLAG);
progressTextPaint.setColor(Color.WHITE);
progressTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
progressTextPaint.setTextSize(28);
progressTextPaint.setStrokeWidth(1f);
containerTextPaint = new Paint(progressTextPaint);
containerTextPaint.setColor(Color.BLACK);
progressBarPaint = new Paint(ANTI_ALIAS_FLAG);
progressBarPaint.setColor(Color.BLUE);
progressBarPaint.setStyle(Paint.Style.FILL);
containerBarPaint = new Paint(ANTI_ALIAS_FLAG);
containerBarPaint.setColor(Color.GRAY);
containerBarPaint.setStyle(Paint.Style.FILL);
}
@Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
int horizontalPadding = getPaddingLeft() + getPaddingRight();
int verticalPadding = getPaddingTop() + getPaddingBottom();
float measuredHeight = height - verticalPadding;
float targetHeight = measuredHeight < VIEW_HEIGHT ? measuredHeight : VIEW_HEIGHT;
float containerWidth = width - horizontalPadding;
viewRectangle = new RectF(getPaddingLeft(), getPaddingTop(), containerWidth, targetHeight);
progressRectangle = new RectF(viewRectangle);
cornersRadius = targetHeight / 2;
String maxValueText = String.valueOf(progressMaxValue);
Rect containerTextBounds = new Rect();
containerTextPaint.getTextBounds(maxValueText, 0, maxValueText.length(), containerTextBounds);
containerTextX = viewRectangle.right - containerTextBounds.width() - cornersRadius / 2;
containerTextY = viewRectangle.centerY() - containerTextBounds.exactCenterY();
}
@Override
protected void onDraw(Canvas canvas) {
float progressWidth = viewRectangle.right * progress;
float cornerDiameter = cornersRadius * 2;
progressRectangle.right = progressWidth > cornerDiameter ? progressWidth : cornerDiameter;
canvas.drawRoundRect(viewRectangle, cornersRadius, cornersRadius, containerBarPaint);
canvas.drawRoundRect(progressRectangle, cornersRadius, cornersRadius, progressBarPaint);
canvas.drawCircle(progressRectangle.right - cornersRadius, progressRectangle.centerY(), whiteCircleRadius, progressTextPaint);
canvas.drawText(String.valueOf(progressMaxValue), containerTextX, containerTextY, containerTextPaint);
String progressText = String.valueOf((int) (progressMaxValue * progress));
float progressTextWidth = progressTextPaint.measureText(progressText);
if (progressTextWidth < progressRectangle.right * 2) {
float requiredProgressTextSpace = cornersRadius + whiteCircleRadius + progressTextPadding + progressTextWidth;
canvas.drawText(progressText, progressRectangle.right - requiredProgressTextSpace, containerTextY, progressTextPaint);
}
}
}
它远非完美,也不是很灵活,但这是一个很好的起点。如果您在这里需要一些评论,请随时提出。这是上面代码的渲染:
我的 UI 设计师想出了这样的进度条设计:
数字应该是进度和最大值。
圆形图像将会改变。在某些设计上,1500 旁边还有一张图片。
每当我尝试在 layer-list
上执行此操作时,我总是以可绘制对象中间的图像结束。理想情况下,我更喜欢使用矢量图形,但如果需要我可以使用 png。我什至还没有考虑将数字放在那里。
那么如何实现呢?
谢谢。
在我看来,使用 canvas 对于这种情况似乎更容易。这是我现在可以想出的一个简短示例:
public class Loading extends View {
private final static float VIEW_HEIGHT = 80;
private RectF viewRectangle;
private RectF progressRectangle;
private float cornersRadius;
private Paint progressBarPaint;
private Paint progressTextPaint;
private Paint containerBarPaint;
private Paint containerTextPaint;
private final int progressMaxValue = 1500;
private float containerTextY;
private float containerTextX;
private final float whiteCircleRadius = 14;
private final float progressTextPadding = 16;
private float progress;
public Loading(Context context) {
super(context);
progress = 0.5f;
progressTextPaint = new Paint(LINEAR_TEXT_FLAG|SUBPIXEL_TEXT_FLAG|ANTI_ALIAS_FLAG);
progressTextPaint.setColor(Color.WHITE);
progressTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
progressTextPaint.setTextSize(28);
progressTextPaint.setStrokeWidth(1f);
containerTextPaint = new Paint(progressTextPaint);
containerTextPaint.setColor(Color.BLACK);
progressBarPaint = new Paint(ANTI_ALIAS_FLAG);
progressBarPaint.setColor(Color.BLUE);
progressBarPaint.setStyle(Paint.Style.FILL);
containerBarPaint = new Paint(ANTI_ALIAS_FLAG);
containerBarPaint.setColor(Color.GRAY);
containerBarPaint.setStyle(Paint.Style.FILL);
}
@Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
int horizontalPadding = getPaddingLeft() + getPaddingRight();
int verticalPadding = getPaddingTop() + getPaddingBottom();
float measuredHeight = height - verticalPadding;
float targetHeight = measuredHeight < VIEW_HEIGHT ? measuredHeight : VIEW_HEIGHT;
float containerWidth = width - horizontalPadding;
viewRectangle = new RectF(getPaddingLeft(), getPaddingTop(), containerWidth, targetHeight);
progressRectangle = new RectF(viewRectangle);
cornersRadius = targetHeight / 2;
String maxValueText = String.valueOf(progressMaxValue);
Rect containerTextBounds = new Rect();
containerTextPaint.getTextBounds(maxValueText, 0, maxValueText.length(), containerTextBounds);
containerTextX = viewRectangle.right - containerTextBounds.width() - cornersRadius / 2;
containerTextY = viewRectangle.centerY() - containerTextBounds.exactCenterY();
}
@Override
protected void onDraw(Canvas canvas) {
float progressWidth = viewRectangle.right * progress;
float cornerDiameter = cornersRadius * 2;
progressRectangle.right = progressWidth > cornerDiameter ? progressWidth : cornerDiameter;
canvas.drawRoundRect(viewRectangle, cornersRadius, cornersRadius, containerBarPaint);
canvas.drawRoundRect(progressRectangle, cornersRadius, cornersRadius, progressBarPaint);
canvas.drawCircle(progressRectangle.right - cornersRadius, progressRectangle.centerY(), whiteCircleRadius, progressTextPaint);
canvas.drawText(String.valueOf(progressMaxValue), containerTextX, containerTextY, containerTextPaint);
String progressText = String.valueOf((int) (progressMaxValue * progress));
float progressTextWidth = progressTextPaint.measureText(progressText);
if (progressTextWidth < progressRectangle.right * 2) {
float requiredProgressTextSpace = cornersRadius + whiteCircleRadius + progressTextPadding + progressTextWidth;
canvas.drawText(progressText, progressRectangle.right - requiredProgressTextSpace, containerTextY, progressTextPaint);
}
}
}
它远非完美,也不是很灵活,但这是一个很好的起点。如果您在这里需要一些评论,请随时提出。这是上面代码的渲染: