admin 发表于 2017-2-21 14:46:18

安卓实现下雨,飘雪,红包雨,碰撞球,自定义View 源码

安卓实现下雨,飘雪,红包雨,碰撞球,自定义View 源码。
目录:
  效果展示
  感想
  代码拆解
  开源地址
效果展示
  有没有兴趣继续看下去,直接看下"颜值"是第一步了。依次对应:下雨,飘雪,红包雨,碰撞球.


http://images2015.cnblogs.com/blog/690927/201701/690927-20170122232010785-141851348.jpg
http://images2015.cnblogs.com/blog/690927/201701/690927-20170122232045348-1505543503.jpg
http://images2015.cnblogs.com/blog/690927/201701/690927-20170122232112754-817148735.jpg
http://images2015.cnblogs.com/blog/690927/201701/690927-20170122232134566-1969545427.jpg

上面是图片,这里再发个视频链接:https://pan.baidu.com/s/1cAa4mq。
16年总算过去了,跟各位猿友有说句祝福吧,新的一年少加点班,身体健康,钱能赚多少就尽量赚。  之前看博客园,很多发纯感想的,都被推荐了好几天,说实话,我几乎一拉到底,就看有没有点↓的。  公司放假时间是在23号,也就明天了,大四实习到现在,一直很忙,这段时间也是我在编程层面上学到了比较多东西的阶段,上面的自定义View是Android的,完成它们是在实习上班期间挤出时间做的,最初的初衷是想把第四个碰撞球的效果加入到毕设里面,现在总算是实现了,过程遇到很多问题,球体的碰撞处理比想象中麻烦很多,前三个比较简单,也是微信,QQ的下表情原理吧,我猜应该是。。。  毕设最终也会开源,还请大家留意我 GitHbub,这将会是一个集合非第三方IM和仿朋友圈+golang制作服务端等等知识的社交APP。
代码拆解  如果你仔细看了上面的四张效果图,你会发现,前三张是没碰撞效果处理的,而第四张是具备的。这也是我要区分实现的效果,目的是为了表明,不仅可以不碰撞还可以选择碰。  同时,飘雪和红包雨,事实也仅仅是图片的不同,这就对了。你只需要修改图片就能实现完全自定义,爱下什么下什么。  言归正传,整体使用了 适配器设计模式。代码是很简练易懂的,可以看看我的目录结构。

  http://images2015.cnblogs.com/blog/690927/201701/690927-20170123000655207-1005766069.png  基类是一个暴露绘制和逻辑抽象方法的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,就可以了。开源地址:**** Hidden Message *****
安卓实现下雨,飘雪,红包雨,碰撞球,自定义View 源码


安卓实现下雨,飘雪,红包雨,碰撞球,自定义View 源码
http://bbs.jiandaima.com/thread-997-1-1.html


原始地址:
http://www.cnblogs.com/linguanh/p/6342099.html

kaneki880914 发表于 2017-2-22 13:26:11

不错,下载看看,。……来自于捡代码论坛

zhiku123 发表于 2017-4-27 14:07:23

这个先收藏,貌似以后能用,增加用户体验。

yang010002 发表于 2019-1-4 12:30:44

学习学习

TXswim 发表于 2019-3-26 09:49:16

wfsdasdasdd

小来同学 发表于 2019-12-23 15:13:18

很好 可以下载看看

nick2021 发表于 2021-4-27 14:31:12

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

- 本文出自捡代码论坛-最全的游戏源码下载技术网站!,原文地址:http://bbs.jiandaima.com/thread-997-1-1.html
页: [1]
查看完整版本: 安卓实现下雨,飘雪,红包雨,碰撞球,自定义View 源码