我想创建一个自定义进度条:
我使用自定义drawable:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@android:id/background">
<shape>
<corners android:radius="10dip" />
<gradient
android:endColor="#3d3d3d"
android:startColor="#3d3d3d" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="10dip" />
<gradient
android:angle="0"
android:endColor="#33bc90"
android:startColor="#4686ef" />
</shape>
</clip>
</item>
</layer-list>
现在我得到下一个结果:
我看到了一个最重要的问题:
end_color
progress = 100
我如何根据我的要求解决这个问题?
答案 0 :(得分:0)
经过调查后,我决定编写自己的实施方案。
代码:
/**
* Copyright 2015-present Sergey Shustikov.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.pandarium.android;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewTreeObserver;
/**
* @author Sergey Shustikov (pandarium.shustkov@gmail.com).
* <p/>
* EdgedProgressBar is a view, like a progress bar, but with the addition of features such as:
* <p/>
* - added the possibility to round off the corners at the progress indicator
* - added the possibility to create gradient from code or XML.
* <p/>
* Created in YouShido company at 2015.
*/
public class EdgedProgressBar extends View
{
/**
* Default values
*/
public static final int DEFAULT_START_COLOR = Color.WHITE;
public static final int DEFAULT_END_COLOR = Color.WHITE;
public static final boolean DEFAULT_EDGE_CORNERS = false;
public static final int DEFAULT_MAX_PROGRESS = 100;
public static final int DEFAULT_CURRENT_PROGRESS = 10;
public static final int DEFAULT_EDGE_VALUE = 10;
public static final int DEFAULT_BACKGROUND_COLOR = Color.BLACK;
/**
* TypedArray for obtaining attributes
*/
private TypedArray attributes;
/**
* The start color of progress gradient.
*
* @see #setStartColor(int)
* @see #getStartColor()
*/
private int startColor = DEFAULT_START_COLOR;
/**
* The end color of progress gradient.
*
* @see #setEndColor(int)
* @see #getEndColor()
*/
private int endColor = DEFAULT_END_COLOR;
/**
* The end color of progress gradient.
*
* @see #setRoundValue(int)
* @see #getRoundValue()
*/
private int roundValue = DEFAULT_EDGE_VALUE;
/**
* The flag indicates enabled edges or not.
*
* @see #setRoundEdgesEnabled(boolean)
* @see #isRoundEdgesEnabled()
*/
private boolean roundEdgesEnabled = DEFAULT_EDGE_CORNERS;
/**
* The max progress. Similar to maximum progress in ProgressBar
*
* @see #setMax(int)
* @see #getMax()
*/
private int maxProgress = DEFAULT_MAX_PROGRESS;
/**
* The current progress. Similar to current progress in ProgressBar
*
* @see #setProgress(int)
* @see #getProgress()
*/
private int currentProgress = DEFAULT_CURRENT_PROGRESS;
/**
* Background color of progressBar.
*
* @see #setBackgroundColor(int)
* @see #getBackgroundColor()
*/
private int backgroundColor = DEFAULT_BACKGROUND_COLOR;
/**
* Internal values
*/
private int finalHeight;
private int finalWidth;
private Paint paint = new Paint();
private LinearGradient gradient;
private int lastGradientWidth, lastGradientHeight;
private int lastL, lastT, lastR, lastB;
private RectF drawingRect;
public EdgedProgressBar(Context context)
{
super(context);
init();
}
public EdgedProgressBar(Context context, AttributeSet attrs)
{
super(context, attrs);
readAttributes(context, attrs);
init();
}
public EdgedProgressBar(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
readAttributes(context, attrs);
init();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public EdgedProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
{
super(context, attrs, defStyleAttr, defStyleRes);
readAttributes(context, attrs);
init();
}
private void init()
{
ViewTreeObserver vto = getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
{
public boolean onPreDraw()
{
getViewTreeObserver().removeOnPreDrawListener(this);
finalHeight = getMeasuredHeight();
finalWidth = getMeasuredWidth();
return true;
}
});
}
private void readAttributes(Context context, AttributeSet attrs)
{
attributes = context.obtainStyledAttributes(attrs, R.styleable.EdgedProgressBar);
try {
startColor =
attributes.getColor(R.styleable.EdgedProgressBar_startColor, DEFAULT_START_COLOR);
endColor =
attributes.getColor(R.styleable.EdgedProgressBar_endColor, DEFAULT_END_COLOR);
roundEdgesEnabled =
attributes.getBoolean(R.styleable.EdgedProgressBar_roundEdgesEnabled, DEFAULT_EDGE_CORNERS);
maxProgress =
attributes.getInteger(R.styleable.EdgedProgressBar_maxProgress, DEFAULT_MAX_PROGRESS);
currentProgress =
attributes.getInteger(R.styleable.EdgedProgressBar_progress, DEFAULT_CURRENT_PROGRESS);
roundValue =
attributes.getInteger(R.styleable.EdgedProgressBar_roundValue, DEFAULT_EDGE_VALUE);
backgroundColor =
attributes.getColor(R.styleable.EdgedProgressBar_backgroundColor, DEFAULT_BACKGROUND_COLOR);
} finally {
attributes.recycle();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
finalHeight = getMeasuredHeight();
finalWidth = getMeasuredWidth();
}
@Override
protected synchronized void onDraw(Canvas canvas)
{
int width = finalWidth;
int height = finalHeight;
int progressDrawableWidth = (currentProgress * width) / maxProgress;
paint.setAntiAlias(true);
int round = roundEdgesEnabled ? roundValue : 0;
paint.setColor(backgroundColor);
int paddingTop = getPaddingTop();
int paddingLeft = getPaddingLeft();
int paddingRight = getPaddingRight();
int paddingBottom = getPaddingBottom();
checkAndRecreate(paddingLeft, paddingTop, paddingRight, paddingBottom, progressDrawableWidth, height);
//draw background
canvas.drawRoundRect(drawingRect, round, round, paint);
paint.setShader(gradient);
//draw progress
canvas.drawRoundRect(drawingRect, round, round, paint);
}
private void checkAndRecreate(int paddingLeft, int paddingTop, int paddingRight, int paddingBottom, int gradientWidth, int gradientHeight)
{
if (gradientWidth != lastGradientWidth || gradientHeight != lastGradientHeight) {
gradient =
new LinearGradient(0, 0, gradientWidth, gradientHeight, startColor, endColor, Shader.TileMode.CLAMP);
lastGradientWidth = gradientWidth;
lastGradientHeight = gradientHeight;
}
if (lastL != paddingLeft || lastT != paddingTop || lastR != paddingRight || lastB != paddingBottom) {
drawingRect =
new RectF(paddingLeft, paddingTop, gradientWidth - paddingRight, gradientHeight - paddingBottom);
lastL = paddingLeft;
lastT = paddingTop;
lastR = paddingRight;
lastB = paddingBottom;
}
}
/**
* @return current progress.
*/
public int getProgress()
{
return currentProgress;
}
/**
* Set current progress.
*/
public void setProgress(int progress)
{
currentProgress = progress;
}
/**
* @return maximum progress.
*/
public int getMax()
{
return maxProgress;
}
/**
* Set maximum progress.
*/
public void setMax(int progress)
{
maxProgress = progress;
}
/**
* @return round value of edges.
*/
public int getRoundValue()
{
return roundValue;
}
/**
* Set round value of progress bar.
*/
public void setRoundValue(int roundValue)
{
this.roundValue = roundValue;
}
/**
* @return edged corners or not.
*/
public boolean isRoundEdgesEnabled()
{
return roundEdgesEnabled;
}
/**
* True - edges in progressBar enabled.
* False - edges disabled.
*/
public void setRoundEdgesEnabled(boolean enabled)
{
roundEdgesEnabled = enabled;
}
/**
* @return start color of gradient in progressBar.
*/
public int getStartColor()
{
return startColor;
}
/**
* Set start color of gradient in progressBar.
*/
public void setStartColor(int color)
{
startColor = color;
}
/**
* @return end color of gradient in progressBar.
*/
public int getEndColor()
{
return endColor;
}
/**
* Set end color of gradient in progressBar.
*/
public void setEndColor(int color)
{
endColor = color;
}
/**
* @return background color of progressBar.
*/
public int getBackgroundColor()
{
return backgroundColor;
}
/**
* Set background color of progressBar.
*/
public void setBackgroundColor(int color)
{
backgroundColor = color;
}
}
attr.xml
<declare-styleable name="EdgedProgressBar">
<attr name="backgroundColor" format="color"/>
<attr name="startColor" format="color"/>
<attr name="endColor" format="color"/>
<attr name="roundEdgesEnabled" format="boolean"/>
<attr name="maxProgress" format="integer"/>
<attr name="progress" format="integer"/>
<attr name="roundValue" format="integer"/>
</declare-styleable>
布局:
<com.pandarium.android.EdgedProgressBar
android:layout_width="wrap_content"
android:layout_height="24dp"
android:id="@+id/view"
edged:backgroundColor="#3d3d3d"
edged:startColor="#4686ef"
edged:endColor="#33bc90"
edged:roundEdgesEnabled="true"
edged:roundValue="30"
edged:maxProgress="100"
edged:progress="50"
android:padding="2dp"/>
结果
50%:
75%:
注意:复制粘贴此代码时,需要将R.java文件导入到类中。
不要忘记添加
xmlns:edged="http://schemas.android.com/apk/res-auto"
进入layout.xml文件。