新手自定义view练习实例之(二) 波浪view
本系列是为新手准备的自定义view练习项目(大牛请无视),相信在学习过程中,想学自定义view又无从下手,不知道做什么。本系列为新手提供了一系列自定义view的简单实例。看过理解之后,自己实现,相信会有很大提高。
转载请注明本篇出处:http://blog.csdn.net/wingichoy/article/details/50460213
继续来本系列的第二篇,启发是吃口香糖看到了包装纸,觉得挺好看,就想画一个出来#职业病#,本次的目标是做一个波浪形状的view,可以是尖角,也可以是圆角。
那么老规矩,上效果图:
聪明的你一眼就看出来了,不就是个矩形加好多三角嘛。答对了,就是这么简单,事不宜迟,快拿起武器动手练一练。毕竟程序员的秘诀就是“无他,唯手熟尔”。
首先,新建一个类 起名为WaveView 继承自View,重写他的构造方法,在第三个构造方法里获取自定义属性。
public WaveView(Context context) {
this(context, null);
}
public WaveView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public WaveView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.WaveView,defStyleAttr,0);
mWaveCount = a.getInt(R.styleable.WaveView_waveCount,10);
mWaveWidth = a.getInt(R.styleable.WaveView_waveWidth,20);
mMode = a.getInteger(R.styleable.WaveView_mode,-2);
mColor = a.getColor(R.styleable.WaveView_android_color,Color.parseColor("#2C97DE"));
}
自定义属性如下 attr.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="WaveView">
<attr name="waveCount" format="integer"/>
<attr name="waveWidth" format="integer"/>
<attr name="android:color"/>
<attr name="mode" >
<enum name = "circle" value="-1"/>
<enum name = "triangle" value = "-2"/>
</attr>
</declare-styleable>
</resources>
这些都没有什么好说的,你一定已经轻车熟路。
然后重写他的onMeasure() 来告诉系统这个view有多大。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//矩形宽度为view的80%
if (widthMode == MeasureSpec.EXACTLY) {
mWidth = widthSize; mRectWidth = (float) (mWidth * 0.8); //如果是wrap_content 直接给一个定值
}else if(widthMode == MeasureSpec.AT_MOST){
mWidth = PxUtils.dpToPx(300,mContext); mRectWidth = (float) (mWidth * 0.8); } //矩形高度为view的80%
if (heightMode == MeasureSpec.EXACTLY) {
mHeight = heightSize;
mRectHeight = (float) (mHeight * 0.8);
//如果是wrap_content 直接给一个定值
}else if(heightMode == MeasureSpec.AT_MOST){ mHeight = PxUtils.dpToPx(200,mContext); mRectHeight = (float) (mHeight * 0.8);
} setMeasuredDimension(mWidth, mHeight);
}
准备工作大致已经完成,接下来开始绘图。首先 画一个矩形。
这个矩形让他处于view的中间,看图:
由图可知, 矩形的左上坐标为 padding ,padding 矩形的右下坐标为padding +mRectWidth, padding + mRectHeight
其中padding 为 (mWidth - mRectWidth)/2 注意这里只是左右padding 为了简易 就不计算上下padding了。
所以我们先将矩形绘制出来,如下图: 可以看到左右padding是相等的,上下不等,这是因为上面只计算了左右padding
protected void onDraw(Canvas canvas) {
Paint p = new Paint();
p.setColor(mColor);
//计算每个三角形的高
mWaveHeight = mRectHeight / mWaveCount;
//绘制矩形
//计算padding
float padding = ((mWidth - mRectWidth) / 2);
canvas.drawRect(padding, padding, mRectWidth + padding, mRectHeight + padding, p);
绘制矩形完毕,需要来一个判断,判断当前模式是圆角还是尖角
if(mMode == MODE_TRIANGLE) {}else{}
我们首先来绘制尖角,还记得上一篇泡泡窗的那个三角吗,我们只要画多次不就形成波浪了吗,所以用循环就可以搞定。坐标计算如下:
矩形的右上角暂定为 StartX,StartY 三角形的宽度为 mWaveWidth 高度为 mWaveHeight 那么还是用path来画,首先将path MoveTo startX,startY 然后计算得出各个坐标,在用一个i来代表第几个三角形来做循环,代码如下:
if(mMode == MODE_TRIANGLE) {
//绘制右边的波浪
float startX = padding + mRectWidth;
float startY = padding;
Path path = new Path();
path.moveTo(startX, startY);
for (int i = 0; i < mWaveCount; i++) {
path.lineTo(startX + mWaveWidth, startY + i * mWaveHeight + (mWaveHeight / 2));
path.lineTo(startX, startY + mWaveHeight * (i + 1));
}
path.close();
canvas.drawPath(path, p);
只要把上面的坐标带入进去即可,那么左边的波浪只是改变了一个x坐标的加减值,也很简单。
//绘制左边的波浪
startX = padding;
startY = padding;
path.moveTo(startX, startY);
for (int i = 0; i < mWaveCount; i++) {
path.lineTo(startX - mWaveWidth, startY + i * mWaveHeight + (mWaveHeight / 2));
path.lineTo(startX, startY + mWaveHeight * (i + 1));
} path.close();
canvas.drawPath(path, p);
这样便完成了整个波浪view的绘制。本篇就到此结束了。
别急,我没忘圆形模式,这里给大家留个家庭作业,大家下去根据这个思路自己把圆形波浪画出来吧~ 毕竟只有多练,才能提高
本项目github地址:点击打开链接 ,求关注,求评论,求star
新手自定义view练习实例之(二) 波浪view的更多相关文章
- Android View框架总结(二)View焦点
请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52263256 前言:View框架写到第六篇,发现前面第二篇竟然没有, ...
- 【朝花夕拾】Android自定义View篇之(一)View绘制流程
前言 转载请申明转自[https://www.cnblogs.com/andy-songwei/p/10955062.html]谢谢! 自定义View.多线程.网络,被认为是Android开发者必须牢 ...
- Autodesk View and Data API二次开发学习指南
什么是View and Data API? 使用View and Data API,你可以轻松的在网页上显示大型三维模型或者二维图纸而不需要安装任何插件.通过View and Data API,你可以 ...
- python学习_数据处理编程实例(二)
在上一节python学习_数据处理编程实例(二)的基础上数据发生了变化,文件中除了学生的成绩外,新增了学生姓名和出生年月的信息,因此将要成变成:分别根据姓名输出每个学生的无重复的前三个最好成绩和出生年 ...
- C语言库函数大全及应用实例十二
原文:C语言库函数大全及应用实例十二 [编程资料]C语言库函数大全及应用实例十二 函数名: setrgbpalette ...
- java学习--自定义类的实例的大小比较和排序
我们知道Object类有一个equals方法,用于比较两个对象是否相等 我们只要在自定义类中重写了equals方法(若不重写就是比较两个实例的地址,相当于==)就可以用来比较该类的两个实例是否相等 问 ...
- 【微信小程序】自定义模态框实例
原文链接:https://mp.weixin.qq.com/s/23wPVFUGY-lsTiQBtUdhXA 1 概述 由于官方API提供的显示模态弹窗,只能简单地显示文字内容,不能对对话框内容进行自 ...
- Qt5MV自定义模型与实例浅析
1. Model/View结构 这种结构,其实就是将界面组件与所编辑的数据分离开来,又通过数据源的方式连接起来,相当于解耦,视图层只关心显示和与用户交互,而数据层负责与实际的数据进行通信,并为视图组件 ...
- SQL Server 2008 数据库镜像部署实例之二 配置镜像,实施手动故障转移
SQL Server 2008 数据库镜像部署实例之二 配置镜像,实施手动故障转移 上一篇文章已经为配置镜像数据库做好了准备,接下来就要进入真正的配置阶段 一.在镜像数据库服务器上设置安全性并启动数据 ...
随机推荐
- [ExtJS6学习笔记]Ext JS6主题系列 (Classic工具包)
本文作者:苏生米沿 本文地址:http://blog.csdn.net/sushengmiyan/article/details/50186709 翻译来源:http://docs.sencha.co ...
- 浅析深度学习mini_batch的BP反传算法
在深度学习中,如果我们已经定义了网络,输入,以及输出,那么接下来就是损失函数,优化策略,以及一般由框架完成的BP反传.这篇博文我们主要探讨一下深度的BP反传算法(以梯度下降为例),尤其是mini_ba ...
- springMVC源码分析--HttpRequestHandlerAdapter(四)
上一篇博客springMVC源码分析--HandlerAdapter(一)中我们主要介绍了一下HandlerAdapter接口相关的内容,实现类及其在DispatcherServlet中执行的顺序,接 ...
- Web自动化框架LazyUI使用手册(5)--模板工程:LazyUI-template详解
概述: LazyUI-template: 提供Maven管理的,基于Spring+Testng的,包含常用浏览器driver的,方便连接各种数据库的java模板工程,并提供以百度搜索为例的第一个测试用 ...
- 长度为N的数组乱序存放着0带N-1.现在只能进行0与其他数的swap操作,请设计并实现排序,必须通过交换实现排序。
void sort(int* arr, int len) { if (!arr) { return; } for (int i = 1; i < len; ++i) { while (arr[0 ...
- TeamView 无法捕捉画面问题的解决办法
teamview是个非常不错的远程协助软件,你要是在项目中还搞个QQ远程协助啥的就显的非常不专业了. 在teamview连接远程后,看到的是一片漆黑,中间框提示"现在无法捕捉画面.这可能是由 ...
- FORM开发两种方式实现动态LIST
方法一:常规的,也是网上比较常见的 1.将目标ITEM的子类信息设置为List,不需要添加列表中元素,不需要初始值. 2.新建一个Procedure,代码如下: PROCEDURE basis_lis ...
- 乐观的并发策略——基于CAS的自旋
悲观者与乐观者的做事方式完全不一样,悲观者的人生观是一件事情我必须要百分之百完全控制才会去做,否则就认为这件事情一定会出问题:而乐观者的人生观则相反,凡事不管最终结果如何,他都会先尝试去做,大不了最后 ...
- ROS连接ABB机械臂调试详细教程-ROS(indigo)和ABB RobotStudio 6.03.02-
在ROS industrial介绍中,给出了ROS和常用机械臂的连接方式.具体信息可以参考:http://wiki.ros.org/Industrial ROS连接ABB机械臂调试详细教程-ROS(i ...
- RxJava在Android中使用场景详解
RxJava 系列文章 <一,RxJava create操作符的用法和源码分析> <二,RxJava map操作符用法详解> <三,RxJava flatMap操作符用法 ...