(本博客为原创: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. PAT (Advanced Level) 1001. A+B Format (20)

    简单题. #include<iostream> #include<cstring> #include<cmath> #include<algorithm> ...

  2. Blog`s CSS

    #div_digg { position: fixed; bottom: 10px; width: 50px; right: 50px; filter: alpha(opacity=20); opac ...

  3. jquery核心功能分析

    作者:zccst 核心功能包括: jQuery是如何定义的,如何调用的,如何扩展的.掌握核心方法是如何实现的,是理解jQuery源码的关键.这里理解了一切豁然开朗. 1,如何定义,即入口 // Def ...

  4. Keil STM32调试,使用ST-Link下载程序时提示“flash timeout.reset the target and try it again”

    参考: 很郁闷,买来没多久的 STM32F4-DISCOVERY 就挂了? STM32F103RB   Jlink调试的时候出现flash timeout.reset the target and t ...

  5. 第一章 Slenium2-Java 自动化测试基础

    都是一些最基础的知识点. 一:软件测试分类 1)单元测试:单元测试(或模块测试)是对程序中的单个子程序或具有独立功能的代码段进行测试的过程.2)集成测试:集成测试是在单元测试的基础上,先通过单元模块组 ...

  6. 安卓能用的modebus CRC16计算,附上对应的C语言的CRC16(转)

    源:安卓能用的modebus CRC16计算,附上对应的C语言的CRC16 “源”即是原文地址,想了解作都更多文章及思想请移步到“源”.转过只是为了本人感兴趣的文章查找方便. 正文: 最近写安卓串口通 ...

  7. LPC2478的硬件IIC使用

    LPC2478的IIC使用 LPC2478带有三个IIC接口,每个IIC都可以工作在主机或者从机模式下,LPC的IIC的架构是一种状态机的形式,在不同的的时间做不同的工作之后有不同的状态来表示, 简单 ...

  8. memcache和memcached之间的区别和联系

    memcache和memcached区别: Memcache是什么?Memcache是一个自由和开放源代码.高性能.分配的内存对象缓存系统.用于加速动态web应用程序,减轻数据库负载.它可以应对任意多 ...

  9. win7 下安装 ubuntu 16.04双系统

    Ubuntu 每年发布两个版本,目前最新正式版版本也升到了 16.04.Ubuntu 16.04 开发代号为"Xenial Xerus",为第六个长期支持(LTS)版本,其主要特色 ...

  10. UVa 11456 - Trainsorting

    题目大意:给一个车辆到达车站的序列(按时间先后),可以对车辆进行以下处理:插在队首.插在队尾或者拒绝进站.车站内的车辆必须按照重量大小从大到小排列,问车站内最多能有多少辆车辆? 假设车i是第一个进站, ...