总体 思路 一个总的场景 进行定时红包的刷新等 红包对象 固有属性 速度 图片 位置等等 红包对象 自己管理自己节省计算
/**
* 作者 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();//开始
}
});