自定义弧形View 渐变View

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HUandroid/article/details/84820541

自定义弧形View 渐变View

由于项目要求,要写一个渐变的弧形View作为背景。看效果图
在这里插入图片描述

规划好属性

  1. 渐变色起点
  2. 渐变色终点
  3. 圆弧高度
  4. 非圆弧颜色
  5. 渐变方向
<declare-styleable name="ArcGradualView">
        <attr name="color_gradual_start" format="color" />
        <attr name="color_gradual_end" format="color" />
        <attr name="height_arc" format="dimension" />
        <attr name="gradual_or">
            <!--水平方向-->
            <enum name="orizontal" value="0" />
            <!--垂直方向-->
            <enum name="vertical" value="1" />
            <!--对角线45-->
            <enum name="angles45" value="2" />
            <!--对角线135-->
            <enum name="angles135" value="3" />
        </attr>
        <attr name="color_other_arc" format="color" />
    </declare-styleable>

代码实现

public class ArcGradualView extends View {
    private Paint mPaint;
    private PointF mStartPoint, mEndPoint, mControlPoint;
    private int mWidth;
    private int mHeight;
    private Path mPath = new Path();
    private float mArcHeight;
    private int mStartColor;
    private int mEndColor;
    private int mOthColor;
    private LinearGradient mLinearGradient;
    private int anInt;
    private Paint mBgPaint;

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

    public ArcGradualView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

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

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public ArcGradualView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        if (attrs != null) {
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ArcGradualView);
            mArcHeight = a.getDimension(R.styleable.ArcGradualView_height_arc, 30);
            anInt = a.getInt(R.styleable.ArcGradualView_gradual_or, 0);
            mStartColor = a.getColor(R.styleable.ArcGradualView_color_gradual_start, Color.parseColor("#000000"));
            mEndColor = a.getColor(R.styleable.ArcGradualView_color_gradual_end, Color.parseColor("#FFFFFF"));
            mOthColor = a.getColor(R.styleable.ArcGradualView_color_other_arc, Color.parseColor("#CCCCCC"));
        } else {
            //低版本情况  这里写一些默认值
        }
        //渐变颜色画笔初始化--不需要设置颜色 用setShader去设置
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(10);
        mPaint.setStyle(Paint.Style.FILL);

        //初始化其他背景的画笔
        mBgPaint = new Paint();
        mBgPaint.setAntiAlias(true);
        mBgPaint.setStrokeWidth(10);
        mBgPaint.setStyle(Paint.Style.FILL);

        //初始化圆弧的控制点
        mStartPoint = new PointF(0, 0);
        mEndPoint = new PointF(0, 0);
        mControlPoint = new PointF(0, 0);
    }

    public void setGradient(int anInt) {
        switch (anInt) {
            case 0:
                mLinearGradient = new LinearGradient(mWidth / 2, 0, mWidth / 2, mHeight, mStartColor, mEndColor, Shader.TileMode.MIRROR);
                break;
            case 1:
                mLinearGradient = new LinearGradient(0, mHeight / 2, mWidth, mHeight / 2, mStartColor, mEndColor, Shader.TileMode.MIRROR);
                break;
            case 2:
                mLinearGradient = new LinearGradient(0, mHeight, mWidth, 0, mStartColor, mEndColor, Shader.TileMode.MIRROR);
                break;
            case 3:
                mLinearGradient = new LinearGradient(0, 0, mWidth, mHeight, mStartColor, mEndColor, Shader.TileMode.MIRROR);
                break;
        }
    }

    /**
     * 动态修改渐变色  暴露在外的
     * @param startColor
     * @param endColor
     * @param anType
     */
    public ArcGradualView setColor(@ColorInt int startColor, @ColorInt int endColor, @IntRange(from = 0, to = 3) int anType) {
        mStartColor = startColor;
        mEndColor = endColor;
        anInt = anType;
        setGradient(anType);
        invalidate();
        return this;
    }

    /**
     * 修改弧高
     * @param acrH
     * @return
     */
    public ArcGradualView changeArcHeight(int acrH){
        mArcHeight = acrH;
        invalidate();
        return this;
    }

    /**
     * 修改非圆弧背景
     * @param otherColor
     * @return
     */
    public ArcGradualView changOtherColor(@ColorInt int otherColor){
        mOthColor = otherColor;
        invalidate();
        return this;
    }

    /**
     * onSizeChanged才能拿到准确的w和h
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
        mPath.reset();
        //顺时针移动
        mPath.moveTo(0, 0);
        mPath.addRect(0, 0, mWidth, mHeight - mArcHeight, Path.Direction.CCW);
        //起始点= 0,布局总高-圆弧高度
        mStartPoint.x = 0;
        mStartPoint.y = mHeight - mArcHeight;
        //起始点= 总宽,布局总高-圆弧高度
        mEndPoint.x = mWidth;
        mEndPoint.y = mHeight - mArcHeight;
        //贝塞尔曲线控制点 = 中点,总高+控制点
        mControlPoint.x = mWidth / 2;
        mControlPoint.y = mHeight + mArcHeight;
        setGradient(anInt);
        invalidate();
    }

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

        mPaint.setShader(mLinearGradient);
        mPath.moveTo(mStartPoint.x, mStartPoint.y);
        mPath.quadTo(mControlPoint.x, mControlPoint.y, mEndPoint.x, mEndPoint.y);
        //先画背景
        canvas.drawRect(new Rect(0, 0, mWidth, mHeight), mBgPaint);
        //画大圆弧
        canvas.drawPath(mPath, mPaint);
    }
}
 <com.hujin.test.view.ArcGradualView
           android:id="@+id/header_view"
           app:height_arc="30dp"
           app:color_gradual_start="@color/colorAccent"
           app:color_gradual_end="@color/colorPrimary"
           app:gradual_or="vertical"
           app:color_other_arc="@android:color/black"
           android:layout_width="match_parent"
           android:layout_height="200dp"/>

最终效果图:
在这里插入图片描述

这里提供了暴露在外的方法提供动态修改.`

  • setColor修改渐变色和渐变方向
  • changeArcHeight修改弧高
  • changOtherColor修改非圆弧背景

主要使用了贝塞尔曲线的绘制,要保证圆弧顶点在最下面,所以圆弧的控制点是在布局外面的

		mControlPoint.x = mWidth / 2;
        mControlPoint.y = mHeight + mArcHeight;

可以参考贝塞尔介绍:
贝塞尔去曲线介绍

代码很简单…
可以研究下新问题:

invalidate();和postInvalidate();requestLayout();的区别

猜你喜欢

转载自blog.csdn.net/HUandroid/article/details/84820541