FileDocCategorySizeDatePackage
DessertCaseView.javaAPI DocAndroid 5.1 API17924Thu Mar 12 22:22:42 GMT 2015com.android.systemui

DessertCaseView

public class DessertCaseView extends android.widget.FrameLayout

Fields Summary
private static final String
TAG
private static final boolean
DEBUG
static final int
START_DELAY
static final int
DELAY
static final int
DURATION
private static final int
TAG_POS
private static final int
TAG_SPAN
private static final int[]
PASTRIES
private static final int[]
RARE_PASTRIES
private static final int[]
XRARE_PASTRIES
private static final int[]
XXRARE_PASTRIES
private static final int
NUM_PASTRIES
private android.util.SparseArray
mDrawables
private static final float[]
MASK
private static final float[]
ALPHA_MASK
private static final float[]
WHITE_MASK
public static final float
SCALE
private static final float
PROB_2X
private static final float
PROB_3X
private static final float
PROB_4X
private boolean
mStarted
private int
mCellSize
private int
mWidth
private int
mHeight
private int
mRows
private int
mColumns
private android.view.View[]
mCells
private final Set
mFreeList
private final android.os.Handler
mHandler
private final Runnable
mJuggle
float[]
hsv
private final HashSet
tmpSet
Constructors Summary
public DessertCaseView(android.content.Context context)


       
        this(context, null);
    
public DessertCaseView(android.content.Context context, android.util.AttributeSet attrs)

        this(context, attrs, 0);
    
public DessertCaseView(android.content.Context context, android.util.AttributeSet attrs, int defStyle)

        super(context, attrs, defStyle);

        final Resources res = getResources();

        mStarted = false;

        mCellSize = res.getDimensionPixelSize(R.dimen.dessert_case_cell_size);
        final BitmapFactory.Options opts = new BitmapFactory.Options();
        if (mCellSize < 512) { // assuming 512x512 images
            opts.inSampleSize = 2;
        }
        opts.inMutable = true;
        Bitmap loaded = null;
        for (int[] list : new int[][] { PASTRIES, RARE_PASTRIES, XRARE_PASTRIES, XXRARE_PASTRIES }) {
            for (int resid : list) {
                opts.inBitmap = loaded;
                loaded = BitmapFactory.decodeResource(res, resid, opts);
                final BitmapDrawable d = new BitmapDrawable(res, convertToAlphaMask(loaded));
                d.setColorFilter(new ColorMatrixColorFilter(ALPHA_MASK));
                d.setBounds(0, 0, mCellSize, mCellSize);
                mDrawables.append(resid, d);
            }
        }
        loaded = null;
        if (DEBUG) setWillNotDraw(false);
    
Methods Summary
private static BitmapconvertToAlphaMask(Bitmap b)

        Bitmap a = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ALPHA_8);
        Canvas c = new Canvas(a);
        Paint pt = new Paint();
        pt.setColorFilter(new ColorMatrixColorFilter(MASK));
        c.drawBitmap(b, 0.0f, 0.0f, pt);
        return a;
    
public voidfillFreeList()

        fillFreeList(DURATION);
    
public synchronized voidfillFreeList(int animationLen)

        final Context ctx = getContext();
        final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(mCellSize, mCellSize);

        while (! mFreeList.isEmpty()) {
            Point pt = mFreeList.iterator().next();
            mFreeList.remove(pt);
            final int i=pt.x;
            final int j=pt.y;

            if (mCells[j*mColumns+i] != null) continue;
            final ImageView v = new ImageView(ctx);
            v.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    place(v, true);
                    postDelayed(new Runnable() { public void run() { fillFreeList(); } }, DURATION/2);
                }
            });

            final int c = random_color();
            v.setBackgroundColor(c);

            final float which = frand();
            final Drawable d;
            if (which < 0.0005f) {
                d = mDrawables.get(pick(XXRARE_PASTRIES));
            } else if (which < 0.005f) {
                d = mDrawables.get(pick(XRARE_PASTRIES));
            } else if (which < 0.5f) {
                d = mDrawables.get(pick(RARE_PASTRIES));
            } else if (which < 0.7f) {
                d = mDrawables.get(pick(PASTRIES));
            } else {
                d = null;
            }
            if (d != null) {
                v.getOverlay().add(d);
            }

            lp.width = lp.height = mCellSize;
            addView(v, lp);
            place(v, pt, false);
            if (animationLen > 0) {
                final float s = (Integer) v.getTag(TAG_SPAN);
                v.setScaleX(0.5f * s);
                v.setScaleY(0.5f * s);
                v.setAlpha(0f);
                v.animate().withLayer().scaleX(s).scaleY(s).alpha(1f).setDuration(animationLen);
            }
        }
    
