转载请标明出处:
http://blog.csdn.net/Iamzgx/article/details/53168567
本文出自:【iGoach的博客】

最近一直在做直播的功能,所以平时也抽时间总结下这些功能,今天就来说下直播间玩色子游戏,这个功能在抱抱app里面就有。感兴趣的同学可以去看下。

其实这功能也不算太难,只能说他是AnimatorSet的结合体,把步骤分清楚就好写了,连TypeEvaluator接口都不用实现。

注意:这里说的是使用AnimatorSet,不是AnimationSet。他两有什么区别呢?AnimatorSet用于Property Animation,AnimationSet用于View Animation。现在google提倡使用Property Animation。而且很早就提供了nineoldandroids向下兼容包,这里我们也用这个兼容包.

这个动画仔细看下,我们会发现,它的动画范围是在整个屏幕,那么我们可以先准备好我们要做动画的View,然后把这些动画通过AnimatorSet串联起来start就行了。下面就来创建这些View吧。
首先是带色子的托盘,我们可以通过自定义LinearLayout创建,这个ViewGroup可以通过设置的点数显示不同的色子点数。把它命名为DiceLayout。先定义它的几个属性

 <declare-styleable name="DiceLayout"><attr name="drawableName" format="string"/><attr name="isTray" format="boolean"/></declare-styleable>

这里解释下上面的几个属性,drawableName主要是通过getIdentifier找资源的时候要用到的资源名。isTray主要控制色子是否是水平排列。

属性定义好之后,接下来就是查找属性然后添加色子view,具体看下面代码

public DiceLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DiceLayout);drawableName = typedArray.getString(R.styleable.DiceLayout_drawableName);isTray = typedArray.getBoolean(R.styleable.DiceLayout_isTray,true);if(TextUtils.isEmpty(drawableName))drawableName = DEFAULT_DRAWABLE_NAME;typedArray.recycle();setGravity(Gravity.CENTER);setOrientation(LinearLayout.HORIZONTAL);Random random = new Random();setDiceNum(new int[]{1+random.nextInt(6),1+random.nextInt(6),1+random.nextInt(6)});}public void setTray(boolean tray) {isTray = tray;}public void setDrawableName(String drawableName) {if(!TextUtils.isEmpty(drawableName))this.drawableName = drawableName;}private ImageView addDiceView(int position){ImageView imageView = new ImageView(getContext());LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);if(isTray){if(position!=0)layoutParams.leftMargin = DensityUtil.dip2px(getContext(),5);if(position!=1)layoutParams.bottomMargin = DensityUtil.dip2px(getContext(),5);}imageView.setLayoutParams(layoutParams);imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);return imageView;}

上面主要是查找属性进行初始化,然后设置一个默认的初始化点数。同时添加了set属性方法。
然后实现对外设置色子数方法

    public void setDiceNum(int[] rockNumberResults){if(rockNumberResults.length!=3)rockNumberResults = new int[]{1,1,1};int firstDiceNum = cling(1,6,rockNumberResults[0]);int secondDiceNum = cling(1,6,rockNumberResults[1]);int threeDiceNum = cling(1,6,rockNumberResults[2]);removeAllViews();int firstDiceRes = getContext().getResources().getIdentifier(drawableName+firstDiceNum,"drawable",getContext().getPackageName());int secondDiceRes = getContext().getResources().getIdentifier(drawableName+secondDiceNum,"drawable",getContext().getPackageName());int threeDiceRes = getContext().getResources().getIdentifier(drawableName+threeDiceNum,"drawable",getContext().getPackageName());for (int i = 0; i < 3; i++) {ImageView childView = addDiceView(i);childView.setImageResource(i==1?secondDiceRes:i==2?threeDiceRes:firstDiceRes);addView(childView);}}public void startRotationAnim(int[] DiceNumberResults){startRotationAnim(DiceNumberResults,-1);}public void startRotationAnim(final int[] DiceNumberResults,final int animTime){for (int i = 0; i < getChildCount(); i++) {View childView = getChildAt(i);if(childView instanceof ImageView){ImageView diceIv = (ImageView)childView;diceIv.setImageResource(R.drawable.dice_user_anim);final AnimationDrawable animDrawable = (AnimationDrawable) diceIv.getDrawable();if(animTime>=0){Observable.timer(animTime, TimeUnit.SECONDS).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Long>() {@Overridepublic void call(Long aLong) {animDrawable.stop();setDiceNum(DiceNumberResults);}});}animDrawable.start();}}}public static int cling(int min, int max, int value) {return Math.min(Math.max(min, value), max);}

