Android粒子效果之雨

Android粒子效果之雨

上篇文章裏面講到了自定義view的基礎和原理 ,在這基礎之上我們來看一下今天的內容,分爲如下的三個部分。

單個雨點的行爲

單個雨點的運動軌跡,實際上就是一條很短的直線做自由落體運動,於是我們先來模仿這樣的一個行爲。

    private void init() {
        sizeX = 10;
        sizeY = 30;

        startX = 100;
        startY = 0;
        stopX = startX + sizeX;
        stopY = startY + sizeY;

        paint = new Paint();
        paint.setColor(0xffffffff);
    }

    @Override
    protected void drawSub(Canvas canvas) {
        canvas.drawLine(startX, startY, stopX, stopY, paint);
    }

    @Override
    protected void logic() {
        float opt = 0.5f;
        startX += sizeX;
        stopX += sizeX;

        startY += sizeY;
        stopY += sizeY;

        if (startY > getHeight()) {
            startX = 100;
            startY = 0;
            stopX = startX + sizeX;
            stopY = startY + sizeY;
        }
    }

這裏寫圖片描述

完善雨點行爲和下雨場景的構建

既然有個單個雨點,於是將單個雨點的作爲對象來進行封裝

public class RainItem {
    private int width;// 屏幕的寬
    private int height;// 屏幕的高

    private float startX;// x方向起點位置
    private float startY;// y方向起點位置
    private float stopX;// x方向結束位置
    private float stopY;// y方向結束位置

    private float sizeX;// x方向上的角度
    private float sizeY;// y方向上的角度

    float opt;// 運動速率

    private Random random;

    private Paint paint;

    public RainItem(int width, int height) {
        super();
        this.width = width;
        this.height = height;

        random = new Random();
        paint = new Paint();
        paint.setColor(0xffffffff);

        init();
    }

    private void init() {
        sizeX = 1 + random.nextInt(10);
        sizeY = 10 + random.nextInt(30);

        // 改變雨點x方向起點位置
        startX = random.nextInt(width);
        // 改變雨點y方向起點位置
        startY = random.nextInt(height);
        // 改變運動速度
        opt = 0.2f + random.nextFloat();
        // 角度的改變
        stopX = startX + sizeX;
        stopY = startY + sizeY;
    }

    public void draw(Canvas canvas) {
        canvas.drawLine(startX, startY, stopX, stopY, paint);
    }

    public void move() {

        startX += sizeX;
        stopX += sizeX;

        startY += sizeY;
        stopY += sizeY;

        if (startY > height) {
            init();
        }
    }
}

從RainItem對象中可以看出這樣我們構建一個下雨的場景就非常的簡單,創建多個雨點對象,調用其每個雨點的draw()方法和move()

public class RainView extends BaseView {
    private int size = 60;
    private List<RainItem> mRainList;

    public RainView(Context context) {
        this(context, null);
    }

    public RainView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RainView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void drawSub(Canvas canvas) {
        for (RainItem item : mRainList) {
            item.draw(canvas);
        }
    }

    @Override
    protected void logic() {
        for (RainItem item : mRainList) {
            item.move();
        }
    }

    @Override
    protected void init() {
        mRainList = new ArrayList<RainItem>();

        for (int i = 0; i < size; i++) {
            RainItem item = new RainItem(getWidth(), getHeight());
            mRainList.add(item);
        }
    }
}

效果是這樣

XML中定義控制下雨的屬性

在res/values下創建文件attrs.xml

<resources>

    <declare-styleable name="RainView">

        <!-- 雨點數量 -->
        <attr name="rainNum" format="integer"></attr>
        <!-- 雨點大小 -->
        <attr name="rainSize" format="integer"></attr>
        <!-- 雨點顏色 -->
        <attr name="rainColor" format="integer"></attr>
    </declare-styleable>

</resources>

在佈局文件中使用:

<com.yiye.rain.view.RainView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        yiye:rainSize="10"
        yiye:rainColor="0xffee0000"
        yiye:rainNum="100" />

代碼中讀取屬性並作用到view上

public class RainView extends BaseView {
    private int rainNum;
    private int rainSize;
    private int rainColor;
    private List<RainItem> mRainList;

    public RainView(Context context) {
        this(context, null);
    }

    public RainView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        // 讀取到自定義屬性
        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.RainView);

        int n = a.getIndexCount();
        for (int i = 0; i < n; i++) {
            int attr = a.getIndex(i);
            switch (attr) {
            case R.styleable.RainView_rainNum:
                rainNum = a.getInt(attr, 50);
                break;

            case R.styleable.RainView_rainSize:
                rainSize = a.getInt(attr, 50);
                break;
            case R.styleable.RainView_rainColor:
                rainColor = a.getInt(attr, 0xffffffff);
                break;

            default:
                break;
            }
        }

        a.recycle();
    }

    public RainView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void drawSub(Canvas canvas) {
        for (RainItem item : mRainList) {
            item.draw(canvas);
        }
    }

    @Override
    protected void logic() {
        for (RainItem item : mRainList) {
            item.move();
        }
    }

    @Override
    protected void init() {
        mRainList = new ArrayList<RainItem>();

        for (int i = 0; i < rainNum; i++) {
            RainItem item = new RainItem(getWidth(), getHeight(), rainSize,
                    rainColor);
            mRainList.add(item);
        }
    }
}

最終的效果:這裏寫圖片描述

源碼下載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章