参考文献
抽奖.gif代码
需求描述
需要做一个抽奖的效果,网上搜索了一下,发现没有搜索到那个可以移动的正方形的圈圈,只是搜索到了修改每个圈圈的颜色的这种的,上面的那一篇博客写的很好,给了我很大的思路。我这个是另外的一个思路
让人感觉的头痛点
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的宽度,所以这里表示的是我们每一边最多移动多少距离
网友评论