支付宝会员积分使用支付宝支付之后会有支付积分产生,这个需要自己手动的去收集,否则不能使用。公司是做文章阅读的,目前有一个需求是需要点击一个按钮,手动的手机阅读文章的磁能分数,类似支付宝的蚂蚁森林收集水滴的效果,如下图所示:

点击立即收取之后需要有个类似支付宝的蚂蚁森林的收集水滴的效果,然后反转中间的按钮,把所有的积分统计出来。
下面的代码示自定义控件的具体实现:

/*** 收集词能的自定义动画* @author guotianhui*/
public class CollectWordsLayout extends RelativeLayout {private int mDefaultEnergyScore;private String mTotalEnergyScore;private boolean isFlipCard = true;private final LayoutInflater mInflater;private boolean isOpenAnimation;//是否开启动画0private boolean isCancelAnimation;//是否销毁动画private boolean isInitLayout =true;private FrameLayout mBtnCollectWords;private final Random mRandom = new Random();private boolean isCollectWords = true;private ArrayList<WordEnergy> mEnergyList; //设置词能集合private RelativeLayout mCollectWordLayout;private CountScoreTextView mTvCollectScore;private AppCompatTextView mTvClickCollect;private static final int WHAT_ADD_PROGRESS = 1;private static final int INIT_ANIMATION = 2;private static final int CHANGE_RANGE = 10;  //view变化的y抖动范围public static final int PROGRESS_DELAY_MILLIS = 12; // 控制抖动动画执行的快慢,人眼不能识别16ms以下的public static final int REMOVE_DELAY_MILLIS = 1500; // 控制移除view的动画执行时间private AppCompatTextView mTvTotalEnergyScore,mTotalEnergy;private final ArrayList<Integer> mWordsEnergy = new ArrayList<>();private ArrayList<Point> mViewPoint = new ArrayList<>(); //创建一个界面的坐标点位置private OnAnimationCloseListener mOnAnimationCloseListener; // 动态收起布局的回调public static final int ANIMATION_SHOW_VIEW_DURATION = 500; //添加水滴时动画显示view执行的时间private final ArrayList<Integer> mRandomViewList = new ArrayList<>(); // 随机的词能列表private final ArrayList<WordsItemLayout> mViewList = new ArrayList<>();private final ArrayList<WordEnergy> mCollectEnergyList  = new ArrayList<>(); //收起词能的集合private final List<Float> mSpds = Arrays.asList(0.5f, 0.3f, 0.4f, 0.6f); //控制水滴动画的快慢private WordsItemLayout mWordsItemOne,mWordsItemTwo,mWordsItemThere,mWordsItemFour,mWordsItemFive,mWordsItemSix,mWordsItemSeven,mWordsItemEight,mWordsItemNine,mWordsItemTen,mWordsItemEleven;public CollectWordsLayout(@NonNull Context context) {this(context, null);initCollectWordsLayout();}public CollectWordsLayout(@NonNull Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);initCollectWordsLayout();}public CollectWordsLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mInflater = LayoutInflater.from(getContext());initCollectWordsLayout();}@SuppressLint("HandlerLeak")private final Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case WHAT_ADD_PROGRESS:if (isCancelAnimation) { //根据isCancelAnimtion来标识是否退出,防止界面销毁时,再一次改变UIreturn;}setWordsOffSet();  //改变View的Y轴坐标位置,实现上下移动的效果mHandler.sendEmptyMessageDelayed(WHAT_ADD_PROGRESS, PROGRESS_DELAY_MILLIS);break;case INIT_ANIMATION:startAnimation();break;default:break;}}};private void initCollectWordsLayout() {if(isInitLayout) {View view = mInflater.inflate(R.layout.layout_collect_words, this, false);mCollectWordLayout = view.findViewById(R.id.rl_collect_words_layout);mWordsItemOne = view.findViewById(R.id.wil_words_item_one);mWordsItemTwo = view.findViewById(R.id.wil_words_item_two);mWordsItemThere = view.findViewById(R.id.wil_words_item_there);mWordsItemFour = view.findViewById(R.id.wil_words_item_four);mWordsItemFive = view.findViewById(R.id.wil_words_item_five);mWordsItemSix = view.findViewById(R.id.wil_words_item_six);mWordsItemSeven = view.findViewById(R.id.wil_words_item_seven);mWordsItemEight = view.findViewById(R.id.wil_words_item_eight);mWordsItemNine = view.findViewById(R.id.wil_words_item_nine);mWordsItemTen = view.findViewById(R.id.wil_words_item_ten);mWordsItemEleven = view.findViewById(R.id.wil_words_item_eleven);mViewList.clear(); //先清空列表,再添加数据mViewList.add(mWordsItemOne);mViewList.add(mWordsItemTwo);mViewList.add(mWordsItemThere);mViewList.add(mWordsItemFour);mViewList.add(mWordsItemFive);mViewList.add(mWordsItemSix);mViewList.add(mWordsItemSeven);mViewList.add(mWordsItemEight);mViewList.add(mWordsItemNine);mViewList.add(mWordsItemTen);mViewList.add(mWordsItemEleven);initOtherViewLayout(view); //抽取方法isInitLayout =false; //解决初始化两次的问题}}private void initOtherViewLayout(View view) {mBtnCollectWords = view.findViewById(R.id.fl_click_collect_words);mTvCollectScore = view.findViewById(R.id.tv_collect_score);mTvClickCollect = view.findViewById(R.id.tv_click_collect);mTotalEnergy = view.findViewById(R.id.tv_total_energy);mTvTotalEnergyScore = view.findViewById(R.id.tv_total_energy_score);initLayoutListener();addView(view);addShowViewAnimation(view);mHandler.sendEmptyMessageDelayed(INIT_ANIMATION, 200);}/*** 设置点击事件*/private void initLayoutListener() {mBtnCollectWords.setOnClickListener((view) -> {ViewClickUtils.setViewDelaySecondsClickAble(mBtnCollectWords,2000);if (isCollectWords) {for (int i=0; i< mViewList.size(); i++) {removeViewAnimation(i);}flipAnimatorXViewShow(mTvClickCollect, mTvCollectScore, 500, 0);}});//统计词能结束,翻转卡片mTvCollectScore.setOnFinishCollectListener(totalScore -> {mTotalEnergyScore = totalScore; //返回总的词能分数mDefaultEnergyScore = Integer.valueOf(totalScore);mTvTotalEnergyScore.setText(mTotalEnergyScore);if (isFlipCard) {isFlipCard = false;flipAnimatorXViewShow(mTvCollectScore, mTvClickCollect, 500, 1500);}});}/*** 添加显示动画* @param view*/private void addShowViewAnimation(View view) {view.setAlpha(0);view.setScaleX(0);view.setScaleY(0);view.animate().alpha(1).scaleX(1).scaleY(1).setDuration(ANIMATION_SHOW_VIEW_DURATION).start();}/*** 设置所有子view的加速度*/private void setViewsSpeed() {for (int i = 0; i < mViewList.size(); i++) {View view = mViewList.get(i);setWordsSpeed(view);}}/*** 设置View的运动速度* @param view*/private void setWordsSpeed(View view) {float spd = mSpds.get(mRandom.nextInt(mSpds.size()));view.setTag(R.string.spd, spd);}/*** 设置偏移*/private void setWordsOffSet() {for (int i = 0; i < mViewList.size(); i++) {View view = mViewList.get(i);//拿到上次view保存的速度float spd = (float) view.getTag(R.string.spd);//水滴初始的位置Point point = mViewPoint.get(i);float original = point.y;boolean isUp = (boolean) view.getTag(R.string.isUp);float translationY;//根据水滴tag中的上下移动标识移动viewif (isUp) {translationY = view.getY() - spd;} else {translationY = view.getY() + spd;}//对水滴位移范围的控制if (translationY - original > CHANGE_RANGE) {translationY = original + CHANGE_RANGE;view.setTag(R.string.isUp, true);} else if (translationY - original < -CHANGE_RANGE) {translationY = original - CHANGE_RANGE;// FIXME:每次当水滴回到初始点时再一次设置水滴的速度,从而达到时而快时而慢setWordsSpeed(view);view.setTag(R.string.isUp, false);}view.setY(translationY);}}/*** 移除动画*/private void removeViewAnimation(int i) {WordsItemLayout view = mViewList.get(i);view.clearAnimation();   //清除抖动动画Interpolator Interpolator = new LinearInterpolator();float distanceX = getTarnslationX(view);float distanceY = getTarnslationY(view);ObjectAnimator transYAnim = ObjectAnimator.ofFloat(view, "translationY", distanceY);ObjectAnimator transXAnim = ObjectAnimator.ofFloat(view, "translationX", distanceX);ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(view, "scaleX", 1.0f, 0.0f);ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(view, "scaleY", 1.0f, 0.0f);ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0.0f);AnimatorSet set = new AnimatorSet();set.setInterpolator(Interpolator);set.playTogether(transYAnim, transXAnim, scaleXAnim, scaleYAnim, alphaAnim);set.setDuration(REMOVE_DELAY_MILLIS);set.start();set.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {view.clearAnimation();addShowViewAnimation(view); //还原动画效果//取出原始坐标,让词能位置还原Point point = mViewPoint.get(i);float originalY = point.y;float originalX = point.x;view.setY(originalY);view.setX(originalX);view.setVisibility(View.INVISIBLE);}});}/*** 计算两点移动的X轴距离* @param view* @return*/private float getTarnslationX(View view) {float viewX = view.getRight();float btnX = mBtnCollectWords.getRight();return btnX - viewX;}/*** 计算两点移动的Y轴距离* @param view* @return*/private float getTarnslationY(View view) {float viewY = view.getBottom();float btnY = mBtnCollectWords.getBottom();return btnY - viewY;}/*** 开启水滴抖动动画*/public void startAnimation() {if (isOpenAnimation) {return;}for (WordsItemLayout wordsItemLayout : mViewList) { // 添加上下移动的动画setViewsSpeed();addShowViewAnimation(wordsItemLayout);wordsItemLayout.setTag(R.string.isUp, false); //随机设置view动画的方向Point point = new Point((int) wordsItemLayout.getX(), (int) wordsItemLayout.getY());mViewPoint.add(point);}isOpenAnimation = true;isCancelAnimation = false;mHandler.sendEmptyMessage(WHAT_ADD_PROGRESS);}/*** 初始化词能数据显示*/private void initWordsEnergyData() {if(mEnergyList.size()  >=11) {  //集合大于11时,先显示一屏的数据for(int i=0 ; i< 11; i++) { //先取出一屏显示displayWordEnergyByIndex(i,false);}}else{for(int i=0 ; i< mEnergyList.size(); i++) {initRandomArrayListByBound(i);//初始化不重复的随机数组displayWordEnergyByIndex(i,true);}}}/*** 根据角标获取显示的词能位置* @param i*/private void displayWordEnergyByIndex(int i, boolean isRandom) {WordsItemLayout wordsItemLayout;if(isRandom){int randomIndex = mRandomViewList.get(i);wordsItemLayout = mViewList.get(randomIndex);}else{wordsItemLayout = mViewList.get(i);}WordEnergy wordEnergy = mEnergyList.get(i); //一个词能对应一个ViewwordsItemLayout.setVisibility(View.VISIBLE);wordsItemLayout.setCollectWord(wordEnergy.getWordName());wordsItemLayout.setCollectWordEnergy(wordEnergy.getWordsEnergy());mCollectEnergyList.add(wordEnergy); //本地保存已经显示过的数据mWordsEnergy.add(wordEnergy.getWordsEnergy());}/*** 获取一个不会重复的随机数,范围0-10*/private void initRandomArrayListByBound(int randomSize) {int[] a = new int[randomSize];//初始化数组int count = 0;//记录有效的随机数个数while(count < a.length){boolean flag = true;//用来标志的变量int r = mRandom.nextInt(mViewList.size());for(int i : a){if(r == i){flag = false;break;}}if(flag){a[count] = r;count++;mRandomViewList.add(r); //把不重复的角标值放入集合}}}/*** 提供一个方法,判断显示过的词能集合和网络返回的词能列表是否相同*/private boolean compareLocalWordsNumber(){if(mEnergyList.size() >mCollectEnergyList.size()){int otherSceenList = mEnergyList.size() - mCollectEnergyList.size();int secondIndex = mCollectEnergyList.size(); //取出第二屏数据的起始位置mWordsEnergy.clear();//清空上一次的词能if(otherSceenList >=11){for (int i = 0; i < 11; i++) {showAnotherSceenWords(secondIndex, i,false);}}else {for (int i = 0; i < otherSceenList; i++) {initRandomArrayListByBound(otherSceenList);//初始化不重复的随机数组showAnotherSceenWords(secondIndex, i,true);}}startAnimation(); //重新开启动画return  true;}else{return false;}}/*** 显示其外一屏数据* @param secondIndex* @param i*/private void showAnotherSceenWords(int secondIndex, int i,boolean isRandom) {WordsItemLayout wordsItemLayout;if(isRandom){int randomIndex = mRandomViewList.get(i);wordsItemLayout = mViewList.get(randomIndex);}else{wordsItemLayout = mViewList.get(i);}WordEnergy wordEnergy = mEnergyList.get(i + secondIndex);wordsItemLayout.setVisibility(View.VISIBLE);wordsItemLayout.setCollectWord(wordEnergy.getWordName());wordsItemLayout.setCollectWordEnergy(wordEnergy.getWordsEnergy());mCollectEnergyList.add(wordEnergy);mWordsEnergy.add(wordEnergy.getWordsEnergy());}/*** 销毁*/private void onDestroy() {isCancelAnimation = true;mHandler.removeCallbacksAndMessages(this);}/*** 界面销毁时回调*/@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();onDestroy();}/*** 翻转卡片动画* @param oldView* @param newView* @param duringTime* @param delayeTime*/private void flipAnimatorXViewShow(final View oldView, final View newView, final long duringTime, long delayeTime) {mBtnCollectWords.postDelayed(new Runnable() {@Overridepublic void run() {ObjectAnimator animator1 = ObjectAnimator.ofFloat(oldView, "rotationX", 0, 90);final ObjectAnimator animator2 = ObjectAnimator.ofFloat(newView, "rotationX", -90, 0);animator2.setInterpolator(new OvershootInterpolator(2.0f));animator1.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {oldView.setVisibility(View.GONE);animator2.setDuration(duringTime).start();newView.setVisibility(View.VISIBLE);}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}});animator2.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);if (isCollectWords) {isFlipCard = true;isCollectWords = false;mTvCollectScore.setTotalScore(mDefaultEnergyScore); //初始化词能mTvCollectScore.setCountScoreList(mWordsEnergy);//添加能量值}else{isFlipCard = true;isCollectWords = true;boolean isCompareLocal = compareLocalWordsNumber();//重新初始化词能布局if(!isCompareLocal){if(ObjectUtils.isNotEmpty(mOnAnimationCloseListener)){  //动态收起布局isCancelAnimation = true;mOnAnimationCloseListener.onAnimationClose(); //回调动态收起布局ArrayList<String> arrayList = new ArrayList<>();for(WordEnergy wordEnergy : mEnergyList){arrayList.add(wordEnergy.getWordName());}mOnAnimationCloseListener.onAddCollectWordsToTagCloud(arrayList);}}}}});animator1.setDuration(duringTime).start();}}, delayeTime);}/*** 提供一个方法接收词能集合,并初始化词能值*/public void setWordsEnergyAndTotalScore(ArrayList<WordEnergy> energyList, int totalScore){this.mEnergyList = energyList;this.mDefaultEnergyScore = totalScore;//显示数据initWordsEnergyData();}/*** 动态收起布局方法* @param view*/public void animateCloseLayout(final RelativeLayout view) {view.post(() ->{int origHeight = view.getHeight();ValueAnimator animator = createDropAnimator(view, origHeight, PhoneSystemUtils.dp2px(90,getContext()));animator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {mCollectWordLayout.clearAnimation();mCollectWordLayout.removeAllViews();mCollectWordLayout.addView(mTotalEnergy);mCollectWordLayout.addView(mTvTotalEnergyScore);mTotalEnergy.setVisibility(View.VISIBLE);mTvTotalEnergyScore.setVisibility(View.VISIBLE);mTvTotalEnergyScore.setText(mTotalEnergyScore);mCollectWordLayout.setBackground(getResources().getDrawable(R.drawable.ic_total_score_bg));}});animator.start();});}/*** 动态改变布局高度的属性动画* @param view* @param start* @param end* @return*/private ValueAnimator createDropAnimator(final View view, int start, int end) {ValueAnimator animator = ValueAnimator.ofInt(start, end);animator.addUpdateListener((animation1) ->{int value = (int) animation1.getAnimatedValue();ViewGroup.LayoutParams layoutParams = view.getLayoutParams();layoutParams.height = value;view.setLayoutParams(layoutParams);});return animator;}/*** 设置回调监听* @param listener*/public void setOnAnimationCloseLayout(OnAnimationCloseListener listener){this.mOnAnimationCloseListener = listener;}/*** 提供一个回调接口,动态的收起布局*/public interface OnAnimationCloseListener{void onAnimationClose();void onAddCollectWordsToTagCloud(List<String> tagsList);}
}

