zoukankan      html  css  js  c++  java
  • 54、Android 粒子效果之雨(下雨的效果)

    核心内容:
    1.绘制下雨场景的个体、雨点(直线)
    2.让直线动起来
    3.处理边界问题
    4.构造雨点对象
    5.雨点大小设置
    6.速度设置和角度设置等
    7.添加多个雨点
    8.抽离可以在 XML 中影响的属性
    9.在代码中解析样式属性并使用其控制雨点变化

    import android.content.Context;
    import android.graphics.Canvas;
    import android.util.AttributeSet;
    import android.view.View;
    
    /**
     * 基类
     */
    public abstract class BaseView extends View {
        private MyThread thread;
        private boolean running = true;
    
        public BaseView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public BaseView(Context context) {
            super(context);
        }
    
        protected abstract void drawSub(Canvas canvas);
        protected abstract void logic();
        protected abstract void init();
        
        class MyThread extends Thread {
            @Override
            public void run() {
                init();
                while (running) {
                    logic();
                    postInvalidate();
                    try {
                        Thread.sleep(30);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        @Override
        protected final void onDraw(Canvas canvas) {
            if (thread == null) {
                thread = new MyThread();
                thread.start();
            } else {
                drawSub(canvas);
            }
        }
    
        @Override
        protected void onDetachedFromWindow() {
            running = false;
            super.onDetachedFromWindow();
        }
    
    }

    1)简单描述单个雨点的行为。

    绘制下雨场景的个体,雨点(直线);

    让直线动起来;

    处理边界问题;

    1 <com.rain.RainView
    2         android:layout_width="match_parent"
    3         android:layout_height="match_parent"
    4         android:background="#ff000000"
    5        />
     1   import android.content.Context;
     2 import android.graphics.Canvas;
     3 import android.graphics.Paint;
     4 import android.util.AttributeSet;
     5 
     6 public class RainView extends BaseView {
     8     private float startX;
     9     private float startY;
    10     private float stopX;
    11     private float stopY;
    12     private float sizeX;
    13     private float sizeY;
    14     private Paint paint;
    15 
    16     public RainView(Context context, AttributeSet attrs) {
    17         super(context, attrs);
    19         // 角度。
    20         sizeX = 10;
    21         sizeY = 30;
    22         // 以下是 初始化直线的坐标。
    23         startX = 100;
    24         startY = 0;
    25         // 改变 角度的直线。
    26         stopX = startX + sizeX;
    27         stopY = startY + sizeY;
    28 
    29         paint = new Paint();
    30         // 把直线 设置成白色。
    31         paint.setColor(0xffffffff);
    32     }
    33 
    34     public RainView(Context context) {
    35         super(context);
    36     }
    37 
    38     @Override
    39     protected void drawSub(Canvas canvas) {
    40         // 绘制一条直线
    41         canvas.drawLine(startX, startY, stopX, stopY, paint);
    42     }
    43 
    44     @Override   /* 让直线动起来 **/ 
    45     protected void logic() {
    46 
    47         //倍率,通过倍率来改变速度。
    48         float opt = 0.5f;
    49 
    50         startX += sizeX * opt;
    51         stopX += sizeX * opt;
    52 
    53         startY += sizeY * opt;
    54         stopY += sizeY * opt;
    55 
    56         // 当直线走出屏幕的时候,变为初始位置。
    57         if (startY > getHeight()) {
    58             startX = 100;
    59             startY = 0;
    60             stopX = startX + 10;
    61             stopY = startY + 30;
    62         }
    63     }
    64 
    65 }

    2)完善雨点行为和构造下雨场景。

    构造雨点对象;

    雨点大小设置;

    速度设置;

    角度设置等 添加多个雨点;

    1 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    2     android:layout_width="match_parent"
    3     android:layout_height="match_parent" >
    4     <com.rain.RainView
    5         android:layout_width="match_parent"
    6         android:layout_height="match_parent"
    7         android:background="#ff000000" />
    8 </FrameLayout>
     1 public class RainView extends BaseView {
     2     // 多个 “雨点” 对象。
     3     private ArrayList<RainItem> list = new ArrayList<RainItem>();
     4     private int rainNum = 80;  // “雨点”个数。
     5 
     6     public RainView(Context context, AttributeSet attrs) {
     7         super(context, attrs);
     8     }
     9 
    10     public RainView(Context context) {
    11         super(context);
    12     }
    13 
    14     @Override
    15     protected void drawSub(Canvas canvas) {
    16         for (RainItem item : list) {
    17             item.draw(canvas);
    18         }
    19     }
    20 
    21     @Override
    22     protected void logic() {
    23         for (RainItem item : list) {
    24             item.move();
    25         }
    26     }
    27 
    28     @Override
    29     protected void init() {
    30         for (int i = 0; i < rainNum; i++) {
    31             RainItem item = new RainItem(getWidth(), getHeight());
    32             list.add(item);
    33         }
    34     }
    35 
    36 }
     1 /**
     2  * 抽象出一个 雨点 的类
     3  */
     4 public class RainItem {
     5     private int width;
     6     private int height;
     7 
     8     private float startX;
     9     private float startY;
    10     private float stopX;
    11     private float stopY;
    12     private float sizeX;
    13     private float sizeY;
    14     private float opt;  // 速率
    15     private Paint paint;
    16     private Random random;  // 随机数
    17 
    18     // 自定义“雨点”的 宽 和 高
    19     public RainItem(int width, int height) {
    20         this.width = width;
    21         this.height = height;
    22         init();
    23     }
    24 
    25     private void init() {
    26         random = new Random();
    27         // 角度 "X和Y随机。
    28         sizeX = 1 + random.nextInt(10);
    29         sizeY = 10 + random.nextInt(20);
    30         // "雨点"X和Y随机位置。
    31         startX = random.nextInt(width);
    32         startY = random.nextInt(height);
    33         stopX = startX + sizeX;
    34         stopY = startY + sizeY;
    35         // 速率随机。
    36         opt = 0.2f + random.nextFloat();
    37         paint = new Paint();
    38         
    39         paint.setColor(0xffffffff);
    40     }
    41 
    42     public void draw(Canvas canvas) {
    43         canvas.drawLine(startX, startY, stopX, stopY, paint);
    44     }
    45 
    46     public void move() {
    47         startX += sizeX * opt;
    48         stopX += sizeX * opt;
    49 
    50         startY += sizeY * opt;
    51         stopY += sizeY * opt;
    52 
    53         if (startY > height) {
    54             init();
    55         }
    56     }
    57 
    58 }

    3)在xml中定义可以控制下雨的属性。

    抽离可以在xml中影响的属性;

    在代码中解析样式属性并使用其控制雨点变化;

    res/values/attrs.xml

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <resources>
     3     <declare-styleable name="RainView">
     4         <!-- 雨点数量 -->
     5         <attr name="rainNum" format="integer"/>
     6         <!-- 雨点大小 -->
     7         <attr name="size" format="integer"/>
     8         <!-- 雨点颜色 -->
     9         <attr name="rainColor" format="integer"/>
    10         <!-- 雨点颜色随机 -->
    11         <attr name="randColor" format="boolean"/>
    12     </declare-styleable>
    13 </resources>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:rain="http://schemas.android.com/apk/res/com.jikexueyuan.rain"
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <com.rain.RainView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#ff000000"
            rain:rainNum="50"
            rain:size="20"
            rain:rainColor="0xff00ff00"
            rain:randColor="true"/>
    </FrameLayout>
     1 public class RainView extends BaseView {
     3     // 多个 “雨点” 对象。
     4     private ArrayList<RainItem> list = new ArrayList<RainItem>();
     5     // 以下4个值,均为默认值。
     6     private int rainNum = 80;  // “雨点”个数。
     7     private int size;
     8     private int rainColor;
     9     private boolean randColor;
    10 
    11     public RainView(Context context, AttributeSet attrs) {
    12         super(context, attrs);
    13 
    14         // 加载,解析 样式属性。res/values/attrs.xml
    15         TypedArray ta = context.obtainStyledAttributes(attrs,
    16                 R.styleable.RainView);
    17 
    18         rainNum = ta.getInteger(R.styleable.RainView_rainNum, 80);
    19         size = ta.getInteger(R.styleable.RainView_size, 20);
    20         rainColor = ta.getInteger(R.styleable.RainView_rainColor, 0xffffffff);
    21         randColor = ta.getBoolean(R.styleable.RainView_randColor, false);
    22         ta.recycle();
    23     }
    24 
    25     public RainView(Context context) {
    26         super(context);
    27     }
    28 
    29     @Override
    30     protected void drawSub(Canvas canvas) {
    31         for (RainItem item : list) {
    32             item.draw(canvas);
    33         }
    34     }
    35 
    36     @Override
    37     protected void logic() {
    38         for (RainItem item : list) {
    39             item.move();
    40         }
    41     }
    42 
    43     @Override
    44     protected void init() {
    45         for (int i = 0; i < rainNum; i++) {
    46             RainItem item = new RainItem(getWidth(), getHeight(), size,
    47                     rainColor, randColor);
    48             list.add(item);
    49         }
    50     }
    51 
    52 }
     1 /**
     2  * 抽象出一个 雨点 的类
     3  */
     4 public class RainItem {
     5 
     6     private int width;
     7     private int height;
     8 
     9     private float startX;
    10     private float startY;
    11     private float stopX;
    12     private float stopY;
    13     private float sizeX;
    14     private float sizeY;
    15     private float opt;  // 速率
    16     private Paint paint;
    17     private Random random;  // 随机数
    18 
    19     private int size = 20;
    20     private int color;
    21     // 随机 雨点颜色 
    22     private boolean randColor = false;;
    23 
    24     // 自定义“雨点”的 宽 和 高
    25     public RainItem(int width, int height) {
    26         this.width = width;
    27         this.height = height;
    28         init();
    29     }
    30 
    31     public RainItem(int width, int height, int size) {
    32         this.size = size;
    33         this.width = width;
    34         this.height = height;
    35         init();
    36     }
    37 
    38     public RainItem(int width, int height, int size, int color) {
    39         this.color = color;
    40         this.size = size;
    41         this.width = width;
    42         this.height = height;
    43         init();
    44     }
    45 
    46     public RainItem(int width, int height, int size, int color,
    47             boolean randColor) {
    48         this.randColor = randColor;
    49         this.color = color;
    50         this.size = size;
    51         this.width = width;
    52         this.height = height;
    53         init();
    54     }
    55 
    56     private void init() {
    57         random = new Random();
    58         // 角度 "X和Y随机。
    59         sizeX = 1 + random.nextInt(size / 2);
    60         sizeY = 10 + random.nextInt(size);
    61         // "雨点"X和Y随机位置。
    62         startX = random.nextInt(width);
    63         startY = random.nextInt(height);
    64         stopX = startX + sizeX;
    65         stopY = startY + sizeY;
    66         // 速率随机。
    67         opt = 0.2f + random.nextFloat();
    68         paint = new Paint();
    69         if (randColor) {
    70             // 颜色随机值。
    71             int r = random.nextInt(256);
    72             int g = random.nextInt(256);
    73             int b = random.nextInt(256);
    74 
    75             paint.setARGB(255, r, g, b);
    76         } else {
    77             paint.setColor(color);
    78         }
    79     }
    80 
    81     public void draw(Canvas canvas) {
    82         canvas.drawLine(startX, startY, stopX, stopY, paint);
    83     }
    84 
    85     public void move() {
    86         startX += sizeX * opt;
    87         stopX += sizeX * opt;
    88 
    89         startY += sizeY * opt;
    90         stopY += sizeY * opt;
    91 
    92         if (startY > height) {
    93             init();
    94         }
    95     }
    96 
    97 }

    DEMO下载路径:http://download.csdn.net/detail/androidsj/9279741

  • 相关阅读:
    Django的认证系统
    Django 中间件
    Django Form和ModelForm组件
    AJAX
    Django中ORM介绍和字段及字段参数
    Django ORM那些相关操作
    Python中应该使用%还是format来格式化字符串?
    Cookie、Session和自定义分页
    ORM版学员管理系统3
    ORM版学员管理系统2
  • 原文地址:https://www.cnblogs.com/androidsj/p/4974108.html
Copyright © 2011-2022 走看看