Android隨機生成一個位置在界面上,不重複。

摘出項目中比較特殊的控件備用,參考同事的代碼。

package com.fable.artedu.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.ScaleAnimation;
import android.widget.RelativeLayout;

import com.fable.artedu.R;
import com.fable.artedu.activity.TimeMachineActivity;

import java.util.ArrayList;
import java.util.Random;

//**
//
// * 可以添加隨機位置View的佈局!
// * 主要的思路是:
// * 1、位置隨機
// * 2、防止覆蓋
// */

public class RandomLayout<T> extends RelativeLayout {
    /**
     * 此列表用於保存隨機的View視圖
     * 在添加隨機View的時候應當判斷此視圖是否有覆蓋的
     * 有的話應該重新進行隨機!
     */
    public ArrayList<View> randomViewList = new ArrayList<>();
    private OnRandomItemClickListener<T> onRandomItemClickListener;
    private OnRandomItemLongClickListener<T> onRandomItemLongClickListener;
    private boolean itemClickable = true;
    private boolean itemLongClickable = true;
    private Context context;
    public RandomLayout(Context context) {
        super(context);
    }
 
    public RandomLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setContext(Context context){
        this.context=context;
    }
 
    /**
     * 添加到一個隨機的XY位置,且不重複。
     */
    public void addViewAtRandomXY(final View view, final T t) {
        if (view == null) return;
        view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
        post(new Runnable() {
            @Override
            public void run() {
                randomViewList.remove(view);
                // 100次隨機上限
                for (int i = 0; i < 100; i++) {
                    int[] xy = createXY(
                            view.getMeasuredHeight(),
                            view.getMeasuredWidth()
                    );
                    if (randomViewList.size() == 0) {
                        addViewAndSetXY(view, xy[0], xy[1], t);
                    } else {
                        boolean isRepeat = false;
                        // 迭代已經存在的View,判斷是否重疊!
                        for (View subView : randomViewList) {
                            // 得到XY
                            int x = (int) subView.getX();
                            int y = (int) subView.getY();
                            int width = subView.getMeasuredWidth();
                            int height = subView.getMeasuredHeight();
                            // 創建矩形
                            Rect v1Rect = new Rect(x, y, width + x, height + y);
                            Rect v2Rect = new Rect(xy[0], xy[1], view.getMeasuredWidth() + xy[0], view.getMeasuredHeight() + xy[1]
                            );
                            if (Rect.intersects(v1Rect, v2Rect)) {
                                isRepeat = true;
                                break;
                            }
                        }
                        if (!isRepeat) {
                            addViewAndSetXY(view, xy[0], xy[1], t);
                            return;
                        }
                    }
                }
            }
        });
    }
 
    public void addViewAndSetXY(View view, int x, int y, final T t) {

        removeView(view);
        addView(view);
        randomViewList.add(view);
        view.setX(x);
        view.setY(y);
        // 設置單擊事件!
        view.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (onRandomItemClickListener != null && isItemClickable()) {
                    onRandomItemClickListener.onRandomItemClick(v, t);
                }
            }
        });
        // 設置長按事件!
        view.setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (onRandomItemLongClickListener != null && itemLongClickable)
                    return onRandomItemLongClickListener.onRandomItemLongClick(v, t);
                return false;
            }
        });
    }


    /**
     * 添加一個View到隨機列表中,以此達到防止覆蓋的效果!
     */
    public void addViewToRandomList(View view) {
        randomViewList.add(view);
    }
 
    /**
     * 清除所有的隨機視圖!
     */
    public void removeAllRandomView() {
        for (View v : randomViewList) {
            removeView(v);
        }
        randomViewList.clear();
    }
 
    /**
     * 從列表中移除一個隨機視圖!
     */
    public void removeRandomViewFromList(View view) {
        randomViewList.remove(view);
    }
 
    /**
     * 隨機生成一個 0 到指定區間的值!
     *
     * @param max 0到max但是不包括max
     * @return 同上
     */
    private int random(int max) {
        // LogUtils.d("Max是:" + max);
        return new Random().nextInt(max);
    }
 
    /**
     * 根據傳入的寬和高返回一個隨機的座標!
     */
    @SuppressLint("NewApi")
    private int[] createXY(int height, int width) {
        int[] xyRet = new int[]{0, 0};
        // 初始化我們當前佈局的屏幕XY!
        int layoutHeight = getMeasuredHeight();
        int layoutWidth = getMeasuredWidth();
        // 先隨機一個X,注意一下就是,X軸是從View的左向右延申的
        // 注意,要減去內部填充!!!
        // LogUtils.d("paddingEnd: " + paddingEnd);
        xyRet[0] = random(
                layoutWidth - (
                        width + getPaddingStart() + getPaddingEnd()
                )
        );
        // LogUtils.d(" 佈局寬度:" + layoutWidth + ",X軸:" + xyRet[0] + ",最終寬度:" + (xyRet[0] + width + paddingEnd + paddingStart));
        // 然後從Y是從View的上向下延申,所以我們需要進行下限值限制,避免越界!
        xyRet[1] = random(
                layoutHeight - (
                        height + getPaddingBottom() + getPaddingTop()
                )
        );
        return xyRet;
    }
 
    public boolean isItemClickable() {
        return itemClickable;
    }
 
    public void setItemClickable(boolean itemClickable) {
        this.itemClickable = itemClickable;
    }
 
    public boolean isItemLongClickable() {
        return itemLongClickable;
    }
 
    public void setItemLongClickable(boolean itemLongClickable) {
        this.itemLongClickable = itemLongClickable;
    }
 
    public OnRandomItemClickListener getOnRandomItemClickListener() {
        return onRandomItemClickListener;
    }
 
    public void setOnRandomItemClickListener(OnRandomItemClickListener<T> onRandomItemClickListener) {
        this.onRandomItemClickListener = onRandomItemClickListener;
    }
 
    public OnRandomItemLongClickListener<T> getOnRandomItemLongClickListener() {
        return onRandomItemLongClickListener;
    }
 
    public void setOnRandomItemLongClickListener(OnRandomItemLongClickListener<T> onRandomItemLongClickListener) {
        this.onRandomItemLongClickListener = onRandomItemLongClickListener;
    }
 
    public interface OnRandomItemClickListener<T> {
        void onRandomItemClick(View view, T t);
    }
 
    public interface OnRandomItemLongClickListener<T> {
        boolean onRandomItemLongClick(View view, T t);
    }
}
調用  初始化
  RandomLayout randomlayout = findViewById(R.id.randomlayout);
   randomlayout.setContext(this);

//添加View


調用方法

//設置佔位view
public void setZwView() {
View view = LayoutInflater.from(TimeMachineActivity.this).inflate(R.layout.machine_ortherday_layout, null, false);
TextView textView = view.findViewById(R.id.tv_mac);
textView.setBackground(ContextCompat.getDrawable(TimeMachineActivity.this, R.mipmap.day_bg));
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight() - StringCompat.dip2px(TimeMachineActivity.this, 360);
view.setVisibility(View.INVISIBLE);
randomlayout.addViewAndSetXY(view, (width - StringCompat.dip2px(TimeMachineActivity.this, 109)) / 2, (height - StringCompat.dip2px(TimeMachineActivity.this, 109)) / 2, -1);
mHandler.postDelayed(runnable, 500);
}

//設置監聽
randomlayout.setOnRandomItemClickListener();

//清除所有的View
randomlayout.removeAllRandomView();

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