api 架构

Android 9宫格抽奖 不是类似PPT那种样子

2019-12-20  本文已影响0人  一个冬季
参考文献

Android超简单实现九宫格抽奖

抽奖.gif
代码

9宫格抽奖Demo

需求描述

需要做一个抽奖的效果,网上搜索了一下,发现没有搜索到那个可以移动的正方形的圈圈,只是搜索到了修改每个圈圈的颜色的这种的,上面的那一篇博客写的很好,给了我很大的思路。我这个是另外的一个思路

让人感觉的头痛点

1、计算每个正方形的位置
2、如何完美的移动到我需要的位置

设计思路
布局方向.jpg

这些数字都是中奖View的位置。现在如何让移动的框框,正好的框在每一个View上面?如下面展示的,我红色的框框是一个透明的FrameLayout,它的作用就是保证包裹每一个黑色的框,且是要是剧中的。蓝色是一张图片,在FrameLayout里面,且是剧中显示的,当然蓝色的宽高要 > 黑色的宽高,黑色的框框0....11表示的是每个中奖的View。所以我们每次都TransLayoutX/Y红色的框框就OK啦


布局解释图.jpg
画出12个中奖View代码
   /**
     * @date :2019/12/17 0017
     * @author : gaoxiaoxiong
     * @description:创建12个Viwe视图
     **/
    private View createView(int position) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.view_child_tweleveluck, this, false);
        LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        view.setLayoutParams(layoutParams);
        view.setBackgroundColor(ContextCompat.getColor(mContext, R.color.white));
        ImageView imageView = view.findViewById(R.id.iv_view_child_tweleveluck);
        imageView.setImageResource(mImgs[position % 3]);
        return view;
    }

    /**
     * @date :2019/12/20 0020
     * @author : gaoxiaoxiong
     * @description:创建12个Viwe视图
     **/
    public void updateView() {
        removeAllViews();
        for (int i = 0; i < 12; i++) {
            viewList.add(createView(i));
            addView(viewList.get(i));
        }
    }

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mRectParentWidth = getMeasuredWidth();
        itemWidthHeight = (mRectParentWidth - itemSpace * 5) / 4;
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View view = viewList.get(i);
            LayoutParams layoutParams = view.getLayoutParams();
            layoutParams.width = itemWidthHeight;
            layoutParams.height = itemWidthHeight;
            view.setLayoutParams(layoutParams);
            measureChild(view, widthMeasureSpec, heightMeasureSpec);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        //前3个
        int left = 0, top = 0, right = 0, bottom = 0;
        top = itemSpace;
        left = itemSpace;
        for (int i = 0; i < 3; i++) {
            View view = viewList.get(i);
            view.layout(left, top, left + itemWidthHeight, top + itemWidthHeight);
            left = left + itemWidthHeight + itemSpace;
        }

        //右边4个
        left = 3 * (itemWidthHeight + itemSpace) + itemSpace;
        top = itemSpace;
        bottom = itemSpace + itemWidthHeight;
        for (int i = 3; i < 7; i++) {
            right = left + itemWidthHeight;
            View view = viewList.get(i);
            view.layout(left, top, right, bottom);
            top = top + itemWidthHeight + itemSpace;
            bottom = bottom + itemSpace + itemWidthHeight;
        }

        //底部3个
        top = (itemSpace + itemWidthHeight) * 3 + itemSpace;
        bottom = top + itemWidthHeight;
        left = (itemSpace + itemWidthHeight) * 2 + itemSpace;
        right = left + itemWidthHeight;
        for (int i = 7; i < 10; i++) {
            View view = viewList.get(i);
            view.layout(left, top , right, bottom);
            left = left - (itemSpace + itemWidthHeight);
            right = left + itemWidthHeight;
        }
        //左边2个
        left = itemSpace;
        right = itemSpace + itemWidthHeight;
        top = 2 * (itemWidthHeight + itemSpace) + itemSpace;
        bottom = top + itemWidthHeight;
        for (int i = 10; i < 12; i++) {
            View view = viewList.get(i);
            view.layout(left , top , right, bottom);
            top = top - (itemWidthHeight + itemSpace);
            bottom = top + itemWidthHeight;
        }
    }
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/shape_rectangle_solid_white_corner5">
    <ImageView
        android:id="@+id/iv_view_child_tweleveluck"
        android:layout_width="match_parent"
        android:layout_gravity="center"
        android:layout_height="match_parent" />
</FrameLayout>

因为我们中奖的View都是通过LayoutInflater.from(mContext).inflate出来的,所以我们可以保证这个View里面的图片一定是剧中的,如上面的GIF里面的白菜/龙虾,而且我们还可以设置View的背景 + 是否圆角等等。

