首页 > 代码库 > Android 自定义View(五) 多片叶子叶子旋转滑动

Android 自定义View(五) 多片叶子叶子旋转滑动

实现思路比较简单,就是添加一个叶子Leaf类,储存每片叶子的信息,

然后随机产生叶子的坐标及旋转角度,最后实时获取每片叶子信息,添加到画布中

1、Leaf.java 叶子类

    private class Leaf {
        // 叶子的坐标
        float x, y;
        // 旋转角度
        int rotateAngle;
        // 起始时间(ms)
        long startTime;
    }

2、初始化每片叶子的信息,然后保存到list中

    //使叶子初始时间有间隔
    int addTime;
    private Leaf getLeaf() {
        Random random = new Random();
        Leaf leaf = new Leaf();
        //随机初始化叶子初始角度
        leaf.rotateAngle = random.nextInt(360);
        //随机初始化叶子启动时间
        addTime += random.nextInt((int) (cycleTime));
        leaf.startTime = System.currentTimeMillis() + cycleTime + addTime;
        return leaf;
    }
    private List<Leaf> getLeafs(int leafSize) {
        List<Leaf> list = new LinkedList<Leaf>();
        for (int i=0; i<leafSize; i++) {
            list.add(getLeaf());
        }
        return list;
    }

3、接下去就是改写getLocation()及getRotate()方法,使其返回每片叶子的坐标及旋转角度

    //获取每片叶子在XY轴上的滑动值
    private void getLocation(Leaf leaf) {
        float betweenTime = leaf.startTime - System.currentTimeMillis();
        //周期结束再加一个cycleTime
        if(betweenTime < 0) {
            leaf.startTime = System.currentTimeMillis() + cycleTime + new Random().nextInt((int) (cycleTime));
            betweenTime = cycleTime;
        }
        //通过时间差计算出叶子的坐标
        float fraction = (float) betweenTime / cycleTime;
        float x = (int)(width * fraction);
        leaf.x = x;
        float w = (float) ((float) 2 * Math.PI / width);
        int y = (int) (18 * Math.sin(w * x)) + (height-mLeafHeight)/2;
        leaf.y = y;

    }

    //获取每片叶子的旋转角度
    private void getRotate(Leaf leaf) {
        float scale = ((leaf.startTime - System.currentTimeMillis())%cycleTime)/ (float)cycleTime;
        int rotate = (int)(scale * 360);
        leaf.rotateAngle = rotate;
    }

4、在onDraw()方法中,画出每片叶子

  @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画叶子
        int size = leafList.size();
        for (int i=0; i<size; i++) {
            Leaf leaf = leafList.get(i);
            //获取叶子坐标
            getLocation(leaf);
            //获取叶子旋转角度
            getRotate(leaf);
            canvas.save();
            Matrix matrix = new Matrix();
            //设置滑动
            matrix.postTranslate(leaf.x, leaf.y);
            //设置旋转
            matrix.postRotate(leaf.rotateAngle, leaf.x + mLeafWidth / 2, leaf.y + mLeafHeight / 2);
            //添加叶子到画布
            canvas.drawBitmap(mLeafBitmap, matrix, new Paint());
            canvas.restore();
        }
        //调用onDraw()重复滑动
        postInvalidate();
    }

完整代码



public class LeafView extends View {
    private String TAG = "--------LeafView";
    private Resources mResources;
    //背景图、叶子
    private Bitmap mLeafBitmap, bgBitmap;
    //整个控件的宽度和高度
    private int width, height;
    private Paint bgPaint;
    private RectF bgRect;
    private Rect  bgDestRect;
    //存放叶子lsit
    private List<Leaf> leafList;
    //叶子的宽和高
    private int mLeafWidth, mLeafHeight;
    //叶子滑动一周的时间5秒
    private final static long cycleTime = 5000;
    //叶子数量
    private final static int leafNumber = 5;
    public LeafView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mResources = getResources();
        mLeafBitmap = ((BitmapDrawable) mResources.getDrawable(R.drawable.leaf, null)).getBitmap();
        mLeafWidth = mLeafBitmap.getWidth();
        mLeafHeight = mLeafBitmap.getHeight()

        bgBitmap = ((BitmapDrawable) mResources.getDrawable(R.drawable.leaf_kuang, null)).getBitmap();
        bgPaint = new Paint();
        bgPaint.setColor(mResources.getColor(R.color.bg_color));
        //获取所有叶子的信息,放入list
        leafList = getLeafs(leafNumber);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
        bgDestRect = new Rect(0, 0 , width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        bgRect = new RectF(0, 0 , width, height);
        //画背景颜色到画布
        canvas.drawRect(bgRect, bgPaint);
        //画背景图片到画布
        canvas.drawBitmap(bgBitmap, null, bgDestRect, null);

        //画叶子
        int size = leafList.size();
        for (int i=0; i<size; i++) {
            Leaf leaf = leafList.get(i);
            //获取叶子坐标
            getLocation(leaf);
            //获取叶子旋转角度
            getRotate(leaf);
            canvas.save();
            Matrix matrix = new Matrix();
            //设置滑动
            matrix.postTranslate(leaf.x, leaf.y);
            //设置旋转
            matrix.postRotate(leaf.rotateAngle, leaf.x + mLeafWidth / 2, leaf.y + mLeafHeight / 2);
            //添加叶子到画布
            canvas.drawBitmap(mLeafBitmap, matrix, new Paint());
            canvas.restore();
        }
        //调用onDraw()重复滑动
        postInvalidate();
    }

    //获取每片叶子在XY轴上的滑动值
    private void getLocation(Leaf leaf) {
        float betweenTime = leaf.startTime - System.currentTimeMillis();
        //周期结束再加一个cycleTime
        if(betweenTime < 0) {
            leaf.startTime = System.currentTimeMillis() + cycleTime + new Random().nextInt((int) (cycleTime));
            betweenTime = cycleTime;
        }
        //通过时间差计算出叶子的坐标
        float fraction = (float) betweenTime / cycleTime;
        float x = (int)(width * fraction);
        leaf.x = x;
        float w = (float) ((float) 2 * Math.PI / width);
        int y = (int) (18 * Math.sin(w * x)) + (height-mLeafHeight)/2;
        leaf.y = y;
    }

    //获取每片叶子的旋转角度
    private void getRotate(Leaf leaf) {
        float scale = ((leaf.startTime - System.currentTimeMillis())%cycleTime)/ (float)cycleTime;
        int rotate = (int)(scale * 360);
        leaf.rotateAngle = rotate;
    }

    private class Leaf {
        // 叶子的坐标
        float x, y;
        // 旋转角度
        int rotateAngle;
        // 起始时间(ms)
        long startTime;
    }

    private List<Leaf> getLeafs(int leafSize) {
        List<Leaf> list = new LinkedList<Leaf>();
        for (int i=0; i<leafSize; i++) {
            list.add(getLeaf());
        }
        return list;
    }

    //使叶子初始时间有间隔
    int addTime;
    private Leaf getLeaf() {
        Random random = new Random();
        Leaf leaf = new Leaf();
        leaf.rotateAngle = random.nextInt(360);
        addTime += random.nextInt((int) (cycleTime));
        leaf.startTime = System.currentTimeMillis() + cycleTime + addTime;
        return leaf;
    }
}

这里还有很多瑕疵,比如叶子的滑动范围覆盖了边框等等

需要图片等信息的可以从下面的Github地址下载,不过原文比较复杂

参考 https://github.com/Ajian-studio/GALeafLoading

 

Android 自定义View(五) 多片叶子叶子旋转滑动