先看效果图:
4X~@W{D~3372R~S0{%1U`QG.png
分析这是线性渐变色,圆弧半径刚好是高度的一半,文字居中处理,大小,颜色可调
首先开始自定义控件的基本步骤
1、style 自定义属性
- <!--自定义控件属性-->
- <declare-styleable name="MyGradientRoundButton">
- <attr name="colorStart" format="reference" />
- <attr name="colorEnd" format="reference" />
- <attr name="round" format="dimension" />
- <attr name="clickEffect" format="boolean" />
- <attr name="colorPressStart" format="reference" />
- <attr name="colorPressEnd" format="reference" />
- <attr name="btnText" format="reference" />
- <attr name="btnTextSize" format="dimension" />
- <attr name="btnTextColor" format="reference" />
- </declare-styleable>
注:原本我是想还有点击效果的
2、继承 view 核心代码
- public class MyGradientRoundButton extends View {
- private int colorStart;
- private int colorEnd;
- private int colorPressStart;
- private int colorPressEnd;
- private int colorS;
- private int colorE;
- private String text;
- private int textColor;
- private float textSize;
- private float round;
- private boolean clickEffect;
- private RectF mBackGroundRect;
- private LinearGradient backGradient;
- //默认画笔
- private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- private Paint mPaintText = new Paint();
- public MyGradientRoundButton(Context context, AttributeSet attrs) {
- super(context, attrs);
- //获取自定义属性
- if (attrs != null) {
- TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyGradientRoundButton);
- colorStart = typedArray.getColor(R.styleable.MyGradientRoundButton_colorStart, getResources().getColor(R.color.btn_color_start));
- colorEnd = typedArray.getColor(R.styleable.MyGradientRoundButton_colorEnd, getResources().getColor(R.color.btn_color_end));
- round = typedArray.getDimension(R.styleable.MyGradientRoundButton_round, Utils.dip2px(context, 10));
- clickEffect = typedArray.getBoolean(R.styleable.MyGradientRoundButton_clickEffect, false);
- colorPressStart = typedArray.getColor(R.styleable.MyGradientRoundButton_colorPressStart, getResources().getColor(R.color.btn_color_PStart));
- colorPressEnd = typedArray.getColor(R.styleable.MyGradientRoundButton_colorPressEnd, getResources().getColor(R.color.btn_color_PEnd));
- text = typedArray.getString(R.styleable.MyGradientRoundButton_btnText);
- textColor = typedArray.getColor(R.styleable.MyGradientRoundButton_btnTextColor, getResources().getColor(R.color.black));
- textSize = typedArray.getDimension(R.styleable.MyGradientRoundButton_btnTextSize, 16);
- colorS = colorStart;
- colorE = colorEnd;
- typedArray.recycle();
- }
- //必须加,否则onTouchEvent只响应ACTION_DOWN
- setClickable(true);
- //设置抗锯齿
- mPaint.setAntiAlias(true);
- //设置防抖动
- mPaint.setDither(true);
- mPaint.setStyle(Paint.Style.FILL);
- mPaintText.setAntiAlias(true);
- mPaintText.setDither(true);
- }@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- mBackGroundRect = new RectF(0, 0, w, h);
- backGradient = new LinearGradient(0, 0, w, 0, new int[] {
- colorS,
- colorE
- },
- null, Shader.TileMode.CLAMP);
- }@Override protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- mPaint.setShader(backGradient);
- //绘制背景 圆角矩形
- if (mBackGroundRect != null) {
- canvas.drawRoundRect(mBackGroundRect, round, round, mPaint);
- }
- //绘制文字
- mPaintText.setTextSize(textSize);
- mPaintText.setColor(textColor);
- mPaintText.setTextAlign(Paint.Align.CENTER);
- Paint.FontMetricsInt fontMetrics = mPaintText.getFontMetricsInt();
- float baseline = mBackGroundRect.top + (mBackGroundRect.bottom - mBackGroundRect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
- canvas.drawText(text, canvas.getWidth() / 2, baseline, mPaintText);
- }@Override public boolean onTouchEvent(MotionEvent event) {
- if (clickEffect) {
- //刷新
- invalidate();
- //判断点击操作
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- colorS = colorPressStart;
- colorE = colorPressEnd;
- break;
- case MotionEvent.ACTION_MOVE:
- break;
- case MotionEvent.ACTION_UP:
- colorS = colorStart;
- colorE = colorEnd;
- break;
- case MotionEvent.ACTION_CANCEL:
- break;
- }
- }
- return super.onTouchEvent(event);
- }
- public void setText(String text) {
- if (!TextUtils.isEmpty(text)) {
- this.text = text;
- invalidate();
- }
- }
- }
关键代码讲解:
onDraw(): 绘制图形过程,canvas.drawXXX() 就是在绘制一层层图层,所以 drawRoundRect 要在 drawText 之前
LinearGradient:线性渐变色
RectF:正方形,配合 drawRoundRect 就可以画出带圆角的图形
onSizeChanged():发生在 onDraw() 之前,一般可以做些不变的参数设定,调用 onDraw(), 它也不调用的
invalidate():每调一次,也就调用了一次 onDraw() 方法,这样就可以做点击效果了
3、引用列子
- <com.yiban1314.yiyue.widge.MyGradientRoundButton
- android:id="@+id/dialog_guide_reg"
- android:layout_width="match_parent"
- android:layout_height="@dimen/d80px"
- app:clickEffect="false"
- app:round="@dimen/d40px"
- app:colorStart="@color/btn_color_start"
- app:colorEnd="@color/btn_color_end"
- app:btnText="@string/register"
- app:btnTextColor="@color/c_22"
- app:btnTextSize="@dimen/s32px"
- android:layout_marginBottom="@dimen/d64px"
- android:layout_marginTop="@dimen/d64px"/>
这个自定义控件有个缺陷宽高不能用 wrap_content 属性。
来源: http://www.jianshu.com/p/26b525dbfaf4