android自定义布局实现优惠券效果
最近需要实现一个凹凸效果的拟物化优惠券效果,我一看,本来想用.9图片做背景实现的,虽说图片做背景实现省事儿方便,但是能用代码实现最好不过了,最终我还是选择了用代码来实现,于是有了下文。
最终效果图
demo下载地址
###1.完整代码 先看完整的代码,后面我们再对代码逐一的解释
public class CouponDisplayView extends RelativeLayout {private Paint mPaint;private Paint mPaint2;
// 圆间距private float gap = 0;
// 半径private float radius = 20;
// 圆数量private int circleNum;private float remain;private int color;public CouponDisplayView(Context context) {super(context);}public CouponDisplayView(Context context, AttributeSet attrs) {super(context, attrs);mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setDither(true);mPaint.setColor(color);mPaint.setStyle(Paint.Style.FILL);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);if (remain == 0) {remain = (int) (w - gap) % (2 * radius + gap);}circleNum = (int) ((w - gap) / (2 * radius + gap));}public CouponDisplayView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);for (int i = 0; i < circleNum; i++) {float x = gap + radius + remain / 2 + ((gap + radius * 2) * i);canvas.drawCircle(x, 0, radius, mPaint);}mPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint2.setDither(true);mPaint2.setColor(getResources().getColor(R.color.divider_color_car));mPaint2.setStyle(Paint.Style.FILL);Paint paint = new Paint();paint.setStyle(Paint.Style.STROKE);paint.setColor(Color.DKGRAY);Path path = new Path();path.moveTo(0, getHeight() / 2 + 60);path.lineTo(getWidth(), getHeight() / 2 + 60);PathEffect effects = new DashPathEffect(new float[]{15, 15, 15, 15}, 2);paint.setPathEffect(effects);canvas.drawPath(path, paint);canvas.drawCircle(0, getHeight() / 2 + 60, radius, mPaint2);canvas.drawCircle(getWidth(), getHeight() / 2 + 60, radius, mPaint2);}public void setColor(int color) {this.color = color;}
}
复制代码
###2.方法解释 1、CouponDisplayView继承自RelativeLayout,通过打印日志测试已知View的执行顺序如下:
CouponDisplayView(context,attrs,defStyleAttr)
CouponDisplayView(context,attrs)
onSizeChanged()
onDraw()
复制代码
onSizeChanged(int w, int h, int oldw, int oldh)
当view的大小发生变化时触发 onDraw(Canvas canvas)
负责将View绘制在屏幕上 public CouponDisplayView(Context context)
Java代码直接new一个CouponDisplayView实例的时候,会调用这个只有一个参数的构造函数 public CouponDisplayView(Context context, AttributeSet attrs)
在默认的XML布局文件中创建的时候调用这个有两个参数的构造函数。AttributeSet类型的参数负责把XML布局文件中所自定义的属性通过AttributeSet带入到View内; public CouponDisplayView(Context context,AttributeSet attrs, int defStyleAttr)
构造函数中第三个参数是默认的Style,这里的默认的Style是指它在当前Application或者Activity所用的Theme中的默认Style,且只有在明确调用的时候才会调用
###3.代码实现思路 从上面的效果图来看,这个自定义View和普通的Linearlayout,RelativeLayout一样,只是上下两边多了类似于半圆锯齿的形状,我们需要在上下两条线上画一个个白色的小圆来实现这种效果。 假如我们上下线的半圆以及半圆与半圆之间的间距是固定的,那么不同尺寸的屏幕肯定会画出不同数量的半圆,那么我们只需要根据控件的宽度来获取能画的半圆数。 我们观察效果图会发现,圆的数量总是圆间距数量-1,
也就是说,假设圆的数量是circleNum,那么圆间距就是circleNum+1,所以我们可以根据这个计算出circleNum: 这里gap就是圆间距,radius是圆半径,w是view的宽
circleNum = (int) ((w-gap)/(2*radius+gap));
复制代码
1 、重写onSizeChanged()方法,根据上面的圆的半径和圆间距来计算需要画的圆数量circleNum
@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);if (remain == 0) {remain = (int) (w - gap) % (2 * radius + gap);}circleNum = (int) ((w - gap) / (2 * radius + gap));}
复制代码
2.接下来只需要重写onDraw()方法,简单的根据circleNum的数量将一个一个的圆绘制在屏幕上
@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);for (int i = 0; i < circleNum; i++) {float x = gap + radius + remain / 2 + ((gap + radius * 2) * i);canvas.drawCircle(x, 0, radius, mPaint);}
}
复制代码
3.画中间的黑色虚线
Paint paint = new Paint();paint.setStyle(Paint.Style.STROKE);paint.setColor(Color.DKGRAY);Path path = new Path();path.moveTo(0, getHeight() / 2 + 60);path.lineTo(getWidth(), getHeight() / 2 + 60);PathEffect effects = new DashPathEffect(new float[]{15, 15, 15, 15}, 2);paint.setPathEffect(effects);canvas.drawPath(path, paint);
复制代码
4.画两边居中的半圆
mPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint2.setDither(true);mPaint2.setColor(getResources().getColor(R.color.divider_color_car));mPaint2.setStyle(Paint.Style.FILL);canvas.drawCircle(0, getHeight() / 2 + 60, radius, mPaint2);canvas.drawCircle(getWidth(), getHeight() / 2 + 60, radius, mPaint2);
复制代码
代码分析完毕
###3.设置自定义样式属性
考虑到复用地方不是很多,所以上面的代码没有写自定义样式属性,而是用了
public void setColor(int color) {this.color = color;}
有需要设置自定义属性的我在这里写一下哈,嘻嘻
1、在res/values/ 下建立一个attr.xml , 在里面定义我们的需要用到的属性以及声明相对应属性的取值类型
<?xml version="1.0" encoding="utf-8"?>
<resources>//半圆颜色<attr name="radiusColor" format="color" /><declare-styleable name="CouponDisplayView"><attr name="radiusColor" /></declare-styleable></resources>
复制代码
上面定义的半圆颜色的属性,format属性的取值类型总共有10种,包括:string
,color
,demension
,integer
,enum
,reference
,float
,boolean
,fraction
,flag
。
2、然后在XML布局中声明我们的自定义View
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:custom="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent">
<--注意:一定要引入xmlns:custom="http://schemas.android.com/apk/res-auto"
custom名字可以自定义--><com.xxx.xxx.CouponDisplayViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="#FBB039"android:orientation="horizontal"android:padding="16dp"custom:radiusColor="@Color/red">
............</com.xxx.xxx.CouponDisplayView>
</LinearLayout>
复制代码
3、在View的构造方法中,获得我们的xml布局文件中定义的颜色
public CouponDisplayView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);Log.d("mDebug", "CouponDisplayView context,attrs,defStyleAttr");
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CouponDisplayView, defStyleAttr, 0);for (int i = 0; i < a.getIndexCount(); i++) {int attr = a.getIndex(i);switch (attr) {case R.styleable.CouponDisplayView_radiusColor:radius = a.getDimensionPixelSize(R.styleable.CouponDisplayView_radiusColor, 10);break;}}a.recycle();
}
复制代码
OK,设置自定义样式属性到此就写完了。
转载于:https://juejin.im/post/5bdda7e451882516bb02e11b
android自定义布局实现优惠券效果相关推荐
- Android 自定义 圆环,Android自定义view实现圆环效果实例代码
先上效果图,如果大家感觉不错,请参考实现代码. 重要的是如何实现自定义的view效果 (1)创建类,继承view,重写onDraw和onMesure方法 public class CirclePerc ...
- android中仿qq最新版抽屉,Android 自定义View实现抽屉效果
Android 自定义View实现抽屉效果 说明 这个自定义View,没有处理好多点触摸问题 View跟着手指移动,没有采用传统的scrollBy方法,而是通过不停地重新布局子View的方式,来使得子 ...
- android波纹效果弹窗,Android自定义View实现波纹效果
Android自定义View实现波纹效果 时间:2017-05-27 来源:移动互联网学院 1.引言:随着Android智能手机的普及,Android应用得到了大力支持,而Android应用的 ...
- android 循环弹幕,Android自定义View实现弹幕效果
原标题:Android自定义View实现弹幕效果 在很多视频直播中都有弹幕功能,而安卓上没有简单好用的弹幕控件,本文介绍一个自定义弹幕view的demo. 效果图: 思路: 自定义Textitem类表 ...
- android下雨动画效果,Android 自定义View(二) 下雨效果
Rain.gif Android 自定义View(二) 下雨效果 一 实现思路, 雨点用线段表示,通过控制线段的大小和宽度来表示不同的线段. 一个雨点下雨的过程可以表示为一条直线,一次雨点在下雨的过程 ...
- android功能相同的view,Android自定义View实现扫描效果
本文实例为大家分享了Android自定义View实现扫描效果的具体代码,供大家参考,具体内容如下 演示效果如下: 实现内容: 1.控制动画是竖向或者横向 2.控制动画初始是从底部/左边开始,或者从上边 ...
- android 自定义布局 根据布局获取类,android自定义布局中的平滑移动之ViewGroup实现...
在android应用程序的开发过程中,相信我们很多人都想把应用的交互做的比较绚丽,比如让界面切换平滑的滚动,还有热度灰常高的伪3D等界面效果,通常情况下,系统提供的应用在特效这方面只能为我们提供简单的 ...
- Android 自定义 HorizontalScrollView 横向滑动效果
自从Gallery被谷歌废弃以后,Google推荐使用ViewPager和HorizontalScrollView来实现Gallery的效果.的确HorizontalScrollView可以实现Gal ...
- android 自定义加载动画效果,Android自定义View实现loading动画加载效果
项目开发中对Loading的处理是比较常见的,安卓系统提供的不太美观,引入第三发又太麻烦,这时候自己定义View来实现这个效果,并且进行封装抽取给项目提供统一的loading样式是最好的解决方式了. ...
最新文章
- python线程只能启动一次_python多线程只能运行一个线程的问题
- 进入编辑模式、vim命令模式、vim实践
- NDK,动态链接库,JNI
- 右键删除选中的行总提示rowIndex
- 激励员工的首席执行官以及他们的秘诀
- STM32中常用的C语言知识点,开始复习!
- Shell脚本之一 Shell脚本简介
- xss挖掘思路分享_新手指南 | permeate靶场漏洞挖掘思路分享
- Java:final和内部类
- 用JS 输出 正三角形
- 干掉hao123恶意植入浏览器
- ECMAScript 是什么?
- 纯jquery 前端导入 Excel数据 减少服务端压力
- 2021中国开源码力榜启动,寻找开源世界的超级玛丽
- 类的访问权限-public、private、protected
- flex中换行符的使用
- 记一次磕磕绊绊的组建跨区卷过程
- SASO认证辅导,没有SASO证书的产品会被沙特港口海关拒绝入境
- app如何增加推广功能 java_Java Web app如何实现这个功能蹦?诚心求指教。
- Revit 2019 64位安装教程【附软件及注册机下载地址】
热门文章
- linux系统每月定时重启,linux系统定时重启.doc
- python生成相似句子_4种方法计算句子相似度
- Unity SRP自定义渲染管线 -- 3.Lights
- Sublime Text官方文档 中英文版本
- 人生哲理---你值得借鉴
- RESTful API概述
- javascript . 05 json的组成、for...in 遍历对象、简单数据类型与复杂数据类型的传值与传址、内置对象...
- C++学习笔记(五)--指针、NULL、引用
- 大话设计模式之策略模式
- 【起航计划 011】2015 起航计划 Android APIDemo的魔鬼步伐 10 App-Activity-Reorder Activities 后退栈 Intent FLAG...