(本博客为原创: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. android 屏幕适配小结

    做android开发,开源嘛,满市场都是凌乱的机型,总少不了适配这样或那样的型号.在这里分享一下自己在开发中用到的方法. 首先要介绍一下drawable-mdpi.drawable-hdpi-1280 ...

  2. R.layout.main cannot be resolved解决办法

    今天敲的代码 package com.sharpandroid.activity; import android.R; import android.app.Activity; import andr ...

  3. css中元素水平垂直居中4种方法介绍

    table-cell轻松设置文本图片水平垂直居中 让一个元素垂直居中的思路:把这个元素的容器设置为table-cell,也就是具有表格单元格的特性,再使用vertical-align(这个属性对blo ...

  4. ecos资源探测器

    两种类型的资源探测器 xml文件资源探测器 目录资源探测器 系统内置的资源探测器(核心) 数据库定义目录资源探测器 -base_application_datable 关注dbschema servi ...

  5. 单应性(homography)变换的推导

    矩阵的一个重要作用是将空间中的点变换到另一个空间中.这个作用在国内的<线性代数>教学中基本没有介绍.要能形像地理解这一作用,比较直观的方法就是图像变换,图像变换的方法很多,单应性变换是其中 ...

  6. FZU 2101 大三的美好时光

    DP+离散化. 首先需要把时间离散化,剩下的就是简单DP. 还要判断哪些选修课与必修课时间有重合,我用了前缀和来处理. 注意:这题时间端点也不能重合. #include<cstdio> # ...

  7. 《javascript语言精粹》——第3章对象

    第三章:对象: 属性名字:可以是包括空字符串在内的任意字符串: 属性值:是除undefined值之外的任何值; [1].对象字面量: var obj={}; //空对象 var obj = new O ...

  8. LPC1768IAP(详解,有上位机)

    之前说了stm32的iap编程,今天天气真好,顺手就来说说lpc1788的iap编程(没看前面的请查看stm笔记下的内容) 首先是flash的算法,lpc1768并没有寄存器来让我们操作flash,他 ...

  9. ios 字体设计

    ref: http://ju.outofmemory.cn/entry/217705 ref:http://gold.xitu.io/entry/57958a41128fe10056be13b1 下面 ...

  10. Java中String的split()方法的一些需要注意的地方

    public String[] split(String regex, int limit) split函数是用于使用特定的切割符(regex)来分隔字符串成一个字符串数组,这里我就不讨论第二个参数( ...