static floatfrand()

        return (float)(Math.random());
    
static floatfrand(float a, float b)

        return (frand() * (b-a) + a);
    
private Point[]getOccupied(android.view.View v)

        final int scale = (Integer) v.getTag(TAG_SPAN);
        final Point pt = (Point)v.getTag(TAG_POS);
        if (pt == null || scale == 0) return new Point[0];

        final Point[] result = new Point[scale * scale];
        int p=0;
        for (int i=0; i<scale; i++) {
            for (int j=0; j<scale; j++) {
                result[p++] = new Point(pt.x + i, pt.y + j);
            }
        }
        return result;
    
static intirand(int a, int b)

        return (int)(frand(a, b));
    
private final Animator.AnimatorListenermakeHardwareLayerListener(android.view.View v)

        return new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animator) {
                v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
                v.buildLayer();
            }
            @Override
            public void onAnimationEnd(Animator animator) {
                v.setLayerType(View.LAYER_TYPE_NONE, null);
            }
        };
    
public voidonDraw(Canvas c)

        super.onDraw(c);
        if (!DEBUG) return;

        Paint pt = new Paint();
        pt.setStyle(Paint.Style.STROKE);
        pt.setColor(0xFFCCCCCC);
        pt.setStrokeWidth(2.0f);

        final Rect check = new Rect();
        final int N = getChildCount();
        for (int i = 0; i < N; i++) {
            View stone = getChildAt(i);

            stone.getHitRect(check);

            c.drawRect(check, pt);
        }
    
protected synchronized voidonSizeChanged(int w, int h, int oldw, int oldh)

        super.onSizeChanged(w, h, oldw, oldh);
        if (mWidth == w && mHeight == h) return;

        final boolean wasStarted = mStarted;
        if (wasStarted) {
            stop();
        }

        mWidth = w;
        mHeight = h;

        mCells = null;
        removeAllViewsInLayout();
        mFreeList.clear();

        mRows = mHeight / mCellSize;
        mColumns = mWidth / mCellSize;

        mCells = new View[mRows * mColumns];

        if (DEBUG) Log.v(TAG, String.format("New dimensions: %dx%d", mColumns, mRows));

        setScaleX(SCALE);
        setScaleY(SCALE);
        setTranslationX(0.5f * (mWidth - mCellSize * mColumns) * SCALE);
        setTranslationY(0.5f * (mHeight - mCellSize * mRows) * SCALE);

        for (int j=0; j<mRows; j++) {
            for (int i=0; i<mColumns; i++) {
                mFreeList.add(new Point(i,j));
            }
        }

        if (wasStarted) {
            start();
        }
    
intpick(int[] a)

        return a[(int)(Math.random()*a.length)];
    
Tpick(T[] a)

        return a[(int)(Math.random()*a.length)];
    
Tpick(android.util.SparseArray sa)

        return sa.valueAt((int)(Math.random()*sa.size()));
    
public voidplace(android.view.View v, boolean animate)

        place(v, new Point(irand(0, mColumns), irand(0, mRows)), animate);
    
