Android 自定义圆角进度 View

标签 android

我想构建一个自定义进度音频播放器。就像 Facebook 一样。

我为此使用自定义 Linearview 和 GradientDrawables。我在 Ondraw 函数上填写了进度条。

public class wavPlayerView extends LinearLayout {

            private float mCornerRadius = 0;
            private float mProgressMargin = 0;
            private int progressColor;
            private boolean mFinish;

            private int mProgress=0;
            private int mMaxProgress = 100;
            private int mMinProgress = 0;

            private GradientDrawable mDrawableLayout;
            private GradientDrawable mDrawableProgressBackground;
            private GradientDrawable mDrawableProgress;
            private Context mContext;

            private wavPlayer mWavPlayer;


            private ImageView wavPlayerButton;
            private TextView wavPlayerDuration;


            public wavPlayerView(Context context) {
                super(context);
                initialize(context,null);
            }

            public wavPlayerView(Context context, @Nullable AttributeSet attrs) {
                super(context, attrs);
                initialize(context,attrs);
            }

            public wavPlayerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
                super(context, attrs, defStyleAttr);
                initialize(context,attrs);
            }

            /**
             *
             * @param context
             * @param attrs
             */
            private void initialize(Context context, AttributeSet attrs) {
                mContext=context;

                LayoutInflater.from(context).inflate(R.layout.wav_player_layout, this);
                setOrientation(VERTICAL);

                //get elements
                wavPlayerButton = (ImageView) findViewById(R.id.wavPlayerBtn);
                wavPlayerDuration=(TextView)  findViewById(R.id.wavDuration);

                //Progress background drawable
                mDrawableProgressBackground = new GradientDrawable();
                //Progress drawable
                mDrawableProgress = new GradientDrawable();
                //Normal drawable
                mDrawableLayout = new GradientDrawable();

                //Get default normal color
                int defaultButtonColor = context.getResources().getColor(R.color.wite);
                //Get default progress color
                int defaultProgressColor = context.getResources().getColor(R.color.blue);
                //Get default progress background color
                int defaultBackColor = context.getResources().getColor(R.color.blue);


                TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.ProgressLayout);
                try {
                    mProgressMargin = attr.getDimension(R.styleable.ProgressLayout_progressMargin, mProgressMargin);
                    mCornerRadius = attr.getDimension(R.styleable.ProgressLayout_cornerRadius, mCornerRadius);
                    //Get custom normal color
                    int layoutColor = attr.getColor(R.styleable.ProgressLayout_layoutColor, defaultButtonColor);
                    //Set normal color
                    mDrawableLayout.setColor(layoutColor);
                    //Get custom progress background color
                    int progressBackColor = attr.getColor(R.styleable.ProgressLayout_progressBackColor, defaultBackColor);
                    //Set progress background drawable color
                    mDrawableProgressBackground.setColor(progressBackColor);
                    //Get custom progress color
                    progressColor = attr.getColor(R.styleable.ProgressLayout_progressColor, defaultProgressColor);
                    //Set progress drawable color
                    mDrawableProgress.setColor(progressColor);

                    //Get default progress
                    mProgress = attr.getInteger(R.styleable.ProgressLayout_progress, mProgress);
                    //Get minimum progress
                    mMinProgress = attr.getInteger(R.styleable.ProgressLayout_minProgress, mMinProgress);
                    //Get maximize progress
                    mMaxProgress = attr.getInteger(R.styleable.ProgressLayout_maxProgress, mMaxProgress);

                } finally {
                    attr.recycle();
                }
                //Set corner radius
                mDrawableLayout.setCornerRadius(mCornerRadius);
                mDrawableProgressBackground.setCornerRadius(mCornerRadius);

                setBackgroundDrawable(mDrawableLayout);

                mFinish = false;
            }


            @Override
            protected void onDraw(Canvas canvas) {

               if (mProgress > mMinProgress && mProgress <= mMaxProgress && !mFinish) {
                    //Calculate the width of progress
                    float progressWidth =
                            (float) getMeasuredWidth() * ((float) (mProgress - mMinProgress) / mMaxProgress - mMinProgress);

                    if(progressWidth >= (getMeasuredWidth()-mCornerRadius)){
                     mDrawableProgress.setCornerRadii(new float[]{mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius,mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius});
                    } else{
                     mDrawableProgress.setCornerRadii(new float[]{mCornerRadius, mCornerRadius, 0, 0, 0, 0, mCornerRadius, mCornerRadius});
                    }


                  //Set rect of progress
                   mDrawableProgress.setBounds(0,0,
                        (int) (progressWidth),(int)getMeasuredHeight());

                   //Draw progress
                   mDrawableProgress.draw(canvas);

                    if (mProgress == mMaxProgress) {
                        setBackgroundDrawable(mDrawableLayout);
                        mFinish = true;
                    }
                }
                super.onDraw(canvas);
            }


            /**
             * Set current progress
             */
            public void setProgress(int progress) {
                if (!mFinish) {
                    mProgress = progress;
                    setBackgroundDrawable(mDrawableProgressBackground);
                    invalidate();
                }
            }

            public void setMaxProgress(int maxProgress) {
                mMaxProgress = maxProgress;
            }

            public void setMinProgress(int minProgress) {
                mMinProgress = minProgress;
            }

            public void reset() {
                mFinish = false;
                mProgress = mMinProgress;

            }


            public wavPlayer getmWavPlayer() {
                return mWavPlayer;
            }        
         }