解释下上面代码,这里把色子数传递,然后重置色子这三个子view,通过getIdentifier查找资源id设置色子对应点数的图片。其中getIdentifier的使用为

通过getResource获取getIdentifier方法,getIdentifier方法三个参数分别为资源名,资源所在的路径名,资源所在的包名

同时提供一个开始旋转色子数的动画方法startRotationAnim,这里我尝试使用了propertyAnimation来做旋转效果,效果不太好,所以这里我使用Drawable Animation来实现效果更好。由于Drawable Animation只能配置android:oneshot为true or false来执行一遍或者无限循环,所以这里我使用定时器来实现旋转传递的时间animTime后停止动画,定时器使用rxJava实现。

注意Rx需要在build引入包,配置好即可使用,无需jar包

  compile 'io.reactivex:rxandroid:1.1.0'compile 'io.reactivex:rxjava:1.1.0'

同时提供下简单的drawable animation 的xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"android:oneshot="false"><item
        android:drawable="@drawable/dice_d_1"android:duration="10"/><item
        android:drawable="@drawable/dice_d_2"android:duration="10"/><item
        android:drawable="@drawable/dice_d_3"android:duration="10"/><item
        android:drawable="@drawable/dice_d_4"android:duration="10"/><item
        android:drawable="@drawable/dice_d_5"android:duration="10"/><item
        android:drawable="@drawable/dice_d_6"android:duration="10"/><item
        android:drawable="@drawable/dice_d_7"android:duration="10"/>
</animation-list>

托盘创建好之后,接下来通过自定义RelativeLayout,在自定义RelativeLayout里面添加托盘和色盅,以及处理动画。这里命名为DiceAnimLayout

在DiceAnimLayout里面先addView

