安卓实现下雨,飘雪,红包雨,碰撞球,自定义View 源码。
目录:
效果展示
感想
代码拆解
开源地址
效果展示
有没有兴趣继续看下去,直接看下"颜值"是第一步了。依次对应:下雨,飘雪,红包雨,碰撞球.
16年总算过去了,跟各位猿友有说句祝福吧,新的一年少加点班,身体健康,钱能赚多少就尽量赚。 之前看博客园,很多发纯感想的,都被推荐了好几天,说实话,我几乎一拉到底,就看有没有点↓的。 公司放假时间是在23号,也就明天了,大四实习到现在,一直很忙,这段时间也是我在编程层面上学到了比较多东西的阶段,上面的自定义View是Android的,完成它们是在实习上班期间挤出时间做的,最初的初衷是想把第四个碰撞球的效果加入到毕设里面,现在总算是实现了,过程遇到很多问题,球体的碰撞处理比想象中麻烦很多,前三个比较简单,也是微信,QQ的下表情原理吧,我猜应该是。。。 毕设最终也会开源,还请大家留意我 GitHbub,这将会是一个集合非第三方IM和仿朋友圈+golang制作服务端等等知识的社交APP。
代码拆解 如果你仔细看了上面的四张效果图,你会发现,前三张是没碰撞效果处理的,而第四张是具备的。这也是我要区分实现的效果,目的是为了表明,不仅可以不碰撞还可以选择碰。 同时,飘雪和红包雨,事实也仅仅是图片的不同,这就对了。你只需要修改图片就能实现完全自定义,爱下什么下什么。 言归正传,整体使用了 适配器设计模式。代码是很简练易懂的,可以看看我的目录结构。
基类是一个暴露绘制和逻辑抽象方法的View子类,所有自定义View需要继承它。子类只需要关注自己要绘制什么,以及我要绘制的东西怎么去不断地改变,逻辑改变设计在一个 Thread 线程里面,采用 postInvalidate 通知 UI 刷新。 - <font size="5">/**
- * 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());
- }
- }
- }
- }
- }</font>
复制代码BaseView 已经是一个可以直接继承的父类了,如果仅仅只是绘制一些比较简单逻辑的自定义View,继承它足以,但是要实现上述的效果,还需要添加多一个抽象类,无论是雨景还是雪景,它们都是个体的集合,也就是说,我们需要一个"景"的抽象。 ShowView 是一个具备泛型的抽象类,它是景色的制作者,至于是什么景,由你来决定,也就是泛型的传入。例如,我要制造雨景,那么我就传入雨点,雪景就是雪块 - <font size="5">/**
- * 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));
- }
- }
- }</font>
复制代码
由于我们的景色里面的个体可能是各种各样,那么为了使他们都能具备一些公共的属性,需要再抽象一个基础的个体类,共不同的景色个体继承。 - <font size="5">/**
- * 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(); /** 运动 */
- }</font>
复制代码
OK,到这里基础的类都搞定了,为什么说是适配器模式呢,其实 BaseItem 就是 ViewHolder,ShowView 是 BaseAdapter,下面放下雨的Item 类和雨景。 注意注释,代码很简练易懂! - <font size="5">/**
- * 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;
- }
- }</font>
复制代码我要制作的雨,随机数可以自定义。
- <font size="5">/**
- * 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();
- }
- }</font>
复制代码到这里总结一下,如果你想实现自己的自定义View,不妨直接继承 BaseView,然后写你自己的 Item,就可以了。 开源地址:
安卓实现下雨,飘雪,红包雨,碰撞球,自定义View 源码
安卓实现下雨,飘雪,红包雨,碰撞球,自定义View 源码
http://bbs.jiandaima.com/thread-997-1-1.html
原始地址:
- http://www.cnblogs.com/linguanh/p/6342099.html
复制代码
|