Android: Полукруг Прогресс-Бар
Я хочу полукруглый индикатор выполнения в фоновом режиме изображения. как раз как под изображением.
Я пытался рисовать с помощью canvas, но не могу добиться успеха. я также устал от некоторой пользовательской библиотеки индикатора выполнения, но результат тот же.
любые предложения.
ищу одно время и использовать в любой размер экрана.
6 ответов
это может быть реализовано путем обрезки холста, содержащего изображение под углом (на чертеже дугой).
вы можете использовать изображение что-то вроде этого
и закрепите это изображение, нарисовав дугу.
вот как вы можете сделать это.
//Convert the progress in range of 0 to 100 to angle in range of 0 180. Easy math.
float angle = (progress * 180) / 100;
mClippingPath.reset();
//Define a rectangle containing the image
RectF oval = new RectF(mPivotX, mPivotY, mPivotX + mBitmap.getWidth(), mPivotY + mBitmap.getHeight());
//Move the current position to center of rect
mClippingPath.moveTo(oval.centerX(), oval.centerY());
//Draw an arc from center to given angle
mClippingPath.addArc(oval, 180, angle);
//Draw a line from end of arc to center
mClippingPath.lineTo(oval.centerX(), oval.centerY());
и как только вы получите путь, вы можете использовать clipPath
функция для того чтобы закрепить холст в этом пути.
canvas.clipPath(mClippingPath);
здесь код
SemiCircleProgressBarView.java
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
public class SemiCircleProgressBarView extends View {
private Path mClippingPath;
private Context mContext;
private Bitmap mBitmap;
private float mPivotX;
private float mPivotY;
public SemiCircleProgressBarView(Context context) {
super(context);
mContext = context;
initilizeImage();
}
public SemiCircleProgressBarView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
initilizeImage();
}
private void initilizeImage() {
mClippingPath = new Path();
//Top left coordinates of image. Give appropriate values depending on the position you wnat image to be placed
mPivotX = getScreenGridUnit();
mPivotY = 0;
//Adjust the image size to support different screen sizes
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.circle);
int imageWidth = (int) (getScreenGridUnit() * 30);
int imageHeight = (int) (getScreenGridUnit() * 30);
mBitmap = Bitmap.createScaledBitmap(bitmap, imageWidth, imageHeight, false);
}
public void setClipping(float progress) {
//Convert the progress in range of 0 to 100 to angle in range of 0 180. Easy math.
float angle = (progress * 180) / 100;
mClippingPath.reset();
//Define a rectangle containing the image
RectF oval = new RectF(mPivotX, mPivotY, mPivotX + mBitmap.getWidth(), mPivotY + mBitmap.getHeight());
//Move the current position to center of rect
mClippingPath.moveTo(oval.centerX(), oval.centerY());
//Draw an arc from center to given angle
mClippingPath.addArc(oval, 180, angle);
//Draw a line from end of arc to center
mClippingPath.lineTo(oval.centerX(), oval.centerY());
//Redraw the canvas
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//Clip the canvas
canvas.clipPath(mClippingPath);
canvas.drawBitmap(mBitmap, mPivotX, mPivotY, null);
}
private float getScreenGridUnit() {
DisplayMetrics metrics = new DisplayMetrics();
((Activity)mContext).getWindowManager().getDefaultDisplay().getMetrics(metrics);
return metrics.widthPixels / 32;
}
}
и использовать его в любой деятельности очень легко.
activity_main.в XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<com.example.progressbardemo.SemiCircleProgressBarView
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
отметим, что clipPath
функция не работает, если hardware acceleration
включен. Аппаратное ускорение можно отключить только для этого вида.
//Turn off hardware accleration
semiCircleProgressBarView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
MainActivity.java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SemiCircleProgressBarView semiCircleProgressBarView = (SemiCircleProgressBarView) findViewById(R.id.progress);
semiCircleProgressBarView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
semiCircleProgressBarView.setClipping(70);
}
}
как и при изменении прогресса вы можете установить progressbar, вызвав функции
semiCircleProgressBarView.setClipping(progress);
Ex:semiCircleProgressBarView.setClipping(50); //50% progress
semiCircleProgressBarView.setClipping(70); //70% progress
вы можете использовать свой собственный образ, чтобы соответствовать требованиям. Надеюсь, это поможет!!
Edit: чтобы переместить полукруг в нижней части экрана, измените mPivotY
значение. Что-то вроде этого!--15-->
//In `SemiCircleProgressBarView.java`
//We don't get the canvas width and height initially, set `mPivoyY` inside `onWindowFocusChanged` since `getHeight` returns proper results by that time
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
mPivotX = getScreenGridUnit();
mPivotY = getHeight() - (mBitmap.getHeight() / 2);
}
вы можете попробовать Библиотека SeekArc. Я знаю, что это другой вид seekbar, но с некоторыми незначительными настройками вы можете использовать его для своего приложения в качестве progressbar. Я сделал то же самое. Вам просто нужно изменить некоторые свойства, такие как seekarc:touchInside="false"
.
Это довольно просто.
теперь пользовательская реализация в моем приложении выглядит примерно так:
img src:CleanMaster в Google Play
вы также можете использовать native ProgressBar
для достижения полукруга.
Определить ProgressBar
такой:
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:max="200"
android:progress="0"
android:progressDrawable="@drawable/circular" />
создать drawable:
circular
(уровень API
<shape
android:innerRadiusRatio="2.3"
android:shape="ring"
android:thickness="5sp" >
<solid android:color="@color/someColor" />
</shape>
circular
(уровень API >= 21):
<shape
android:useLevel="true"
android:innerRadiusRatio="2.3"
android:shape="ring"
android:thickness="5sp" >
<solid android:color="@color/someColor" />
</shape>
useLevel
и false
по умолчанию на уровне API 21.
теперь, так как мы установили max = 200
, для достижения полукруга диапазон прогресса должен быть 0
to 100
. Вы можете играть с этими значениями, чтобы достичь желаемой формы.
таким образом, используйте его так:
ProgressBar progressBar = (Progressbar) view.findViewById(R.id.progressBar);
progressBar.setProgress(value); // 0 <= value <= 100
Это вид, высота которого равна половине его ширины. Используйте сеттеры, чтобы настроить поведение по желанию. По умолчанию прогресс равен 0, а ширина дуги равна 20. Вызов setProgress () аннулирует представление с заданным прогрессом. Добавление фона drawable возможно, и индикатор выполнения будет рисовать сверху.
public class SemicircularProgressBar extends View {
private int mProgress;
private RectF mOval;
private RectF mOvalInner;
private Paint mPaintProgress;
private Paint mPaintClip;
private float ovalsDiff;
private Path clipPath;
public SemicircularProgressBar(Context context) {
super(context);
init();
}
public SemicircularProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SemicircularProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mProgress = 0;
ovalsDiff = 20;
mOval = new RectF();
mOvalInner = new RectF();
clipPath = new Path();
mPaintProgress = new Paint();
mPaintProgress.setColor(Color.GREEN);
mPaintProgress.setAntiAlias(true);
mPaintClip = new Paint();
mPaintClip.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mPaintClip.setAlpha(0);
mPaintClip.setAntiAlias(true);
}
// call this from the code to change the progress displayed
public void setProgress(int progress) {
this.mProgress = progress;
invalidate();
}
// sets the width of the progress arc
public void setProgressBarWidth(float width) {
this.ovalsDiff = width;
invalidate();
}
// sets the color of the bar (#FF00FF00 - Green by default)
public void setProgressBarColor(int color){
this.mPaintProgress.setColor(color);
}
@Override
public void onDraw(Canvas c) {
super.onDraw(c);
mOval.set(0, 0, this.getWidth(), this.getHeight()*2);
mOvalInner.set(0+ovalsDiff, 0+ovalsDiff, this.getWidth()-ovalsDiff, this.getHeight()*2);
clipPath.addArc(mOvalInner, 180, 180);
c.clipPath(clipPath, Op.DIFFERENCE);
c.drawArc(mOval, 180, 180f * ((float) mProgress / 100), true, mPaintProgress);
}
// Setting the view to be always a rectangle with height equal to half of its width
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth/2, parentHeight);
ViewGroup.LayoutParams params = this.getLayoutParams();
params.width = parentWidth;
params.height = parentWidth/2;
this.setLayoutParams(params);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
вы можете использовать эту библиотеку :
compile 'com.github.lzyzsd:circleprogress:1.1.1'
например :
<com.github.lzyzsd.circleprogress.DonutProgress
android:layout_marginLeft="50dp"
android:id="@+id/donut_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:donut_progress="30"/>
<com.github.lzyzsd.circleprogress.ArcProgress
android:id="@+id/arc_progress"
android:background="#214193"
android:layout_marginLeft="50dp"
android:layout_width="100dp"
android:layout_height="100dp"
custom:arc_progress="55"
custom:arc_bottom_text="MEMORY"/>
для получения дополнительной информации см. Следующий веб-сайт:
вы можете использовать этот библиотека github-circularseekbar. Чтобы достичь полукруга, вам нужно будет манипулировать следующими атрибутами: "app:start_angle" & "app:end_angle"
Дополнительные Параметры:
- библиотека Голо Seekbar
- учебник, показывающий полукруглый seekbar ссылка на учебник