自定义控件的布局文件实现:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/rl_collect_words_layout"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/bg_ffe5c4_solid_r10"><android.support.v7.widget.AppCompatTextViewandroid:id="@+id/tv_total_energy"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="总词能"android:textColor="#fff29f87"android:textSize="15sp"android:visibility="gone"android:layout_centerHorizontal="true"android:layout_marginTop="@dimen/dp_15"/><android.support.v7.widget.AppCompatTextViewandroid:id="@+id/tv_total_energy_score"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="8,345"android:textColor="#fff29f87"android:textSize="24sp"android:visibility="gone"android:layout_marginTop="@dimen/dp_8"android:layout_below="@+id/tv_total_energy"android:layout_centerHorizontal="true"/><com.fenji.read.module.student.widget.WordsItemLayoutandroid:id="@+id/wil_words_item_there"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:visibility="invisible"android:layout_marginTop="@dimen/dp_30"android:layout_marginStart="@dimen/dp_22"/><FrameLayoutandroid:id="@+id/fl_click_collect_words"android:layout_width="75dp"android:layout_height="75dp"android:layout_centerHorizontal="true"android:layout_marginTop="@dimen/dp_25"android:layout_below="@+id/wil_words_item_there"android:background="@drawable/bg_collect_words_r75"><com.fenji.read.module.student.widget.CountScoreTextViewandroid:id="@+id/tv_collect_score"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="14sp"android:gravity="center"android:layout_gravity="center"android:background="@drawable/bg_collect_words_r60"android:textColor="@color/white"/><android.support.v7.widget.AppCompatTextViewandroid:id="@+id/tv_click_collect"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="点击领取"android:textSize="14sp"android:gravity="center"android:layout_gravity="center"android:background="@drawable/bg_collect_words_r60"android:textColor="@color/white"/></FrameLayout><com.fenji.read.module.student.widget.WordsItemLayoutandroid:id="@+id/wil_words_item_one"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="@dimen/dp_12"android:visibility="invisible"android:layout_marginStart="@dimen/dp_12"/><com.fenji.read.module.student.widget.WordsItemLayoutandroid:id="@+id/wil_words_item_two"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_toEndOf="@+id/wil_words_item_one"android:layout_marginTop="@dimen/dp_15"android:visibility="invisible"android:layout_marginStart="@dimen/dp_15"/><com.fenji.read.module.student.widget.WordsItemLayoutandroid:id="@+id/wil_words_item_four"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_toStartOf="@+id/wil_words_item_five"android:layout_marginTop="@dimen/dp_20"android:visibility="invisible"android:layout_marginEnd="@dimen/dp_15"/><com.fenji.read.module.student.widget.WordsItemLayoutandroid:id="@+id/wil_words_item_five"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentEnd="true"android:layout_marginTop="@dimen/dp_15"android:visibility="invisible"android:layout_marginEnd="@dimen/dp_15"/><com.fenji.read.module.student.widget.WordsItemLayoutandroid:id="@+id/wil_words_item_six"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/wil_words_item_one"android:layout_marginTop="@dimen/dp_12"android:visibility="invisible"android:layout_marginStart="@dimen/dp_12"/><com.fenji.read.module.student.widget.WordsItemLayoutandroid:id="@+id/wil_words_item_seven"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_toEndOf="@+id/wil_words_item_six"android:layout_below="@+id/wil_words_item_two"android:layout_marginTop="@dimen/dp_15"android:visibility="invisible"android:layout_marginStart="@dimen/dp_15"/><com.fenji.read.module.student.widget.WordsItemLayoutandroid:id="@+id/wil_words_item_eight"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/wil_words_item_four"android:layout_toStartOf="@+id/wil_words_item_nine"android:layout_marginTop="@dimen/dp_15"android:visibility="invisible"android:layout_marginEnd="@dimen/dp_15"/><com.fenji.read.module.student.widget.WordsItemLayoutandroid:id="@+id/wil_words_item_nine"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentEnd="true"android:layout_below="@+id/wil_words_item_five"android:layout_marginTop="@dimen/dp_15"android:visibility="invisible"android:layout_marginEnd="@dimen/dp_15"/><com.fenji.read.module.student.widget.WordsItemLayoutandroid:id="@+id/wil_words_item_ten"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentStart="true"android:layout_marginBottom="@dimen/dp_20"android:visibility="invisible"android:layout_below="@+id/wil_words_item_seven"android:layout_marginTop="@dimen/dp_15"android:layout_marginStart="40dp"/><com.fenji.read.module.student.widget.WordsItemLayoutandroid:id="@+id/wil_words_item_eleven"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentEnd="true"android:visibility="invisible"android:layout_below="@+id/wil_words_item_nine"android:layout_marginTop="@dimen/dp_15"android:layout_marginBottom="@dimen/dp_20"android:layout_marginEnd="40dp"/>
</RelativeLayout>

