美文网首页api 架构
Android 9宫格抽奖 不是类似PPT那种样子

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

作者: 一个冬季 | 来源:发表于2019-12-20 23:38 被阅读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的宽度,所以这里表示的是我们每一边最多移动多少距离

    相关文章

      网友评论

        本文标题:Android 9宫格抽奖 不是类似PPT那种样子

        本文链接:https://www.haomeiwen.com/subject/bbfinctx.html