问题

问题出在 linearLayout 的圆角上。当我绘制进度矩形时,它超出了布局,当它离开角落时变成了内部。

screenchot1 screenshot2 screenshot3 screenchot4

最佳答案

我用这个数学公式解决了问题:

[ figure]

[ a=]

这是新代码:

@Override
    protected void onDraw(Canvas canvas) {

       if (mProgress > mMinProgress && mProgress <= mMaxProgress && !mFinish) {
            //Calculate the width of progress
            float progressWidth =
                    (float) getMeasuredWidth() * ((float) (mProgress - mMinProgress) / mMaxProgress - mMinProgress);

            if(progressWidth >= (getMeasuredWidth()-mCornerRadius)){
                float diff=progressWidth-((getMeasuredWidth()-mCornerRadius));
                mDrawableProgress.setBounds(0,0,
                        (int) (progressWidth),(int)getMeasuredHeight());
                mDrawableProgress.setCornerRadii(new float[]{mCornerRadius, mCornerRadius,diff,diff,diff, diff, mCornerRadius, mCornerRadius});
                //Draw progress
                mDrawableProgress.draw(canvas);
            } else{

                if(progressWidth<mCornerRadius){

                    Paint paint = new Paint();
                    paint.setStyle(Paint.Style.FILL);
                    paint.setColor(progressColor);
                    double a=2* Math.sqrt(progressWidth*((2*mCornerRadius)-progressWidth));
                    float rectTop=(float)(getMeasuredHeight()-a)/2;
                    RectF rect=new RectF(0,rectTop,2*progressWidth,(float)(rectTop+a));
                    canvas.drawArc(rect,90,180,true,paint);


                }else{
                    //Set rect of progress
                    mDrawableProgress.setBounds(0,0,
                            (int) (progressWidth),(int)getMeasuredHeight());
                    mDrawableProgress.setCornerRadii(new float[]{mCornerRadius, mCornerRadius, 0, 0, 0, 0, mCornerRadius, mCornerRadius});
                    //Draw progress
                    mDrawableProgress.draw(canvas);
                }

            }

            if (mProgress == mMaxProgress) {
              //  setBackgroundDrawable(mDrawableLayout);
                mFinish = true;
            }
        }
        super.onDraw(canvas);
    }

这里是结果:

image 1

image 2

image 3

关于Android 自定义圆角进度 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58247299/

相关文章:

android - 我应该将图像放在 eclipse 资源文件夹中的什么位置?

Android:如何根据 XML 中的屏幕密度访问不同的布局

android - 使用 SKZoonLevelConfiguration 启用自动缩放

android - 微调器错误 "Spinner adapter view type count must be 1"

android - On Activity 结果未调用且未找到错误源

Android:如何将 ListView 定位在屏幕上的特定位置

android - gson.fromJson - 反序列化失败

c# - 有没有办法为 Xamarin.Forms.Maps 引脚移动设置动画

android - 如何将媒体商店中没有的音乐文件设置为铃声

android - 关于生命周期方法定义的问题