实例化自定义控件之后,需要手动调用它的方法把词能数据传进去。代码如下:

  ArrayList<WordEnergy> wordEnergies = new ArrayList<>();for (int i = 0; i <14; i++){WordEnergy wordEnergy = new WordEnergy("凤毛麟角",1);wordEnergies.add(wordEnergy);}mCollectWordsLayout.setWordsEnergyAndTotalScore(wordEnergies,50);

数据实体对象代码:

/*** 词云养成的词能数据对象* @author guotianhui*/
public class WordEnergy{public WordEnergy(String name,int energy){this.wordName = name;this.wordsEnergy =energy;}private String wordName;private int wordsEnergy;public String getWordName() {return wordName;}public void setWordName(String wordName) {this.wordName = wordName;}public int getWordsEnergy() {return wordsEnergy;}public void setWordsEnergy(int wordsEnergy) {this.wordsEnergy = wordsEnergy;}
}

最后我把实现积分统计的自定义控件给贴上代码,代码直接可以用,希望对您有用,谢谢!


/*** 动态计分的TextView* @author guotianhui*/
public class CountScoreTextView extends AppCompatTextView{int scoreIndex = 0; //集合取值的角标private Timer mTimer; //定时计数器private int TOTAL_SCORE = 0; //获取的总词能private ArrayList<Integer> mScoreList; //词能集合private OnFinishCollectWords mOnFinishCollectListener;public CountScoreTextView(Context context) {super(context);}public CountScoreTextView(Context context, AttributeSet attrs) {super(context, attrs);}public CountScoreTextView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}/*** 创建一个Handler,不断发送消息让Textview的分数累加,直到完成*/@SuppressLint("HandlerLeak")private final Handler mHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what){case 100:if(msg.arg1 >0) {int score = TOTAL_SCORE + msg.arg1;setText(String.valueOf(score));TOTAL_SCORE = score;if(ObjectUtils.isNotEmpty(mOnFinishCollectListener)){  //回传总词能mOnFinishCollectListener.onFinishCollect(String.valueOf(score));}}break;default:{}break;}}};/*** 创建一个定时任务,循环把集合中的数值取出,并发送消息*/public void startCountScore(){if(mTimer == null) {mTimer = new Timer();mTimer.schedule(new TimerTask() {@Overridepublic void run() {if(mScoreList != null && mScoreList.size() >= scoreIndex) {final Message message = new Message();message.what = 100;message.arg1 = getCountScoreListItem(scoreIndex);mHandler.sendMessage(message);scoreIndex++;}else{//取完所有数值之后,停止计数并清空集合和重置角标stopCountScore();scoreIndex =0;}}}, 0, 30);}}/*** 提供一个方法接收需要添加的数字集合*/public void setCountScoreList(ArrayList<Integer> scoreList){this.mScoreList = scoreList;startCountScore();}/*** 根据角标获取到集合中的能量值并返回* @param scoreIndex* @return*/public int getCountScoreListItem(int scoreIndex) {if(mScoreList!=null && mScoreList.size() > scoreIndex){return mScoreList.get(scoreIndex);}else {return 0;}}/*** 设置计数的起始分数* @param totalScore*/public void setTotalScore(int totalScore) {this.TOTAL_SCORE = totalScore;setText(String.valueOf(TOTAL_SCORE));}/*** 停止计数*/public void stopCountScore(){if(ObjectUtils.isNotEmpty(mTimer)) {mTimer.cancel();mTimer = null; //把计数器释放,下次进来重新创建}}/*** 提供一个方法设置回调监听*/public void setOnFinishCollectListener(OnFinishCollectWords listener){this.mOnFinishCollectListener = listener;}/*** 提供一个回调接口,收集完词能翻转卡片*/public interface OnFinishCollectWords{void onFinishCollect(String totalScord);}
}