public synchronized voidplace(android.view.View v, Point pt, boolean animate)

             
        final int i = pt.x;
        final int j = pt.y;
        final float rnd = frand();
        if (v.getTag(TAG_POS) != null) {
            for (final Point oc : getOccupied(v)) {
                mFreeList.add(oc);
                mCells[oc.y*mColumns + oc.x] = null;
            }
        }
        int scale = 1;
        if (rnd < PROB_4X) {
            if (!(i >= mColumns-3 || j >= mRows-3)) {
                scale = 4;
            }
        } else if (rnd < PROB_3X) {
            if (!(i >= mColumns-2 || j >= mRows-2)) {
                scale = 3;
            }
        } else if (rnd < PROB_2X) {
            if (!(i == mColumns-1 || j == mRows-1)) {
                scale = 2;
            }
        }

        v.setTag(TAG_POS, pt);
        v.setTag(TAG_SPAN, scale);

        tmpSet.clear();

        final Point[] occupied = getOccupied(v);
        for (final Point oc : occupied) {
            final View squatter = mCells[oc.y*mColumns + oc.x];
            if (squatter != null) {
                tmpSet.add(squatter);
            }
        }

        for (final View squatter : tmpSet) {
            for (final Point sq : getOccupied(squatter)) {
                mFreeList.add(sq);
                mCells[sq.y*mColumns + sq.x] = null;
            }
            if (squatter != v) {
                squatter.setTag(TAG_POS, null);
                if (animate) {
                    squatter.animate().withLayer()
                            .scaleX(0.5f).scaleY(0.5f).alpha(0)
                            .setDuration(DURATION)
                            .setInterpolator(new AccelerateInterpolator())
                            .setListener(new Animator.AnimatorListener() {
                                public void onAnimationStart(Animator animator) { }
                                public void onAnimationEnd(Animator animator) {
                                    removeView(squatter);
                                }
                                public void onAnimationCancel(Animator animator) { }
                                public void onAnimationRepeat(Animator animator) { }
                            })
                            .start();
                } else {
                    removeView(squatter);
                }
            }
        }

        for (final Point oc : occupied) {
            mCells[oc.y*mColumns + oc.x] = v;
            mFreeList.remove(oc);
        }

        final float rot = (float)irand(0, 4) * 90f;

        if (animate) {
            v.bringToFront();

            AnimatorSet set1 = new AnimatorSet();
            set1.playTogether(
                    ObjectAnimator.ofFloat(v, View.SCALE_X, (float) scale),
                    ObjectAnimator.ofFloat(v, View.SCALE_Y, (float) scale)
            );
            set1.setInterpolator(new AnticipateOvershootInterpolator());
            set1.setDuration(DURATION);

            AnimatorSet set2 = new AnimatorSet();
            set2.playTogether(
                    ObjectAnimator.ofFloat(v, View.ROTATION, rot),
                    ObjectAnimator.ofFloat(v, View.X, i* mCellSize + (scale-1) * mCellSize /2),
                    ObjectAnimator.ofFloat(v, View.Y, j* mCellSize + (scale-1) * mCellSize /2)
            );
            set2.setInterpolator(new DecelerateInterpolator());
            set2.setDuration(DURATION);

            set1.addListener(makeHardwareLayerListener(v));

            set1.start();
            set2.start();
        } else {
            v.setX(i * mCellSize + (scale-1) * mCellSize /2);
            v.setY(j * mCellSize + (scale-1) * mCellSize /2);
            v.setScaleX((float) scale);
            v.setScaleY((float) scale);
            v.setRotation(rot);
        }
    
intrandom_color()

      
//        return 0xFF000000 | (int) (Math.random() * (float) 0xFFFFFF); // totally random
        final int COLORS = 12;
        hsv[0] = irand(0,COLORS) * (360f/COLORS);
        return Color.HSVToColor(hsv);
    
public voidstart()

        if (!mStarted) {
            mStarted = true;
            fillFreeList(DURATION * 4);
        }
        mHandler.postDelayed(mJuggle, START_DELAY);
    
public voidstop()

        mStarted = false;
        mHandler.removeCallbacks(mJuggle);