您的位置:首页 > 其它

自定义优惠券

2016-06-04 16:19 337 查看
最近做项目的时候,加入优惠券模块,效果图如下:



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

首先是自定义了一个控件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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息