转载请标明出处:
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>() {
@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之后,我们就要来分析下这个动画步骤了。
- 色盅掉下来移动到托盘地方
- 色盅和托盘合起来之后向下缓冲移动一点距离
- 然后向上移动一段距离,
- 再左右旋转30度,循环执行动画几次
- 然后下移到托盘位置,
- 色盅上移打开
- 托盘显示色子,显示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下看三行队列的效果
具体感兴趣的可以下载代码查看