2015-07-04 35 views
22

Tôi đang cố tạo thanh tiến trình hình tròn trên Android và có vẻ như công việc khá đơn giản, nhưng tôi đang vật lộn với làm tròn các cạnh của tiến trình và tiến trình phụ.Cạnh tròn hình tròn trên thanh tròn hình tròn

Có cách nào để làm điều đó mà không thực hiện chế độ xem tùy chỉnh không? Sử dụng bán kính góc? hoặc chín bản vá có thể vẽ được?

Đối với quan điểm này (xem attachement) Tôi đang sử dụng một tập tin xml đơn giản

<item android:id="@android:id/progress"> 


    <shape 
     android:useLevel="true" 
     android:innerRadius="@dimen/sixty_dp" 
     android:shape="ring" 
     android:thickness="@dimen/seven_dp"> 

     <solid android:color="#477C5B"/> 

     <stroke android:width="1dip" 
      android:color="#FFFF"/> 
    </shape> 






</item> 

enter image description here

+2

Tôi nghĩ bạn nên đi với giao diện tùy chỉnh ... vì tôi cũng phải đối mặt với cùng một vấn đề ... http://stackoverflow.com/q/29516123/3544839 và tôi đã thực hiện nó với customview – Moinkhan

+0

@ Moinkhan bạn có thể làm cho mã của bạn có sẵn trên Github không? Cảm ơn bạn trước. – moujib

+0

hiện tại tôi đang ở xa máy tính của mình ..i sẽ gửi cho bạn vào ngày mai .. – Moinkhan

Trả lời

19

Chỉ cần tạo lớp được gọi là MyProgress trong gói của bạn .. và dán đoạn mã sau ..

import android.content.Context; 
import android.content.res.TypedArray; 
import android.graphics.Canvas; 
import android.graphics.Paint; 
import android.graphics.RectF; 
import android.text.TextPaint; 
import android.util.AttributeSet; 
import android.view.View; 

public class MyProgress extends View { 

    private Paint mPrimaryPaint; 
    private Paint mSecondaryPaint; 
    private RectF mRectF; 
    private TextPaint mTextPaint; 
    private Paint mBackgroundPaint; 

    private boolean mDrawText = false; 

    private int mSecondaryProgressColor; 
    private int mPrimaryProgressColor; 
    private int mBackgroundColor; 

    private int mStrokeWidth; 

    private int mProgress; 
    private int mSecodaryProgress; 

    private int mTextColor; 

    private int mPrimaryCapSize; 
    private int mSecondaryCapSize; 
    private boolean mIsPrimaryCapVisible; 
    private boolean mIsSecondaryCapVisible; 

    private int x; 
    private int y; 
    private int mWidth = 0, mHeight = 0; 


    public MyProgress(Context context) { 
     super(context); 
     init(context, null); 
    } 

    public MyProgress(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(context, attrs); 
    } 

    public MyProgress(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     init(context, attrs); 
    } 

