Android 红包雨的实现及大概思路 复制即可使用 具体自己可以调整

 

总体 思路  一个总的场景 进行定时红包的刷新等  红包对象 固有属性 速度 图片 位置等等 红包对象 自己管理自己节省计算

/**
 * 作者 lxy on Time 2020-10-2015:46.
 * 上有天,下有地,中间站着你自己,做一天人,尽一天人事儿
 * 人生是一个永不停息的工厂,那里没有懒人的位置。工作吧!创造吧!
 * <p>
 * 红包雨  作用提供红包雨的场景并全局控制
 */
public class RedRainView extends RelativeLayout {
    int height;
    int wide;
    ArrayList<RedView> redViews = new ArrayList<>();//保存的红包数组

    private int number = 0;//点到的红包数量

    public RedRainView(@NonNull Context context) {
        super(context);
    }

    public RedRainView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public RedRainView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void init() {
        post(new Runnable() {//场景绘制完成后 获取红包的宽高
            @Override
            public void run() {
                height = getMeasuredHeight();
                wide = getMeasuredWidth();
            }
        });
    }

    public void start() { //开始下红包
        TimeUtils.newInstance().setCallBack(onTimeCallListent);//设置定时器监听
        mHandler.postDelayed(r, 1000);//延迟一秒后计算当前生成的红包

    }

    TimeUtils.OnTimeCallListent onTimeCallListent = new TimeUtils.OnTimeCallListent() {//定时器 每隔一秒进行刷新红包数量操作
        @Override
        public void onTime(long time) {
            int number = 2 + (int) (Math.random() * 5);  //随机生成红包个数
            for (int i = 0; i < number; i++) {            //创建红包并添加到布局内
                RedView redView = new RedView(getContext()); //红包对象
                addView(redView);
                redView.init(RedRainView.this);
                redView.setOnClickListener(onClickListener);
                redViews.add(redView);  //加入红包数组内
            }

        }
    };


    final Handler mHandler = new Handler();
    Runnable r = new Runnable() {
        @Override
        public void run() {  //定时刷新红包信息 并移除 已失效红包
            ArrayList<RedView> redViews1 = new ArrayList<>();
            for (int i = 0; i < redViews.size(); i++) {
                RedView redView = redViews.get(i);
                redView.refresh();
                if (!redView.isOut)
                    redViews1.add(redView);
            }

            redViews.clear();
            redViews.addAll(redViews1);

            mHandler.postDelayed(this, 2);
        }
    };

    OnClickListener onClickListener = new OnClickListener() {  //红包的点击事件 计数
        @Override
        public void onClick(View view) {
            number++;
        }
    };


    public int getNumber() {
        return number;
    }
}

红包场景控件 

 


/**
 * 作者 lxy on Time 2020-10-2015:54.
 * 上有天,下有地,中间站着你自己,做一天人,尽一天人事儿
 * 人生是一个永不停息的工厂,那里没有懒人的位置。工作吧!创造吧!
 */
public class RedView extends android.support.v7.widget.AppCompatImageView { //红包对象
    int wide;  //红包的宽
    int height; //红包的高
    int v = 1; //红包的速度
    int margTop = 0; //红包的距离顶部位置
    boolean isOut = false; //是否失效
    ViewGroup group; // 父容器

    int maxHeight = 0; //场景的最大高度

    RelativeLayout.LayoutParams params;

    public RedView(Context context) {
        super(context);
    }

    public RedView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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


    public void init(ViewGroup group) { //初始化红包
        this.group = group;
        isOut = false;
        Resources resources = this.getResources();
        DisplayMetrics dm = resources.getDisplayMetrics();
        int width3 = dm.widthPixels; // 获取屏幕的宽度 与高度
        maxHeight = dm.heightPixels;


        v = (int) (12 + Math.random() * 8);  //随机 红包下落速度
        wide = (int) (BaseActivity.dp2px(getContext(), 30) + BaseActivity.dp2px(getContext(), (int) (Math.random() * 20))); //随机 红包大小
        height = (int) (wide / 314.0 * 426.0); //等比换算高度
        params = (RelativeLayout.LayoutParams) getLayoutParams(); //设定红包 大小与初始位置
        params.height = height;
        params.width = wide;
        params.topMargin = -height;
        params.leftMargin = (int) (Math.random() * (width3 - BaseActivity.dp2px(getContext(), 120))
                + BaseActivity.dp2px(getContext(), 40));
        setLayoutParams(params);
        setBackgroundResource(R.mipmap.red_icon);  //设置红包图片
        super.setOnClickListener(onClickListener);
    }