移动红色的框框到指定的位置
<FrameLayout
        android:layout_width="314dp"
        android:layout_height="314dp"
        android:layout_gravity="center"
        android:background="@drawable/shape_rectangle_solid_white_corner5">
        <!--12个View的父容器-->
        <com.example.myapplication.TwelveLuckPanLayoutV2
            android:id="@+id/luck_drawa_twelevluck"
            android:layout_width="308dp"
            android:layout_height="308dp"
            android:layout_gravity="center"
            android:background="@color/liba_720f1b" />
        <!--开始按钮-->
        <ImageView
            android:id="@+id/luck_drawa_startchou"
            android:layout_width="140dp"
            android:layout_height="140dp"
            android:layout_gravity="center"
            android:src="@drawable/icon_go" />
        <!--和TwelveLuckPanLayoutV2宽高大小保持一致,为了后面计算方便-->
        <FrameLayout
            android:layout_width="308dp"
            android:layout_height="308dp"
            android:layout_gravity="center">
            <!--红色的FrameLayout-->
            <FrameLayout
                android:id="@+id/fl_luck_drawa_work_kuang"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <!--蓝色的ImageView-->
                <ImageView
                    android:id="@+id/iv_luck_drawa_work_kuang"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_gravity="center"
                    android:scaleType="fitXY"
                    android:src="@mipmap/icon_work_kuang" />
            </FrameLayout>
        </FrameLayout>
    </FrameLayout>

这里要特别注意的有2点
1、有2个View都是308dp的宽高,都是在父容器里面剧中的,还有就是是为了保证在计算移动红色FrameLayout的时候减少错误
2、红色的FrameLayout包裹着一个ImageView且是剧中的模式

/**
    * @date: 创建时间:2019/12/20
    * @author: gaoxiaoxiong
    * @descripion:需要中奖的View
    **/
    public void onPosition(final int position) {
       final int totalWidth = twelveLuckPanLayout.getmRectParentWidth() - twelveLuckPanLayout.getmRectParentWidth() / 4;//一条直线上的
       final int oneItem = twelveLuckPanLayout.getmRectParentWidth() / 4;//一个的Item
       final   ValueAnimator valueAnimator = ValueAnimator.ofInt(0, oneItem * 12);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int currentValue = (int) animation.getAnimatedValue();
                float percent = (float) currentValue / ((float) totalWidth * 4);
                if (currentValue >= 0 && currentValue <= totalWidth) {//第一排
                    flWorkKuangLayout.setTranslationX(percent * totalWidth * 4);
                    flWorkKuangLayout.setTranslationY(0);
                } else if (currentValue > totalWidth && currentValue <= totalWidth * 2) {//第二
                    flWorkKuangLayout.setTranslationX(twelveLuckPanLayout.getmRectParentWidth() - flWorkKuangLayout.getWidth());
                    float release = percent * totalWidth * 4 - totalWidth;
                    flWorkKuangLayout.setTranslationY(release);
                } else if (currentValue > totalWidth * 2 && currentValue <= totalWidth * 3) {//第三
                    flWorkKuangLayout.setTranslationY(totalWidth);
                    float release = percent * totalWidth * 4 - totalWidth * 3;
                    flWorkKuangLayout.setTranslationX(-release);
                } else if (currentValue > totalWidth * 3 && currentValue <= totalWidth * 4) {//第四
                    float release = percent * totalWidth * 4 - totalWidth * 4;
                    flWorkKuangLayout.setTranslationY(-release);
                    flWorkKuangLayout.setTranslationX(0);
                }
                if (currentValue == totalWidth * 4) {
                    flWorkKuangLayout.setTranslationY(0);
                    flWorkKuangLayout.setTranslationX(0);
                }

                if (repecount == 2 && !isSetting) {
                    int trans = oneItem * position;
                    valueAnimator.setIntValues(trans);
                    isSetting = true;
                }
            }
        });
        valueAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                int trans = oneItem * position;
                if (trans >= 0 && trans <= totalWidth) {//第一排
                    flWorkKuangLayout.setTranslationX(twelveLuckPanLayout.getChildAt(position).getLeft() - twelveLuckPanLayout.getItemSpace());
                } else if (trans > totalWidth && trans <= totalWidth * 2) {//第二
                    flWorkKuangLayout.setTranslationY(twelveLuckPanLayout.getChildAt(position).getTop() - twelveLuckPanLayout.getItemSpace());
                } else if (trans > totalWidth * 2 && trans <= totalWidth * 3) {//第三
                    flWorkKuangLayout.setTranslationY(twelveLuckPanLayout.getChildAt(position).getTop() - twelveLuckPanLayout.getItemSpace());
                    flWorkKuangLayout.setTranslationX(twelveLuckPanLayout.getChildAt(position).getLeft() - twelveLuckPanLayout.getItemSpace());
                } else if (trans > totalWidth * 3 && trans <= totalWidth * 4) {//第四
                    flWorkKuangLayout.setTranslationY(twelveLuckPanLayout.getChildAt(position).getTop() - twelveLuckPanLayout.getItemSpace());
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                repecount = repecount + 1;
                flWorkKuangLayout.setTranslationY(0);
                flWorkKuangLayout.setTranslationX(0);
            }
        });
        valueAnimator.setRepeatCount(2);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setDuration(1000);
        valueAnimator.start();
    }

我们红色框框转一圈所需要移动的距离是12 * oneItem ,在这里我们先让他故意转2圈,当到了第二圈的时候我们通过

           if (repecount == 2 && !isSetting) {
                    int trans = oneItem * position;
                    valueAnimator.setIntValues(trans);
                    isSetting = true;
                }

来锁定最后他移动到的位置,我们每次移动都是移动整个红色的框框
totalWidth:我们从 0 位置 移动到 3位置,我们实际移动的是3个item的宽度,所以这里表示的是我们每一边最多移动多少距离

上一篇 下一篇

猜你喜欢

热点阅读