private void addChildView(){//添加托盘trayLayout = new DiceLayout(getContext());trayLayout.setDrawableName("dice_icon");trayLayout.setTray(true);trayLayout.setBackgroundResource(R.drawable.dice_tray_icon);LayoutParams diceLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);diceLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM,RelativeLayout.TRUE);diceLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);diceLayoutParams.bottomMargin = DensityUtil.dip2px(getContext(),110);trayLayout.setLayoutParams(diceLayoutParams);addView(trayLayout);//添加盖子diceCap = new ImageView(getContext());LayoutParams diceCapParams = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);diceCapParams.addRule(RelativeLayout.CENTER_HORIZONTAL);diceCapParams.topMargin = -DensityUtil.dip2px(getContext(),197);diceCap.setLayoutParams(diceCapParams);diceCap.setScaleType(ImageView.ScaleType.CENTER_CROP);diceCap.setImageResource(R.drawable.dice_cap_icon);addView(diceCap);//添加盖住viewmDiceCapedRl = LayoutInflater.from(getContext()).inflate(R.layout.dice_cap_layout,this,false);addView(mDiceCapedRl);trayLayout.setVisibility(View.INVISIBLE);diceCap.setVisibility(View.INVISIBLE);mDiceCapedRl.setVisibility(View.INVISIBLE);}

上面添加了托盘和色盅,还有就是合起来之后的ViewGroup,这里通过布局来提供,当然可以直接切图,但是这里为了减少图片资源,所以这样处理
dice_cap_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:layout_marginBottom="110dp"android:layout_height="217dp"><ImageView
        android:layout_width="wrap_content"android:layout_height="wrap_content"android:scaleType="centerCrop"android:layout_alignParentBottom="true"android:src="@drawable/dice_tray_icon"/><ImageView
        android:layout_width="wrap_content"android:layout_height="wrap_content"android:scaleType="centerCrop"android:src="@drawable/dice_cap_icon"/>
</RelativeLayout>

添加好view之后,我们就要来分析下这个动画步骤了。

  1. 色盅掉下来移动到托盘地方
  2. 色盅和托盘合起来之后向下缓冲移动一点距离
  3. 然后向上移动一段距离,
  4. 再左右旋转30度,循环执行动画几次
  5. 然后下移到托盘位置,
  6. 色盅上移打开
  7. 托盘显示色子,显示2s后消失

具体看下代码

 private DiceLayout trayLayout;private ImageView diceCap;private View mDiceCapedRl;private AnimatorSet allAnimSet;//托盘合起来的高度private final int DICE_CAPED_HEIGHT = DensityUtil.dip2px(getContext(),17) ;//合起来后向上移动的位置private final int UP_AND_DOWN_Y = DensityUtil.dip2px(getContext(),193) ;//合起来后向下缓冲位移private final int MOVE_BUFFER_Y = DensityUtil.dip2px(getContext(),10) ;private final int ANIM_DURING_TIME = 500 ;private AnimEndListener animEndListener;
public void startAnimation(final int[] rockNumberResults){if(allAnimSet.isStarted())return;diceCap.setVisibility(View.VISIBLE);trayLayout.setVisibility(View.VISIBLE);trayLayout.setAlpha(1.0f);mDiceCapedRl.setVisibility(View.INVISIBLE);//托盘高度为DICE_CAPED_HEIGHTValueAnimator capTransAnim = ObjectAnimator.ofFloat(diceCap,"translationY",0,trayLayout.getBottom()- DICE_CAPED_HEIGHT);capTransAnim.setDuration(ANIM_DURING_TIME);capTransAnim.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);mDiceCapedRl.setVisibility(View.VISIBLE);diceCap.setVisibility(View.INVISIBLE);trayLayout.setVisibility(View.INVISIBLE);animation.removeAllListeners();}});//合起来之后向下缓冲运动ValueAnimator downDiceCapedTransAnim = ObjectAnimator.ofFloat(mDiceCapedRl,"translationY",0,MOVE_BUFFER_Y);downDiceCapedTransAnim.setInterpolator(new DecelerateInterpolator());downDiceCapedTransAnim.setDuration(20);//合起来之后向上移动ValueAnimator upTransAnim = ObjectAnimator.ofFloat(mDiceCapedRl,"translationY",MOVE_BUFFER_Y,-UP_AND_DOWN_Y);upTransAnim.setDuration(ANIM_DURING_TIME);//旋转ValueAnimator rotationAnim = ObjectAnimator.ofFloat(mDiceCapedRl,"rotation",30.0f,-30.0f,0.0f);mDiceCapedRl.setPivotX(mDiceCapedRl.getWidth()/2);mDiceCapedRl.setPivotY(0);rotationAnim.setRepeatCount(5);rotationAnim.setDuration(ANIM_DURING_TIME);//向下移动ValueAnimator downTransAnim = ObjectAnimator.ofFloat(mDiceCapedRl,"translationY",-UP_AND_DOWN_Y,0);upTransAnim.setDuration(ANIM_DURING_TIME);//盖子向上移动消失ValueAnimator capUpAnim = ObjectAnimator.ofFloat(diceCap,"translationY",mDiceCapedRl.getBottom()- DICE_CAPED_HEIGHT,0);capUpAnim.setDuration(ANIM_DURING_TIME);capUpAnim.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationStart(Animator animation) {super.onAnimationStart(animation);mDiceCapedRl.setVisibility(View.INVISIBLE);setDiceTrayNum(rockNumberResults);diceCap.setVisibility(View.VISIBLE);trayLayout.setVisibility(View.VISIBLE);}@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);diceCap.setVisibility(View.INVISIBLE);if(animEndListener!=null)animEndListener.AnimEnd();animation.removeAllListeners();}});//托盘显示2s后消失ValueAnimator trayAlphaAnim = ObjectAnimator.ofFloat(trayLayout,"alpha",1.0f,0.0f);trayAlphaAnim.setDuration(50);trayAlphaAnim.setStartDelay(2000);allAnimSet.playSequentially(capTransAnim,downDiceCapedTransAnim,upTransAnim,rotationAnim,downTransAnim,capUpAnim,trayAlphaAnim);allAnimSet.start();}public void setDiceTrayNum(int[] rockNumberResults){trayLayout.setDiceNum(rockNumberResults);}public void setAnimEndListener(AnimEndListener animEndListener){this.animEndListener = animEndListener;}public interface AnimEndListener{void AnimEnd();}

上面代码只要按照上面步骤看,就很简单了。在合起来的时候我们把托盘和色盅暂时INVISIBLE,合起来的View显示出来,然后对合起来的View进行动画操作,通过AnimatorSet来结合translationY移动动画,rotation旋转动画,这里旋转5个周期,以及alpha透明动画,具体位置可以getBottom()活着getTop()等方法获取。具体按标注给的效果图调整

注意

view.getBottom()或者view.getTop(),view.getWidth无法再onCreate等这些view还没绘制完前就调用的方法里面获取,所以我们要在veiw绘制完之后调用这些方法才有效果

最后来看下类似直播送礼的动效展示色子点数,实现和DiceAnimLayout类似,这里叫DiceUserAnimLayout。

首先我们定义一些view属性

private LayoutInflater mLayoutInflater;private View mFirstLineDiceView;private View mSecondLineDiceView;private View mThreeLineDiceView;private AnimatorSet mFirstAnimatorSet;private AnimatorSet mSecondAnimatorSet;private AnimatorSet mThreeAnimatorSet;private List<DicePo> mFirstAnimList;private List<DicePo> mSecondAnimList;private List<DicePo> mThreeAnimList;private boolean firstIsShow;private boolean secondIsShow;private boolean threeIsShow;

这里创建的是三行效果,所以需要三行view,分别对应一个AnimatorSet 和一个是否显示的标示

同样以布局实现效果,效果和布局如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/trans_round_shape"android:orientation="horizontal"><LinearLayout
        android:layout_width="0dp"android:layout_height="match_parent"android:orientation="vertical"android:layout_marginRight="5dp"android:layout_marginLeft="20dp"android:layout_marginBottom="3dp"android:layout_weight="1"><TextView
            android:id="@+id/id_play_gift_name_tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="@android:color/white"android:textSize="10sp"android:maxEms="8"android:ellipsize="end"android:singleLine="true"android:text="昵称"android:layout_marginTop="1dp"android:layout_marginBottom="1dp"/><com.common.animdemo.view.DiceLayout
            android:id="@+id/id_user_dice_dl"android:layout_width="wrap_content"android:layout_height="wrap_content"app:drawableName="img_dmx_sz_"app:isTray="false"/></LinearLayout><ImageView
        android:id="@+id/id_dice_user_head_icon_iv"android:layout_width="35dp"android:layout_height="35dp"android:layout_margin="2dp"android:scaleType="centerCrop"android:src="@drawable/head"/>
</LinearLayout>

把布局绑定在三个view上面,实现三行的效果。

public DiceUserAnimLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);setOrientation(LinearLayout.VERTICAL);mFirstAnimList = new ArrayList<>();mSecondAnimList = new ArrayList<>();mThreeAnimList = new ArrayList<>();mLayoutInflater = LayoutInflater.from(getContext());mFirstLineDiceView = mLayoutInflater.inflate(R.layout.dice_user_layout,this,false);mSecondLineDiceView = mLayoutInflater.inflate(R.layout.dice_user_layout,this,false);mThreeLineDiceView = mLayoutInflater.inflate(R.layout.dice_user_layout,this,false);LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);layoutParams.bottomMargin = DensityUtil.dip2px(getContext(),5);addView(mFirstLineDiceView,layoutParams);addView(mSecondLineDiceView,layoutParams);addView(mThreeLineDiceView,layoutParams);mFirstLineDiceView.setVisibility(View.INVISIBLE);mSecondLineDiceView.setVisibility(View.INVISIBLE);mThreeLineDiceView.setVisibility(View.INVISIBLE);mFirstAnimatorSet = new AnimatorSet();mSecondAnimatorSet = new AnimatorSet();mThreeAnimatorSet = new AnimatorSet();}

上面代码主要作用是,通过布局获取三个View,然后把View添加到DiceUserAnimLayout里面。然后初始化,这里三个View初始化为INVISIBLE的原因是:如果初始化为GONE,GONE是不会去绘制View的,所以会导致后面获取不到具体位置。最后初始化三个AnimatorSet和通过ArrayList实现的三个队列

接下来我们再设置动画

public void showAnimator(ResultMsgBody resultMsgBody){if(mThreeAnimList.size()<=mSecondAnimList.size()&&mThreeAnimList.size()<=mFirstAnimList.size()){mThreeAnimList.add(resultMsgBody);startThreeAnimator();}else if(mSecondAnimList.size()<=mFirstAnimList.size()&&mSecondAnimList.size()<=mThreeAnimList.size()){mSecondAnimList.add(resultMsgBody);startSecondAnimator();}else{mFirstAnimList.add(resultMsgBody);startFirstAnimator();}}private void startThreeAnimator(){if(!threeIsShow){if(mThreeAnimList.isEmpty())return;threeIsShow = true ;setViewAnim(mThreeAnimList,mThreeAnimatorSet,mThreeLineDiceView, new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);if(!mThreeAnimList.isEmpty()){animation.removeAllListeners();mThreeAnimList.remove(mThreeAnimList.get(0));threeIsShow = false ;startThreeAnimator();}}});}}private void startSecondAnimator(){if(!secondIsShow){if(mSecondAnimList.isEmpty())return;secondIsShow = true ;setViewAnim(mSecondAnimList,mSecondAnimatorSet,mSecondLineDiceView, new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);if(!mSecondAnimList.isEmpty()){animation.removeAllListeners();mSecondAnimList.remove(mSecondAnimList.get(0));secondIsShow = false ;startSecondAnimator();}}});}}private void startFirstAnimator(){if(!firstIsShow){if(mFirstAnimList.isEmpty())return;firstIsShow = true ;setViewAnim(mFirstAnimList, mFirstAnimatorSet, mFirstLineDiceView, new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);if(!mFirstAnimList.isEmpty()){animation.removeAllListeners();mFirstAnimList.remove(mFirstAnimList.get(0));firstIsShow = false ;startFirstAnimator();}}});}}private void setViewAnim(final List<ResultMsgBody> mAnimList,final AnimatorSet animatorSet,final View animView,Animator.AnimatorListener listener){if(getContext() instanceof CameraActivity){if(mAnimList.get(0).getSound()==1)soundPoolHelper.startPlay();if(mAnimList.get(0).getVibrate()==1)vibrator.vibrate(1000);}final DiceLayout diceLayout = (DiceLayout) animView.findViewById(R.id.id_user_dice_dl);ImageView mDiceUserHead = (ImageView) animView.findViewById(R.id.id_dice_user_head_icon_iv);TextView mDiceUserNickNameTv = (TextView) animView.findViewById(R.id.id_play_gift_name_tv);mDiceUserNickNameTv.setText(mAnimList.get(0).getSendUserInfo().getNickname());String nickNameColor = mAnimList.get(0).getSendUserInfo().getNicknameColor();if(!TextUtils.isEmpty(nickNameColor))mDiceUserNickNameTv.setTextColor(Color.parseColor(nickNameColor));GlideUtils.loadCircleImageView(mDiceUserHead,BitmapUtil.cropWAndHImg(mAnimList.get(0).getSendUserInfo().getAvatar(),DensityUtil.dip2px(ForumsApplication.getInstance(),35),DensityUtil.dip2px(ForumsApplication.getInstance(),35)),R.drawable.head,R.drawable.head);ValueAnimator mTransAnimator = ObjectAnimator.ofFloat(animView,"translationX",animView.getRight(),animView.getRight()-animView.getWidth());mTransAnimator.cancel();mTransAnimator.setDuration(2000);mTransAnimator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationStart(Animator animation) {super.onAnimationStart(animation);animView.setAlpha(1.0f);animView.setVisibility(View.VISIBLE);diceLayout.startRotationAnim(((DiceUserContent)mAnimList.get(0).getMsgBody()).getRockNumberResults(),2);}@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);animation.removeAllListeners();}});ValueAnimator alphaAnimator = ObjectAnimator.ofFloat(animView,"alpha",1.0f,0.0f);alphaAnimator.setDuration(500);alphaAnimator.setStartDelay(4000);alphaAnimator.addListener(listener);animatorSet.playSequentially(mTransAnimator,alphaAnimator);animatorSet.start();}

在外部我们只需要把数据设置进来就行,然后来判断三个队列哪个队列最少数据,把设置进来的数据添加到最少数据的队列里面,然后通过动画逐个展示队列里面的数据。展示完之后我们会在onAnimationEnd把addListener数据清理掉,否则onAnimationEnd会执行很多遍,从而会导致队列显示不正确的BUG,或者引起其他bug,为什么会执行多遍呢,查看下Animator源码就知道了。

public void addListener(AnimatorListener listener) {if (mListeners == null) {mListeners = new ArrayList<AnimatorListener>();}mListeners.add(listener);}

它是通过ArrayList保存起来了,所以每次addListener都会通过ArrayList保存。

View布局准备好后,接下来就在MainActivity里面来使用下

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"><com.common.animdemo.view.DiceAnimLayout
        android:id="@+id/id_dice_anim_layout"android:layout_width="match_parent"android:layout_height="match_parent"/><com.common.animdemo.view.DiceUserAnimLayout
        android:id="@+id/id_user_anim_layout"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_marginTop="30dp"/><LinearLayout
        android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:orientation="horizontal"><Button
            android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="点击开始摇色子动画"android:onClick="startRockDiceClick"/><Button
            android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="点击出现用户消息动画"android:onClick="startUserDiceClick"/></LinearLayout>