    public void refresh() {  // 刷新红包位置  根据红包速度进行位置计算
        margTop = v + margTop;
        params = (RelativeLayout.LayoutParams) getLayoutParams();
        params.topMargin = margTop;
        setLayoutParams(params);
        if (margTop >= maxHeight) {//判断红包位置 是否超出场景 如果超出 则设为失效并移除 节省资源
            diss(false);
        }
    }


    private void diss(boolean isOnClick) {  //失效事件  isOnClick 为是否因为点击失效
        isOut = true;               //设置为已失效
        group.removeView(this);  //幕布移除 失效红包

        if (!isOnClick)  //如果是点击导致的失效 则在原位置显示 +1 动画
            return;
        TextView textView = new TextView(getContext());
        textView.setText("+1");
        textView.setTextSize(BaseActivity.dp2px(getContext(), 11));
        textView.setTextColor(getResources().getColor(R.color.white));
        group.addView(textView);

        params.height = RelativeLayout.LayoutParams.WRAP_CONTENT;
        params.width = RelativeLayout.LayoutParams.WRAP_CONTENT;
        textView.setLayoutParams(params);
        startObjectAnimatorAnims(textView);
    }

    public void startObjectAnimatorAnims(View v) {  //+1动画 结束后自动移除
        ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(v, "alpha", 1.0f, 0f);
        //执行事件
        alphaAnim.setDuration(500);
        //延迟
        alphaAnim.setStartDelay(0);

        alphaAnim.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {

            }

            @Override
            public void onAnimationEnd(Animator animator) {
                group.removeView(v);
            }

            @Override
            public void onAnimationCancel(Animator animator) {

            }

            @Override
            public void onAnimationRepeat(Animator animator) {

            }
        });

        alphaAnim.start();
    }


    OnClickListener onClickListener = new OnClickListener() {
        @Override
        public void onClick(View view) {
            diss(true);
            if (l != null)
                l.onClick(view);
        }
    };

    OnClickListener l;

    @Override
    public void setOnClickListener(@Nullable OnClickListener l) {
        this.l = l;
    } // 设置 红包点击事件
}

红包对象 

 


public class TimeUtils {

    private static TimeUtils timeUtils;
    ArrayList<WeakReference<OnTimeCallListent>> listents = new ArrayList<>();


    private TimeUtils() {
        mHandler.postDelayed(r, 1000);//延时100毫秒
    }

    public static synchronized TimeUtils newInstance() {
        if (timeUtils == null) {
            timeUtils = new TimeUtils();
        }
        return timeUtils;
    }


    public void setCallBack(OnTimeCallListent onTimeCallListent) {
        for (int i = 0; i < listents.size(); i++) {
            if (listents.get(i).get() == onTimeCallListent)
                return;
        }

        WeakReference<OnTimeCallListent> weakReference = new WeakReference<>(onTimeCallListent);
        listents.add(weakReference);
    }

    public interface OnTimeCallListent {
        public void onTime(long time);
    }


    final Handler mHandler = new Handler();
    Runnable r = new Runnable() {

        @Override
        public void run() {
            ArrayList<WeakReference<OnTimeCallListent>> mList = new ArrayList<>();
            for (int i = 0; i < listents.size(); i++) {
                OnTimeCallListent listent = listents.get(i).get();
                if (listent != null) {
                    mList.add(listents.get(i));
                    listent.onTime(DateUtil.getLongTime() / 1000);
                }
            }
            listents.clear();
            listents = mList;
            mHandler.postDelayed(this, 1000);
        }
    };


}

定时器

 

 

使用方式

<com.tany.base.widget.RedRainView
                android:id="@+id/redRain"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:clipChildren="false" />


 mBinding.redRain.init();//初始化
                mBinding.redRain.post(new Runnable() {
                    @Override
                    public void run() {
                        mBinding.redRain.start();//开始
                    }
                });

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值