自定义优惠券

最近做项目的时候,加入优惠券模块,效果图如下:

最终效果图

下面简单的说下实现过程。

  • 首先是自定义了一个控件CouponView,该控件继承了LinearLayout,该控件有如下几个自定义属性:
<declare-styleable name="CouponView">
        <attr name="radius" format="dimension"/>
        <attr name="sawtooth_color" format="color"/>
        <attr name="background_color" format="color"/>
        <attr name="sawtooth_width_gap" format="dimension"/>
        <attr name="sawtooth_weight" format="float"/>
    </declare-styleable>

其中radius表示的是右边那列小锯齿的半径大小,sawtooth_color表示左边的锯齿部分的背景颜色,background_color表示整体的背景颜色,sawtooth_width_gap表示锯齿之间的间隙大小,sawtooth_weight表示左边含有锯齿部分的宽度占整个布局的宽度比例。

  • 接下来在CouponView中获取到这些属性:
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CouponView);
        int n = a.getIndexCount();
        for (int i = 0; i < n; i++) {

            int attr = a.getIndex(i);
            switch (attr) {
                case R.styleable.CouponView_radius:
                    mRRadius = a.getDimension(attr, 10);
                    break;
                case R.styleable.CouponView_sawtooth_color:
                    mSawtoothColor = a.getColor(attr, 0);
                    break;
                case R.styleable.CouponView_sawtooth_width_gap:
                    mRCircleGap = a.getDimension(attr, 8);
                    break;
                case R.styleable.CouponView_sawtooth_weight:
                    mSawtoothWeight = a.getFloat(attr, 0.65f);
                    break;
                case R.styleable.CouponView_background_color:
                    mBackgroundColor = a.getColor(attr, 0);
            }
        }
        a.recycle();

获取参数这个没什么好说的,获取完参数之后别忘了初始化Paint,还有千万别漏了setWillNotDraw(false),如果不设置该属性为false,onDraw有可能不会被调用到:

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setDither(true);
        mPaint.setStyle(Paint.Style.FILL);
        //别忘了将该属性设置为false
        setWillNotDraw(false);
  • 接着根据既有数值算出锯齿的个数及剩余空间:
@Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if(changed) {
            //计算剩余空间
            if (mRRemain == 0) {
                mRRemain = (int) (b - t - mRCircleGap - getPaddingTop() - getPaddingBottom()) % (2 * mRRadius + mRCircleGap);
            }
            //计算锯齿半圆个数
            mRCircleNum = (int) ((b - t - mRCircleGap - getPaddingTop() - getPaddingBottom()) / (2 * mRRadius + mRCircleGap));
        }
    }

这里的剩余空间是指根据指定的半径大小画了mRCircleNum个 半圆后还剩余的高度,用于指定画半圆的开始的位置。

  • 接下来就是draw的过程了:
 float width = getWidth() - getPaddingLeft() - getPaddingRight();
        float height = getHeight() - getPaddingTop() - getPaddingBottom();
        mPaint.setColor(mSawtoothColor);
        //画锯齿背景
        canvas.drawRect(getPaddingLeft(), getPaddingTop(), getPaddingLeft() + (width * mSawtoothWeight), getPaddingTop() + height, mPaint);

        mPaint.setColor(mBackgroundColor);
        //画锯齿部分
        for (int i = 0; i < mRCircleNum; i++) {
            float y = mRCircleGap + mRRadius + mRRemain / 2 + ((mRCircleGap + mRRadius * 2) * i) + getPaddingTop();
            canvas.drawCircle(getPaddingLeft() + width * mSawtoothWeight, y, mRRadius, mPaint);
        }
        //画右边剩余部分
        canvas.drawRect(getPaddingLeft() + width * mSawtoothWeight, getPaddingTop(), width + getPaddingLeft(), height + getPaddingTop(), mPaint);
mPaint);
        //画左边的大的半圆
        mOval.set(getPaddingLeft() - mLRadius,
                getPaddingTop() + (height - 2 * mLRadius) / 2,
                getPaddingLeft() + mLRadius,
                getPaddingTop() + (height - 2 * mLRadius) / 2 + 2 * mLRadius);
        canvas.drawArc(mOval, -90, 180, true, mPaint);

这里需要说明的是画左边的半圆用的是drawArc而不是drawCircle,因为drawCircle会画出整个圆,所以这里通过计算弧度来画半圆。其余的都比较简单,不用多说。

  • 最后在布局文件中使用就行了:
<com.example.coupondemo.view.CouponView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:coupon="http://schemas.android.com/apk/res-auto"
    coupon:background_color="@android:color/white"
    coupon:sawtooth_color="@color/coupon_sawtooth_bg_color"
    coupon:sawtooth_weight="0.7"
    android:layout_width="match_parent"
    android:layout_height="120dp"
    android:paddingLeft="30dp"
    android:paddingRight="30dp"
    android:orientation="horizontal">

代码就这么多,基本实现了该效果。

附上代码:
CouponDemo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值