(本博客为原创:http://www.cnblogs.com/linguanh/)

目录:

  效果展示

  感想

  代码拆解

  开源地址

效果展示

  有没有兴趣继续看下去,直接看下"颜值"是第一步了。依次对应:下雨,飘雪,红包雨,碰撞球

   

  上面是图片,这里再发个视频链接:http://pan.baidu.com/s/1miyPn76

感想

  16年总算过去了,跟各位猿友有说句祝福吧,新的一年少加点班,身体健康,钱能赚多少就尽量赚。

  之前看博客园,很多发纯感想的,都被推荐了好几天,说实话,我几乎一拉到底,就看有没有点↓的。

  公司放假时间是在23号,也就明天了,大四实习到现在,一直很忙,这段时间也是我在编程层面上学到了比较多东西的阶段,上面的自定义View是Android的,完成它们是在实习上班期间挤出时间做的,最初的初衷是想把第四个碰撞球的效果加入到毕设里面,现在总算是实现了,过程遇到很多问题,球体的碰撞处理比想象中麻烦很多,前三个比较简单,也是微信,QQ的下表情原理吧,我猜应该是。。。

  毕设最终也会开源,还请大家留意我 GitHbub,这将会是一个集合非第三方IM和仿朋友圈+golang制作服务端等等知识的社交APP。

代码拆解

  如果你仔细看了上面的四张效果图,你会发现,前三张是没碰撞效果处理的,而第四张是具备的。这也是我要区分实现的效果,目的是为了表明,不仅可以不碰撞还可以选择碰。

  同时,飘雪和红包雨,事实也仅仅是图片的不同,这就对了。你只需要修改图片就能实现完全自定义,爱下什么下什么。

  言归正传,整体使用了 适配器设计模式。代码是很简练易懂的,可以看看我的目录结构。

  

  基类是一个暴露绘制和逻辑抽象方法的View子类,所有自定义View需要继承它。子类只需要关注自己要绘制什么,以及我要绘制的东西怎么去不断地改变,逻辑改变设计在一个 Thread 线程里面,采用 postInvalidate 通知 UI 刷新。

 /**
* Created by LinGuanHong on 2017/1/15.
*
* My GitHub : https://github.com/af913337456/
*
* My Blog : http://www.cnblogs.com/linguanh/
*
*/ public abstract class BaseView extends View { protected String TAG = "zzzzz";
private static final int sleepTime = 30;
private RefreshThread refreshThread = null; public BaseView(Context context) {
super(context);
} public BaseView(Context context, AttributeSet attrs) {
super(context, attrs);
} public abstract void drawSub(Canvas canvas); public abstract void baseInit(int width,int height); public abstract void logic(); @Override
protected final void onDraw(Canvas canvas) {
if(refreshThread == null){
refreshThread = new RefreshThread();
refreshThread.start();
}else{
drawSub(canvas);
}
} @Override
protected void onDetachedFromWindow() {
running = false;
super.onDetachedFromWindow();
} private boolean running = true;
private class RefreshThread extends Thread{ @Override
public void run() {
baseInit(getWidth(),getHeight());
while (running){
try{
logic();
postInvalidate();
Thread.sleep(sleepTime);
}catch (Exception e){
Log.d(TAG,e.toString());
}
}
}
}
}

   BaseView 已经是一个可以直接继承的父类了,如果仅仅只是绘制一些比较简单逻辑的自定义View,继承它足以,但是要实现上述的效果,还需要添加多一个抽象类,无论是雨景还是雪景,它们都是个体的集合,也就是说,我们需要一个"景"的抽象。

  ShowView 是一个具备泛型的抽象类,它是景色的制作者,至于是什么景,由你来决定,也就是泛型的传入。例如,我要制造雨景,那么我就传入雨点,雪景就是雪块

 /**
* Created by LinGuanHong on 2017/1/15.
*
* My GitHub : https://github.com/af913337456/
*
* My Blog : http://www.cnblogs.com/linguanh/
*
*/ public abstract class ShowView<T extends BaseItem> extends BaseView { protected List<T> itemList = new ArrayList<>();
protected int size = 1; public ShowView(Context context) {
super(context);
} /** 子类实现布局必须要重写这个构造方法 */
public ShowView(Context context, AttributeSet attrs) {
super(context, attrs);
} @Override
public void drawSub(Canvas canvas) {
for(T t:itemList){
t.draw(canvas);
}
} @Override
public void logic() {
beforeLogicLoop();
for(T t:itemList){
t.move();
}
} public abstract void beforeLogicLoop();
public abstract T getItem(int width, int height,Resources resources);
public abstract int getCount(); @Override
public void baseInit(int width, int height) {
size = getCount();
Resources resources = getResources();
for(int i = 0; i< size; i++){
itemList.add(getItem(width,height,resources));
}
} }

  由于我们的景色里面的个体可能是各种各样,那么为了使他们都能具备一些公共的属性,需要再抽象一个基础的个体类,共不同的景色个体继承。

 /**
* Created by LinGuanHong on 2017/1/15.
*
* My GitHub : https://github.com/af913337456/
*
* My Blog : http://www.cnblogs.com/linguanh/
*
* 公共的属性和行为
*
*/ public abstract class BaseItem { protected int width,height; /** 景内宽高 */
protected Resources resources; public BaseItem(int width,int height,Resources resources){
this.width = width;
this.height = height;
this.resources = resources;
} public abstract void draw(Canvas canvas); /** 显示 */
public abstract void move(); /** 运动 */ }

  OK,到这里基础的类都搞定了,为什么说是适配器模式呢,其实 BaseItem 就是 ViewHolder,ShowView 是 BaseAdapter,下面放下雨的Item 类和雨景。

  注意注释,代码很简练易懂!

 /**
* Created by LinGuanHong on 2017/1/15.
*
* 造雨,造多少个,160个,具体是什么雨,交给 item 实现
*
*/ public class RainView extends ShowView<RainItem> { public RainView(Context context) {
super(context);
} public RainView(Context context, AttributeSet attrs) {
super(context, attrs);
} @Override
public void beforeLogicLoop() { } @Override
public RainItem getItem(int width, int height, Resources resources) {
return new RainItem(width,height,resources); /** 要造的雨,是什么雨就在这里传入 */
} @Override
public int getCount() { /** 要制作的雨数目 */
return 160;
}
}

  我要制作的雨,随机数可以自定义。

 /**
* Created by LinGuanHong on 2017/1/15.
*/ public class RainItem extends BaseItem { private float opt;
private int sizeX,sizeY; /** 充当角度 */
private int startX,startY,stopX,stopY;
private Paint paint;
private Random random; public RainItem(int width, int height, Resources resources) {
super(width,height,resources);
init();
loopInit();
} @Override
public void move() {
startX += sizeX * opt;
stopX += sizeX * opt; startY += sizeY * opt;
stopY += sizeY * opt;
if(startY > height){
loopInit();
}
} @Override
public void draw(Canvas canvas) {
Log.d("zzzzz","drawView "+startX+" "+startY+" "+stopX+" "+stopY);
canvas.drawLine(startX,startY,stopX,stopY,paint);
} private void loopInit(){
sizeX = 1 + random.nextInt(10);
sizeY = 10 + random.nextInt(20); startX = random.nextInt(width );
startY = random.nextInt(height); opt = 0.2f + random.nextFloat(); stopX = startX + sizeX;
stopY = startY + sizeY;
} private void init(){
paint = new Paint(Paint.ANTI_ALIAS_FLAG); /** 抗锯齿 */
paint.setColor(0xffffffff); /** a,r,g,b 255,255,255,255 */ random = new Random();
} }

  到这里总结一下,如果你想实现自己的自定义View,不妨直接继承 BaseView,然后写你自己的 Item,就可以了。

开源地址

  我的:https://github.com/af913337456/XView

  

2017了,回家前 "年末" 分享:下雨,飘雪,红包雨,碰撞球,自定义View的更多相关文章

  1. 2017年排名前15的数据科学python库

    2017年排名前15的数据科学python库 2017-05-22 Python程序员 Python程序员 Python程序员 微信号 pythonbuluo 功能介绍 最专业的Python社区,有每 ...

  2. Android自定义View前传-View的三大流程-Measure

    Android自定义View前传-View的三大流程-Measure 参考 <Android开发艺术探索> https://developer.android.google.cn/refe ...

  3. 3D语音天气球(源码分享)——创建可旋转的3D球

    开篇废话: 在9月份时参加了一个网站的比赛,比赛的题目是需要使用第三方平台提供的服务做出创意的作品. 于是我选择使用语音服务,天气服务,Unity3D,Android来制作一个3D语音天气预报,我给它 ...

  4. android 自定义view 前的基础知识

    本篇文章是自己自学自定义view前的准备,具体参考资料来自 Android LayoutInflater原理分析,带你一步步深入了解View(一) Android视图绘制流程完全解析,带你一步步深入了 ...

  5. 2017最新的Python教程分享

    Python在数据科学盛行的今天,其易于阅读和编写的特点,越来越受编程者追捧.在IEEE发布的2017年编程语言排行榜中,Python也高居首位.如果你有学Python的计划,快来看看小编分享的Pyt ...

  6. 2017埙箫简谱清单分享(附音频Demo)

    前言 习箫五载,略有所获,皆在坚持. 本博文记录旨在记录练习过程中所录制的Demo以供自省.自娱.自乐,同时记录.分享简谱与箫友(目前为简谱,日后学会线谱后会添加相应谱子分类). 简谱 &&a ...

  7. 回家前的挣扎——SQLite增删改查

    引言 最后一天,公司就两个人,也不知道弄点什么,就在网上找了Sqlite的文档,看了看,这里也是现学现卖,给自己找点事做,感觉时间过得还是比较快的,不然焦急等待,滋味不好受啊. SQLite简介 SQ ...

  8. 2015年末分享:利用RS修改用户密码

    马上就要2016农历新年了,送点什么给大家呢?我觉得还是分享点技术吧.前不久用户在抱怨为什么登录Cognos Connection的密码不能让我们自己改?相信Cognos开发的很多人知道,Cognos ...

  9. 简单跳转到微信分享,基于libWeiChatSDK 和简单的自定义UIActivityViewController

    一.自定义UIActivity: 如果想要自定义UIActivity必须知道UIActivityViewController.首先这个类主要是用于接受字符串,RUL类型和图片类型的数据用于分享和操作的 ...

随机推荐

  1. Milk Pails

    Milk Pails 题目描述 Farmer John has received an order for exactly M units of milk (1≤M≤200) that he need ...

  2. windows矢量字体点阵数据的提取(转)

    源:windows矢量字体点阵数据的提取 问题参考:windows api 获取字库点阵的问题 1.提取原理 在windows系统当中提取矢量字体的字模有很多方法,下面介绍一种利用GetGlyphOu ...

  3. Spring mvc 返回json格式 - 龙企阁 - 博客频道 - CSDN.NET

    第一次使用spring mvc ,在此也算是记录一下以防忘记,希望有经验的朋友指出不足的地方 一.使用maven管理jar. <dependency> <groupId>org ...

  4. WEB前端资源集(一)

    做前端已经一年了,开发中换过很多开发工具,遇到bug到处求解,以及自学时到处找相关文章及教程,所以经过这么多的风波,我总结了一些对大家有帮助的网站,主题也将长期更新. 资源网站篇 CSDN:全球最大中 ...

  5. jpg转bmp(使用libjpeg)

    源: jpg转bmp(使用libjpeg) [转]JPEG压缩原理 bmp转jpg(使用libjpeg)

  6. Xcode7 新添旧版模拟器方法

    http://blog.csdn.net/xiaoluodecai/article/details/48649697 更新了最新的Xcode后,总是仅保留最新的模拟器,如iOS9.0,如果此时想添加以 ...

  7. iOS 的三种自建证书方法https请求相关配置

    如果你的app服务端安装的是SLL颁发的CA,可以使用系统方法直接实现信任SSL证书,关于Apple对SSL证书的要求请参考:苹果官方文档CertKeyTrustProgGuide 这种方式不需要在B ...

  8. PHP 判断几秒前,几分钟,几小时前

    PHP 对于时间的过了多久的判断,几秒前,几分钟前,几小时前,$time = strtotime("2017-01-15 14:42:00"); $time = strtotime ...

  9. IOS FMDB模糊查询

    http://blog.sina.com.cn/s/blog_9630f1310101fx1d.html /查询记录 -(NSArray*)selectitemDream_desc:(JiemengS ...

  10. ajax--2017年1月15日

    听说点六下就能复制了? ajax: 一般处理程序(数据接口):ashx 跨语言传递数据:xml: 结构不清晰 代码量比较大 查找起来比较费事 非面向对象结构 json: 结构清晰 代码量相对较小 面向 ...