Android:半圆进度条

Android:半圆进度条,android,progress-bar,android-progressbar,Android,Progress Bar,Android Progressbar,我想在图像的背景半圆进度条。如下图所示 我曾尝试用画布画画,但没有成功。我也厌倦了一些自定义进度条库,但结果是一样的 任何建议 正在寻找一次开发并在每个屏幕大小中使用。您可以使用此功能。要实现半圆,您需要操纵以下属性:“app:start_angle”和“app:end_angle” 更多选项: 显示半圆形seekbar的教程 这可以通过以一定角度剪裁包含图像的画布(通过绘制圆弧)来实现 你可以使用像这样的图像 //In `SemiCircleProgressBarView.java` //

我想在图像的背景半圆进度条。如下图所示

我曾尝试用画布画画,但没有成功。我也厌倦了一些自定义进度条库,但结果是一样的

任何建议


正在寻找一次开发并在每个屏幕大小中使用。

您可以使用此功能。要实现半圆,您需要操纵以下属性:“app:start_angle”和“app:end_angle”

更多选项

  • 显示半圆形seekbar的教程

  • 这可以通过以一定角度剪裁包含图像的画布(通过绘制圆弧)来实现

    你可以使用像这样的图像

    //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);
            }
    

    并通过绘制一个圆弧来剪裁该图像

    这是你可以做到的

    //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);
    
    这是完整的代码

    半圆程序BarView.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>   
    
    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);
        }
    
    }  
    
    当进度发生变化时,您可以通过调用函数设置进度条

    semiCircleProgressBarView.setClipping(progress);
    
    例:
    semicrcleprogressbarview.setClipping(50)//50%的进度

    semiCircleProgressBarView.setClipping(70); //70% progress
    

    您可以使用自己的映像来满足要求。希望能有帮助

    编辑:要将半圆移动到屏幕底部,请更改
    mPivotY
    值。像这样的

    //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);
            }
    

    这是一个高度等于其宽度一半的视图。 使用设定器根据需要调整行为。 默认情况下,进度为0,弧的宽度为20。 调用setProgress()将使具有给定进度的视图无效。 添加一个背景绘图是可能的,进度条将绘制在顶部

    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);
    }
    }
    
    你可以试试。我知道它是一种不同的seekbar,但是通过一些小的定制,你可以将它作为progressbar应用程序使用。我也这么做了。您只需更改一些属性,如
    请参见karc:touchInside=“false”

    这相当简单

    现在,我的应用程序上的自定义实现看起来有点像:


    img src:

    您还可以使用本机的
    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" />
    
    ProgressBar progressBar = (Progressbar) view.findViewById(R.id.progressBar);
    progressBar.setProgress(value); // 0 <= value <= 100
    
    通告
    (API级别>=21):


    您可以使用此库:

     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"/>
    
    
    

    
    
    有关更多信息,请访问以下网站:


    将setProgressDrawable与您的自定义可绘制绘图一起使用上面添加了更多选项,希望其中一个有帮助。@DhawalSodhaParmar Yes.。这应该是可能的。.尝试更改
    mPivotX
    mPivotY
    值。为什么要剪裁图像而不只是绘制半圆?这样你就不必关闭硬件加速。@AustynMahoney是的,你是对的。@DhawalSodhaParmar如果你不想关闭硬件加速,你可以只画图像而不是剪切。但逻辑仍然是一样的。您也可以使用相同的路径。在测量错误时,请在emulator 5“”中尝试,看看它是如何工作的。这是一个很好的使用方法。现在我想了解更多的想法,以改进或了解我的需求,即。,我想在现有的基础上再加一个,我会考虑它的总数,新的一个是用的,因为我在同一个布局中放置了一个,现在我想从左到右添加第二个动画来提供一些指导来达到这个完美的库。
     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"/>