</RelativeLayout>
public class MainActivity extends AppCompatActivity {private DiceAnimLayout mDiceAnimLayout;private DiceUserAnimLayout mDiceUserAnimLayout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mDiceAnimLayout = (DiceAnimLayout)findViewById(R.id.id_dice_anim_layout);mDiceUserAnimLayout = (DiceUserAnimLayout)findViewById(R.id.id_user_anim_layout);}public void startRockDiceClick(View view){int[] rockNumArr = new int[3];Random random = new Random();rockNumArr[0] = random.nextInt(6)+1;rockNumArr[1] = random.nextInt(6)+1;rockNumArr[2] = random.nextInt(6)+1;mDiceAnimLayout.startAnimation(rockNumArr);}public void startUserDiceClick(View view){int[] rockNumArr = new int[3];Random random = new Random();rockNumArr[0] = random.nextInt(6)+1;rockNumArr[1] = random.nextInt(6)+1;rockNumArr[2] = random.nextInt(6)+1;DicePo dicePo = new DicePo();dicePo.setUserName("用户昵称");dicePo.setRocketDiceNum(rockNumArr);mDiceUserAnimLayout.showAnimator(dicePo);}
}

通过调用startAnimation和showAnimator方法,然后设置每次的旋转点数和其他数据就可以了。最后来看下动效。我这里连击12下看三行队列的效果

具体感兴趣的可以下载代码查看

