最近项目中用到这种效果,UX 圣诞度假,只能自力更生,开一波车了,记录下爬坑过程

先来个效果图

弧形背景ShapeDrawable,PathShape,Path自定义图形边界

中间用到这个函数

public void quadTo(float x1, float y1, float x2, float y2){
	...
}

这个参数x1,y1,是贝塞尔曲线的控制点,也就是起始位置的切线交点,弧形并没有经过它,这里我们需要三点确定圆弧,也就是下图中的E,D,A,而E点就是我们view的左上顶点,A点是我们的右上顶点,CD的长度是我们自定义的高度ArcBackgroundViewTopHeight,用来控制圆弧,那我们需要知道B点相对于E点的坐标就可以画出来了,怎么算呢?

弧形背景ShapeDrawable,PathShape,Path自定义图形边界

一度陷入了计算中,解出来感觉这是个初中证明题,添加个辅助线CF,C是AE的中点,△ACF 相似于△AEB,那么AC/AE = AF/AB=1/2,也就是F是AB的中点,同理△BDF 相似于△BEA ,那么BD/BC = BF/BA = 1/2,即D为BC的中点,那么控制点的相对于view 原点E的坐标就是 mArcBackgroundViewTopHeight * 2

这里用的渐变色,如果是背景图片 需要用到BitmapShader

至于用到的android api 网上介绍很多就不展开了

全部代码

package com.example.zhangyan.myapplication;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Path;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.PathShape;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import com.zhang.test.R;

public class ArcBackgroundView extends View {

    private int mWidth;
    private int mHeight;
    private int mArcImageViewTopHeight;
    private Path mPath;
    private PathShape mPathShape;
    private int mArcBackgroundViewEndColor;
    private int mArcBackgroundViewStartColor;
    private int[] mColors;
    private LinearGradient mLinearGradient;
    private ShapeDrawable mShapeDrawable;

    public ArcBackgroundView(Context context) {
        this(context, null);
    }

    public ArcBackgroundView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ArcBackgroundView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

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

    private void init(AttributeSet attrs, Context context) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ArcBackgroundView);
        mArcBackgroundViewEndColor = typedArray.getColor(R.styleable.ArcBackgroundView_ArcBackgroundViewEndColor, mArcBackgroundViewEndColor);
        mArcBackgroundViewStartColor = typedArray.getColor(R.styleable.ArcBackgroundView_ArcBackgroundViewStartColor, mArcBackgroundViewStartColor);
        mArcImageViewTopHeight = typedArray.getDimensionPixelOffset(R.styleable.ArcBackgroundView_ArcBackgroundViewTopHeight, 0);
        mPath = new Path();
        typedArray.recycle();
        mColors = new int[]{mArcBackgroundViewStartColor, mArcBackgroundViewEndColor};
        mShapeDrawable = new ShapeDrawable();

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        mHeight = MeasureSpec.getSize(heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPath.reset();
        mPath.moveTo(0, 0);
        mPath.quadTo(mWidth/2, mArcImageViewTopHeight * 2,mWidth, 0);
        mPath.lineTo(mWidth,mHeight);
        mPath.lineTo(0,mHeight);
        mPath.close();
        if (mPathShape == null) {
            mPathShape = new PathShape(mPath, mWidth,mHeight);
            mLinearGradient = new LinearGradient(0, 0, 0, mHeight, mColors, null, Shader.TileMode.CLAMP);
        }
        mShapeDrawable.setShape(mPathShape);
        mShapeDrawable.setBounds(0,0,mWidth,mHeight);
        mShapeDrawable.getPaint().setShader(mLinearGradient);
        mShapeDrawable.draw(canvas);
    }
}

自定义属性

<declare-styleable name="ArcBackgroundView">
    <attr name="ArcBackgroundViewStartColor" format="color" />
    <attr name="ArcBackgroundViewTopHeight" format="dimension" />
    <attr name="ArcBackgroundViewEndColor" format="color" />
</declare-styleable>

使用

 <com.example.zhangyan.myapplication.ArcBackgroundView
        android:layout_width="match_parent"
        android:layout_marginTop="90dp"
        app:ArcBackgroundViewEndColor="#f0f"
        app:ArcBackgroundViewStartColor="#ff0"
        app:ArcBackgroundViewTopHeight="80dp"
        android:layout_height="400dp" />

相关文章: