答案 0 :(得分:2)
经过数天的研究,我能够通过清晰的UI以及所有上述要求和灵活性实现预期目标。可以实现上面的精确UI,也可以实现以下参数: 1.进步颜色 2.进展背景颜色 3.容器颜色(由您设置的容器颜色,您可以设置圆角边缘的颜色以匹配容器颜色) 4.进度条的高度和宽度,以满足您的需求。
以下是实现它的代码和步骤:
予。将此代码放在值文件夹下的 attrs.xml 文件中
<declare-styleable name="SlantingProgressBar">
<attr name="slantingProgress" format="integer"/>
<attr name="borderRadius" format="integer"/>
<attr name="borderColor" format="integer"/>
<attr name="slantingProgressColor" format="string"/>
<attr name="progressBackgroundColor" format="string"/>
<attr name="slantingProgressFullColor" format="string"/>
</declare-styleable>
II。创建一个这样的java类:
public class SlantingProgressbar extends View {
private float height = 0;
private float width = 0;
private int borderRadius = 20;
private float progress = 0;
private int rawProgress = 0;
private static final String OPACITY_30_PERCENT = "#66";
private int roundedBorderColor;
private String backgroundColor = "";
private String progressColor = "";
private String progressFullColor = "#fc3d39";
public SlantingProgressbar(Context context) {
super(context);
}
public SlantingProgressbar(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray array = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.SlantingProgressBar,
0, 0);
try {
setProgress(array.getInt(R.styleable.SlantingProgressBar_slantingProgress, 0));
setBackgroundColor(array.getString(R.styleable.SlantingProgressBar_progressBackgroundColor)); //Default color set in the method
setBorderRadius(array.getInt(R.styleable.SlantingProgressBar_borderRadius, 20));
setRoundedBorderColor(array.getInt(R.styleable.SlantingProgressBar_borderColor, 0));
setProgressColor(array.getString(R.styleable.SlantingProgressBar_slantingProgressColor));
} finally {
array.recycle();
}
}
public void setBorderRadius(int borderRadius) {
this.borderRadius = borderRadius;
}
public int getProgress() {
return rawProgress;
}
public void setProgress(int progress) {
if(progress >=0)
{
this.rawProgress = progress;
this.invalidate();
}
else
Log.e("ChlorophyllProgressBar", "Invalid 'progress' value detected, value should be between 0 and 100");
}
public void setRoundedBorderColor(int roundedBorderColor) {
if ( roundedBorderColor == 0) {
this.roundedBorderColor = getResources().getColor(R.color.white);
Log.e("CUSTOM_TAG", "Color set to White: " + this.roundedBorderColor);
return;
}
this.roundedBorderColor = roundedBorderColor;
Log.e("CUSTOM_TAG", "Color set to custom: " + this.roundedBorderColor);
}
private int getRoundedBorderColor()
{
return roundedBorderColor;
}
public void setSlantingProgressFullColor(String color)
{
if (TextUtils.isEmpty(progressFullColor)) {
this.progressFullColor = "#fc3d39";
return;
}
}
public void setBackgroundColor(String backgroundColor) {
if (TextUtils.isEmpty(backgroundColor)) {
this.backgroundColor = "#bfe8d4";
return;
}
this.backgroundColor = backgroundColor;
}
public void setProgressColor(String progressColor) {
if (TextUtils.isEmpty(progressColor)) {
this.progressColor = "#2bb673"; //Green
return;
}
this.progressColor = progressColor;
}
public float getViewHeight() {
return height;
}
public void setViewHeight(float height) {
this.height = height;
}
public float getViewWidth() {
return width;
}
public void setViewWidth(float width) {
this.width = width;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
height = getHeight();
width = getWidth();
progress = getProcessedProgress();
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor(backgroundColor));
canvas.drawPaint(paint);
paint.setColor(getProcessedProgressColor());
paint.setAntiAlias(true);
Log.d("CUSTOM_TAG", "Height: " + height);
canvas.drawRect(0, 0, progress, height, paint);
Path triangle = new Path();
triangle.setFillType(Path.FillType.EVEN_ODD);
triangle.moveTo(progress, 0);
triangle.lineTo(progress + height, 0);
triangle.lineTo(progress, height);
triangle.close();
canvas.drawPath(triangle, paint);
drawBorders(canvas, getRoundedBorderColor());
}
private void drawBorders(Canvas canvas, int color) {
float height = getHeight();
float trueWidth = getWidth();
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(color);
//paint.setColor(getResources().getColor(R.color.white));
paint.setAntiAlias(true);
Path border = new Path();
border.moveTo(0, 0);
border.lineTo(0, height / 2);
border.quadTo(height / borderRadius, height / borderRadius, height / 2, 0);
border.lineTo(0, 0);
canvas.drawPath(border, paint);
border.reset();
border.moveTo(0, height);
border.lineTo(height / 2, height);
border.quadTo(height / borderRadius, (height - height / borderRadius), 0, height / 2);
border.lineTo(0, height);
canvas.drawPath(border, paint);
border.reset();
border.moveTo(trueWidth, 0);
border.lineTo(trueWidth - (height / 2), 0);
border.quadTo((trueWidth - height / borderRadius), height / borderRadius, trueWidth, height / 2);
border.lineTo(trueWidth, 0);
canvas.drawPath(border, paint);
border.reset();
border.moveTo(trueWidth, height);
border.lineTo(trueWidth - (height / 2), height);
border.quadTo((trueWidth - height / borderRadius), (height - height / borderRadius), trueWidth, height / 2);
border.lineTo(trueWidth, height);
canvas.drawPath(border, paint);
//Adding 1 pixel color
Paint paint1 = new Paint();
paint1.setStyle(Paint.Style.FILL);
int fadedColor = (color & 0x00FFFFFF) | 0x66000000;
Log.d("CUSTOM_TAG", "Faded Color Code: " + fadedColor);
paint1.setColor(fadedColor);
canvas.drawRect(0, 0, 1, height, paint1);
canvas.drawRect(trueWidth-1, 0, trueWidth, height, paint1);
}
private float getProcessedProgress()
{
return (rawProgress == 99) ? ((getWidth() * 98) / 100) : ((getWidth() * rawProgress) / 100);
}
private int getProcessedProgressColor()
{
if(rawProgress > 100)
{
return Color.parseColor(progressFullColor);
}
else
{
return Color.parseColor(progressColor);
}
}
}
III。要在xml文件中使用布局:
<com.whatever.package.SlantingProgressbar
android:id="@+id/progressbar_detail"
android:layout_width="match_parent"
android:layout_height="@dimen/dimension1"
android:layout_alignParentLeft="true"
slanting_progress:borderColor="@color/darkgray"
android:layout_below="@id/alphacon_detail"
android:layout_marginBottom="@dimen/budget_list_item_paddingBottom"
android:progress="50" />
我会在一段时间之后分享这段代码,所以我可能错过了一两件事,我很确定你能解决这个问题,请随时纠正我。
说明: 我们在java中使用'draw'方法来实现此功能。优点是,绘制UI元素可以为我们提供清晰明了的UI,无论您做多大或多小。 可能存在一些硬编码值,因此请务必在实现之前对其进行编辑。
祝你好运,如果这篇文章对你有帮助,不要忘了向上投票。谢谢! :)
答案 1 :(得分:0)
我会在这里发布一个答案,以显示您的代码的一些改进。
draw
期间创建新对象。 draw
一次又一次被多次调用以重绘自定义元素,所有这些对new Paint()
的调用都在创建新对象,需要新的内存分配,并且它会使垃圾收集器变得疯狂并使您的查看资源更加密集,可能会导致滚动元素滞后,例如RecyclerView
。
或者你应该将它们声明为private Paint border
然后private Paint triangle
等等。然后你应该在一个单独的方法中初始化所有油漆的值,并且只有在参数改变时。示例代码:
private boolean initPaint = false;
private void initPaintsIfNecessary(){
if(!initPaint) return;
initPaint = false;
triangle = new Paint();
triangle.set.... etc
border = new Paint();
border.set.... etc
}
然后是所有方法setRoundedBorderColor
,setProgressColor
等。您拨打initPaint = true;
并在draw
的开头呼叫initPaintsIfNecessary();
。这将避免所有额外的垃圾收集器工作,并将允许您的应用程序的UI运行更顺畅。
这也包括Paint
方法中的所有drawBorders
。
format="color" instead of
string`。调用Color.parse(String)
是一个非常慢的调用,它非常容易出错。或者,您应该使用正确的color
元素,如下所示:
<attr name="slantingProgressColor" format="color"/>
这不仅是正确的方法,而是在编辑器上为您提供颜色预览,可以在应用程序样式参数上建立索引,并避免对parse
的低效调用
当然你应该适当调整或方法。例如: setProgressColor(array.getColor(R.styleable.SlantingProgressBar_slantingProgressColor));
getColor
将返回一个可以在paint.setColor(int);
我希望这些提示能够帮助您(以及社区中的其他人)创建更高效的View
元素。快乐的编码!
答案 2 :(得分:0)
我知道这个老问题要回答,但这个答案可能有帮助.. 您可以使用drawArc方法来实现此目的。
RectF oval = new RectF();
oval.set(left, top ,right, bottom);
canvas.drawArc(oval, 270, 360, false, paint);