    void init(Context context, AttributeSet attrs) { 
     TypedArray a; 
     if (attrs != null) { 
      a = context.getTheme().obtainStyledAttributes(
        attrs, 
        R.styleable.MyProgress, 
        0, 0); 
     } else { 
      throw new IllegalArgumentException("Must have to pass the attributes"); 
     } 

     try { 
      mDrawText = a.getBoolean(R.styleable.MyProgress_showProgressText, false); 

      mBackgroundColor = a.getColor(R.styleable.MyProgress_backgroundColor, android.R.color.darker_gray); 
      mPrimaryProgressColor = a.getColor(R.styleable.MyProgress_progressColor, android.R.color.darker_gray); 
      mSecondaryProgressColor = a.getColor(R.styleable.MyProgress_secondaryProgressColor, android.R.color.black); 

      mProgress = a.getInt(R.styleable.MyProgress_progress, 0); 
      mSecodaryProgress = a.getInt(R.styleable.MyProgress_secondaryProgress, 0); 

      mStrokeWidth = a.getDimensionPixelSize(R.styleable.MyProgress_strokeWidth, 20); 
      mTextColor = a.getColor(R.styleable.MyProgress_textColor, android.R.color.black); 

      mPrimaryCapSize = a.getInt(R.styleable.MyProgress_primaryCapSize, 20); 
      mSecondaryCapSize = a.getInt(R.styleable.MyProgress_secodaryCapSize, 20); 

      mIsPrimaryCapVisible = a.getBoolean(R.styleable.MyProgress_primaryCapVisibility, true); 
      mIsSecondaryCapVisible = a.getBoolean(R.styleable.MyProgress_secodaryCapVisibility, true); 
     } finally { 
      a.recycle(); 
     } 

     mBackgroundPaint = new Paint(); 
     mBackgroundPaint.setAntiAlias(true); 
     mBackgroundPaint.setStyle(Paint.Style.STROKE); 
     mBackgroundPaint.setStrokeWidth(mStrokeWidth); 
     mBackgroundPaint.setColor(mBackgroundColor); 

     mPrimaryPaint = new Paint(); 
     mPrimaryPaint.setAntiAlias(true); 
     mPrimaryPaint.setStyle(Paint.Style.STROKE); 
     mPrimaryPaint.setStrokeWidth(mStrokeWidth); 
     mPrimaryPaint.setColor(mPrimaryProgressColor); 

     mSecondaryPaint = new Paint(); 
     mSecondaryPaint.setAntiAlias(true); 
     mSecondaryPaint.setStyle(Paint.Style.STROKE); 
     mSecondaryPaint.setStrokeWidth(mStrokeWidth - 2); 
     mSecondaryPaint.setColor(mSecondaryProgressColor); 

     mTextPaint = new TextPaint(); 
     mTextPaint.setColor(mTextColor); 

     mRectF = new RectF(); 
    } 

    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     super.onSizeChanged(w, h, oldw, oldh); 
     mRectF.set(getPaddingLeft(), getPaddingTop(), w - getPaddingRight(), h - getPaddingBottom()); 
     mTextPaint.setTextSize(w/5); 
     x = (w/2) - ((int) (mTextPaint.measureText(mProgress + "%")/2)); 
     y = (int) ((h/2) - ((mTextPaint.descent() + mTextPaint.ascent())/2)); 
     mWidth = w; 
     mHeight = h; 
     invalidate(); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 

     mPrimaryPaint.setStyle(Paint.Style.STROKE); 
     mSecondaryPaint.setStyle(Paint.Style.STROKE); 

     // for drawing a full progress .. The background circle 
     canvas.drawArc(mRectF, 0, 360, false, mBackgroundPaint); 

     // for drawing a secondary progress circle 
     int secondarySwipeangle = (mSecodaryProgress * 360)/100; 
     canvas.drawArc(mRectF, 270, secondarySwipeangle, false, mSecondaryPaint); 

     // for drawing a main progress circle 
     int primarySwipeangle = (mProgress * 360)/100; 
     canvas.drawArc(mRectF, 270, primarySwipeangle, false, mPrimaryPaint); 

     // for cap of secondary progress 
     int r = (getHeight() - getPaddingLeft() * 2)/2;  // Calculated from canvas width 
     double trad = (secondarySwipeangle - 90) * (Math.PI/180d); // = 5.1051 
     int x = (int) (r * Math.cos(trad)); 
     int y = (int) (r * Math.sin(trad)); 
     mSecondaryPaint.setStyle(Paint.Style.FILL); 
     if (mIsSecondaryCapVisible) 
      canvas.drawCircle(x + (mWidth/2), y + (mHeight/2), mSecondaryCapSize, mSecondaryPaint); 

     // for cap of primary progress 
     trad = (primarySwipeangle - 90) * (Math.PI/180d); // = 5.1051 
     x = (int) (r * Math.cos(trad)); 
     y = (int) (r * Math.sin(trad)); 
     mPrimaryPaint.setStyle(Paint.Style.FILL); 
     if (mIsPrimaryCapVisible) 
      canvas.drawCircle(x + (mWidth/2), y + (mHeight/2), mPrimaryCapSize, mPrimaryPaint); 


