最近一直在做直播的功能,所以平时也抽时间总结下这些功能,今天就来说下直播间玩色子游戏,这个功能在抱抱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>() { @Override public 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); //添加盖住view mDiceCapedRl = 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_HEIGHT ValueAnimator capTransAnim = ObjectAnimator.ofFloat(diceCap,"translationY",0,trayLayout.getBottom()- DICE_CAPED_HEIGHT); capTransAnim.setDuration(ANIM_DURING_TIME); capTransAnim.addListener(new AnimatorListenerAdapter() { @Override public 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() { @Override public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); mDiceCapedRl.setVisibility(View.INVISIBLE); setDiceTrayNum(rockNumberResults); diceCap.setVisibility(View.VISIBLE); trayLayout.setVisibility(View.VISIBLE); } @Override public 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() { @Override public 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() { @Override public 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() { @Override public 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() { @Override public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); animView.setAlpha(1.0f); animView.setVisibility(View.VISIBLE); diceLayout.startRotationAnim(((DiceUserContent)mAnimList.get(0).getMsgBody()).getRockNumberResults(),2); } @Override public 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; @Override protected 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下看三行队列的效果
具体感兴趣的可以下载代码查看
作者:iGoach