仿支付宝收取积分的收集动画相关推荐

  1. Android 高仿支付宝二维码扫描动画实现 3分钟学会 人脸识别扫描线

    原理: 1.把方框的位置在xml中布置好 2.把扫描线的图片也布置好 3.用平移动画,移动y轴,循环的次数反复. 不过我网上搜了搜很多方法都是实时绘制出来的,计算点的位置然后重绘出来.我的第一感觉是完 ...

  2. Android 仿支付宝蚂蚁森林动画效果

    Android 动画可以归纳为以下几种: 视图动画(View 动画) 帧动画(Frame 动画.Drawable 动画) 属性动画 触摸反馈动画(Ripple Effect) 揭露动画(Reveal ...

  3. iOS仿支付宝芝麻信用仪表盘效果

    概述 自定义View之高仿支付宝芝麻信用分数仪表盘动画效果 详细 代码下载:http://www.demodashi.com/demo/10654.html 仿支付宝芝麻信用仪表盘效果 一.主要思路 ...

  4. Android开发笔记(一百四十四)高仿支付宝的头部伸缩动画

    Android5.0推出的MaterialDesign库包含了处理头部工具栏的多个控件,不但允许自定义顶部导航栏,而且导航栏高度是可以伸缩的.如此一来,一方面导航栏能够放得下更多控件,另一方面在用户想 ...

  5. Android仿支付宝咻一咻动画

    Android特效专辑(十二)--仿支付宝咻一咻功能实现波纹扩散特效,精细小巧的View 先来看看这个效果 这是我的在Only上添加的效果,说实话,Only现在都还只是半成品,台面都上不了,怪自己技术 ...

  6. 高仿支付宝首页头部动画

    高仿支付宝首页头部动画(使用design实现效果,CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout+Toolbar) 效果图(效果图渐变不明 ...

  7. 高仿支付宝增加减少item功能和动画效果

    闲来无事,看了下支付宝App做的应用item效果,很炫,效果如下: 自己实现的效果如下: gif可能有点卡,但是实现了支付宝效果, 说下思路:下面是实例图(凑合看吧,大概意思是) 开始是打算用Scro ...

  8. Flutter高仿支付宝打钩动画

    文章目录 简介 效果 预备知识 自定义控件基本知识 动画基本知识 动画分析 PathMetric类作用 关键代码 简介 Flutter高仿支付宝打钩动画,利用动画和路径Path实现简易效果.熟悉And ...

  9. Android特效专辑(十二)——仿支付宝咻一咻功能实现波纹扩散特效,精细小巧的View...

    Android特效专辑(十二)--仿支付宝咻一咻功能实现波纹扩散特效,精细小巧的View 先来看看这个效果 这是我的在Only上添加的效果,说实话,Only现在都还只是半成品,台面都上不了,怪自己技术 ...

最新文章

  1. merge into用法mysql_SQL中merge into用法
  2. win32 数据类型 vs c#
  3. 常用加密算法的Java实现(一) ——单向加密算法MD5和SHA
  4. OpenWrt安装迅雷成功,实现BT emule等多协议下载
  5. Linux 4.1内核热补丁成功实践
  6. [轨道力学] 轨道力学期末复习
  7. npm包的语义版本控制(Semantic Versioning of Packages)
  8. leetcode python3 简单题171. Excel Sheet Column Number
  9. h5语音识别和文字转语音
  10. 苹果手机处理器_全球最强手机处理器诞生!苹果A14主频首超3GHz:性能秒杀华为/高通...
  11. 全网首发:JDK绘制文字:八、绘制函数简要分析
  12. 用Flash CS4打开fla文件提示“意外的格式”的解决方法
  13. 小爱同学app安卓版_小爱同学app下载安卓版-小爱同学 安卓版v2.9.42-pc6手机下载...
  14. 用户自治的数字身份在我国的标准
  15. wso2_使用WSO2开发
  16. 信息安全工程07875 自考软件工程 助学班复习纲要
  17. AHU 2022 CTF新生赛web_writeup
  18. [原创]反汇编之一:和Taskmgr过不去篇(无厘头版)
  19. Fliqlo时钟屏保Windows版本
  20. 如何写一个仿真文件——testbench

热门文章

  1. mui mui-icon-extra的使用
  2. 四年后看微软第二代超融合系统:Azure Stack HCI
  3. WPS如何转成PPT格式文件
  4. 2022-2028年全球与中国管道净水器行业竞争格局与投资战略研究
  5. python 读写yaml
  6. 李洪强iOS开发之苹果企业开发者账号申请流程
  7. Java发展方向路线图
  8. 苏州会不会成为下一个深圳?
  9. 运维自动化之ansible,轻松实现企业级自动化运维
  10. 专业护眼灯什么牌子好?分享最专业护眼灯品牌排行