仿直播间玩色子游戏,AnimatorSet的综合使用相关推荐

  1. 今天我们来一个升级版本玩色子游戏

    本次的题目比前一次要难一些,但是大家认真思考于我写的代码结合,希望大家有所收获!! 题目:终极需求,玩家初始金额为1000元,并且可以选择要进行的游戏玩法,可以猜大小也可以猜单双,确定游戏之后,用户输 ...

  2. 抖音爆火的“弹幕互动游戏”是什么,如何搭建直播间?

    老A最近发现,有一种新型游戏直播悄悄在抖音火了. 直播间里人数一般不多,往往几十个人,上百个人,但观众刷弹幕,刷礼物的热情却高涨.有的主播,播了一个小时,就轻松赚了 112 万音浪(约人民币 11 万 ...

  3. 老A:抖音爆火的“弹幕互动游戏”是什么?该如何搭建直播间?

    老A最近发现,有一种新型游戏直播悄悄在抖音火了. 直播间里人数一般不多,往往几十个人,上百个人,但观众刷弹幕,刷礼物的热情却高涨.有的主播,播了一个小时,就轻松赚了 112 万音浪(约人民币 11 万 ...

  4. 直播间小游戏,带货直播源码如何实现?

    带货直播源码的更新优化速度非常快,而互动小游戏也是现在主流带货直播源码中的常见功能.当然单独拿出某一个小游戏,我们都可以将它看做一个个体,如果与视频直播结合,就可以为直播软件增光添彩了.那么,带货直播 ...

  5. 链叨叨直播间丨CryptoMechaKing——末世机甲“元宇宙游戏”来临

    2021年11月16日周二晚上20:00,链叨叨直播间之大咖分享汇特邀CryptoMechaKing CMO Albrt 进行<CryptoMechaKing--末世机甲"元宇宙游戏& ...

  6. 3个直播间直播未经审批的游戏,斗鱼遭罚款1万元

    近日,贝多财经获悉,武汉斗鱼网络科技有限公司(下称"斗鱼",NASDAQ:DOYU)再次因内容违规而遭到监管处罚. 根据企查查信息,今年10月14日,武汉市文化和旅游局对斗鱼下发的 ...

  7. 小明兄短视频引流变现必火课,最强DOU+玩法 超级变现法则,两天直播间涨粉20W+

    1.小白如何进入短视频领域 2.学会抖音底层逻辑 热门真的太简单了 3.分享必火系列标题模版 4.短视频必火标题模版 5.相同拍摄场景用到底的打造方法 6.服装行业抖音热门直播带货的玩法 7.连爆技术 ...

  8. 抖音直播间没人气?速看让直播间人气快速突破1000人的实战玩法!

    最近嗨妹在看直播的时候,经常看到这样一个现象: 有些抖音号只有几百个粉丝,但直播间在线观看人数却有好几千甚至上万,而且观众非常活跃,并不是刷机器人: 还有的抖音号有小几十万粉丝,但是直播间依然只有几百 ...

  9. 11种提升抖音直播间人气玩法

    好的直播内容能为主播带来人气热度,而高人气也会不断想尽办法创新内容,提供更多好看的内容吸引关注和打赏. 要想提升抖音直播间人气,首先要了解抖音的推荐逻辑. 抖音是如何推荐直播的? 首先抖音会通过大数据 ...

最新文章

  1. 3. SQL -- 存储过程
  2. 中国联通沈阳互联网数据中心
  3. Python知识点4——if分支与while循环
  4. 电商ERP vs.传统ERP,有何不一样?
  5. 保护 wp cron.php,wp-cron.php任务的定时执行和控制
  6. java ssm 多租户_(十一)java B2B2C 源码 多级分销springmvc mybatis多租户电子商城系统- SSO单点登录之OAuth2.0登录流程(2)...
  7. Cisco网络防火墙配置方法
  8. 0224 2101循环笔记
  9. python字符串_python的字符串怎么拼接
  10. PHP里的“夏令虫”
  11. Qt窗口部件——QFrame/QAbstractButton/QLineEdit/QAbstractSpinBox/QAbstractSlider
  12. 关于DHCP的中继问题
  13. 通信upf是什么意思_中兴通讯全场景UPF 极简设计,随需而动
  14. 新加坡经验:大数据时代政府的角色
  15. django 模型choice基本讲解
  16. 【问题】SQL远程过程调用失败
  17. 记一次流量分析实战——安恒科技(八月ctf)
  18. 啥是原神?女友说想要全角色语音+表情包,顺手用python把高清图也整下来了
  19. 阿ken的HTML、CSS的学习笔记_浮动与定位(笔记六)
  20. 好消息!ios10越狱插件造成桌面图标消失的完美解决方法来了!!!

热门文章

  1. 马云:我说了很久的DT时代,你们明白了吗?
  2. 【JsvaScript】——运算符
  3. 扫地机器人湿地_石头扫地机器人体验:拖地更方便更好了,能给爸妈买吗?| 验货...
  4. 为什么用了高防还是被DDoS打死
  5. pageHelper简单使用过程
  6. 一本python学习的好书
  7. 通过答卷分析对学生水平进行评价
  8. 三大运营商的网络制式
  9. 【Linux命令】文件和目录权限
  10. matlab初步学习1