     if (mDrawText) 
      canvas.drawText(mProgress + "%", x, y, mTextPaint); 
    } 

    public void setDrawText(boolean mDrawText) { 
     this.mDrawText = mDrawText; 
     invalidate(); 
    } 

    public void setBackgroundColor(int mBackgroundColor) { 
     this.mBackgroundColor = mBackgroundColor; 
     invalidate(); 
    } 

    public void setSecondaryProgressColor(int mSecondaryProgressColor) { 
     this.mSecondaryProgressColor = mSecondaryProgressColor; 
     invalidate(); 
    } 

    public void setPrimaryProgressColor(int mPrimaryProgressColor) { 
     this.mPrimaryProgressColor = mPrimaryProgressColor; 
     invalidate(); 
    } 

    public void setStrokeWidth(int mStrokeWidth) { 
     this.mStrokeWidth = mStrokeWidth; 
     invalidate(); 
    } 

    public void setProgress(int mProgress) { 
     this.mProgress = mProgress; 
     invalidate(); 
    } 

    public void setSecondaryProgress(int mSecondaryProgress) { 
     this.mSecodaryProgress = mSecondaryProgress; 
     invalidate(); 
    } 

    public void setTextColor(int mTextColor) { 
     this.mTextColor = mTextColor; 
     invalidate(); 
    } 

    public void setPrimaryCapSize(int mPrimaryCapSize) { 
     this.mPrimaryCapSize = mPrimaryCapSize; 
     invalidate(); 
    } 

    public void setSecondaryCapSize(int mSecondaryCapSize) { 
     this.mSecondaryCapSize = mSecondaryCapSize; 
     invalidate(); 
    } 

    public boolean isPrimaryCapVisible() { 
     return mIsPrimaryCapVisible; 
    } 

    public void setIsPrimaryCapVisible(boolean mIsPrimaryCapVisible) { 
     this.mIsPrimaryCapVisible = mIsPrimaryCapVisible; 
    } 

    public boolean isSecondaryCapVisible() { 
     return mIsSecondaryCapVisible; 
    } 

    public void setIsSecondaryCapVisible(boolean mIsSecondaryCapVisible) { 
     this.mIsSecondaryCapVisible = mIsSecondaryCapVisible; 
    } 


    public int getSecondaryProgressColor() { 
     return mSecondaryProgressColor; 
    } 

    public int getPrimaryProgressColor() { 
     return mPrimaryProgressColor; 
    } 

    public int getProgress() { 
     return mProgress; 
    } 

    public int getBackgroundColor() { 
     return mBackgroundColor; 
    } 

    public int getSecodaryProgress() { 
     return mSecodaryProgress; 
    } 

    public int getPrimaryCapSize() { 
     return mPrimaryCapSize; 
    } 

    public int getSecondaryCapSize() { 
     return mSecondaryCapSize; 
    } 
} 

và thêm dòng sau vào res-> values-> attr.xml dưới thẻ và tạo

<declare-styleable name="MyProgress"> 
    <attr name="showProgressText" format="boolean" /> 
    <attr name="progress" format="integer" /> 
    <attr name="secondaryProgress" format="integer" /> 
    <attr name="progressColor" format="color" /> 
    <attr name="secondaryProgressColor" format="color" /> 
    <attr name="backgroundColor" format="color" /> 
    <attr name="primaryCapSize" format="integer" /> 
    <attr name="secodaryCapSize" format="integer" /> 
    <attr name="primaryCapVisibility" format="boolean" /> 
    <attr name="secodaryCapVisibility" format="boolean" /> 
    <attr name="strokeWidth" format="dimension" /> 
    <attr name="textColor" format="color" /> 
</declare-styleable> 

đó là nó .... và sử dụng trong cách bố trí của bạn ..

<Your_Package_Name.MyProgress 
    android:padding="20dp" 
    android:id="@+id/timer1" 
    app:strokeWidth="10dp" 
    app:progress="30" 
    app:secondaryProgress="50" 
    app:backgroundColor="@android:color/black" 
    app:progressColor="@android:color/holo_blue_bright" 
    app:secondaryProgressColor="@android:color/holo_blue_dark" 
    app:primaryCapSize="30" 
    app:secodaryCapSize="40" 
    app:primaryCapVisibility="true" 
    app:secodaryCapVisibility="true" 
    android:layout_width="200dp" 
    android:layout_height="200dp" /> 

Bạn cũng có thể thay đổi tất cả tài sản progrmatically sử dụng setMethods() ... enter image description here

vui lòng hỏi bất cứ điều gì .. may mắn nhất

[Cập nhật 23-01-2016]

cuối cùng tôi đã tải lên mã trên github. Bạn có thể tham khảo từ đây https://github.com/msquare097/MProgressBar

Bây giờ bạn có thể sử dụng ProgressBar này bằng cách viết dòng sau vào tệp build.gradle ứng dụng của bạn. Bạn không phải sao chép mã trên.

compile 'com.msquare.widget.mprogressbar:mprogressbar:1.0.0' 
+0

Tôi vẫn đang làm việc với nó ... vì vậy tôi sẽ đặt nó sau này trên github ... – Moinkhan

+1

Cảm ơn, đó là những gì tôi cần. Chấp nhận câu trả lời của bạn. Làm cho nó có sẵn trên github sẽ là tuyệt vời. – moujib

+0

@Moinkhan làm thế nào tôi có thể thiết lập Cap không chỉ cho sự kết thúc của tiến bộ, cũng cho đầu tiên của nó ??? TnX –