自定義彈幕控制元件

銳湃發表於2015-10-20

效果圖如下:




MyBarrageView.java

package com.example.example.view;

import java.lang.ref.SoftReference;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
/**
 * 自定義彈幕控制元件
 * @author 1
 *
 */
public class MyBarrageView extends LinearLayout { 
	/**
	 * 每行有多少個彈幕item
	 */
	private static final int ROW_ITEM_COUNT = 2;
	/**
	 * 是否停止彈幕動畫
	 */
	private boolean stop = false;
	/**
	 * 存放所有用到的動畫
	 */
	private HashSet<ObjectAnimator> animators = new HashSet<ObjectAnimator>(); 
	private HashSet<ObjectAnimator> pausedAnimators = new HashSet<ObjectAnimator>();
	
	public MyBarrageView(Context context) {
		super(context);
		init(); 
	}
	
	public MyBarrageView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}
	public MyBarrageView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init();
	} 
	private void init() {
		setOrientation(LinearLayout.VERTICAL);  
	}
	/**
	 * 停止彈幕滑動
	 */
	public void stop(){
		stop = true;
		if(!animators.isEmpty()){
			Iterator<ObjectAnimator> iterator = animators.iterator();
			while (iterator.hasNext()) {
				ObjectAnimator anim = iterator.next();
				if(anim.isRunning()){
					anim.cancel(); 
					pausedAnimators.add(anim);
				}
				
			}
		}
	}
	/**
	 * 在主執行緒將彈幕移動起來
	 */
	Handler handler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			ObjectAnimator animator = (ObjectAnimator) msg.obj;
			animator.start();
		};
	};
	/**
	 * 開啟彈幕移動
	 */
	public void start(){
		stop = false;
		if(!pausedAnimators.isEmpty()){
			new Thread(){
				public void run() {
					Iterator<ObjectAnimator> iterator = pausedAnimators.iterator();
					while (iterator.hasNext()) {
						Message msg = handler.obtainMessage();
						msg.obj = iterator.next(); 
						msg.sendToTarget();
						try {
							//使動畫啟動時間分散不要太集中
							sleep(30);
						} catch (InterruptedException e) { 
							e.printStackTrace();
						}
					}
					pausedAnimators.clear();
				};
			}.start();
			
		} 
	}
	/**
	 * 增加彈幕
	 * @param txt
	 */
	public void add(String txt){
		if(isFull()){
			addViewItem(txt);
		}else {
			addGroupItem(txt);
		}
	} 
	/**
	 * 檢查行Viewgroup是不是已加滿
	 * @return
	 */
	private boolean isFull() {
		if(getChildCount() < 1){
			return false;
		}
		View lastViewGroup = getChildAt(getChildCount()-1);
		int lastBottom = lastViewGroup.getTop()+lastViewGroup.getMeasuredHeight();
		boolean b1 = lastBottom >= getMeasuredHeight();
		boolean b2 = lastBottom + lastViewGroup.getMeasuredHeight() - getMeasuredHeight() >= lastViewGroup.getHeight()/3;
		return b1 || b2;
	}
	
	/**
	 * 根據指定的字元生成Textview
	 * @param txt
	 * @return
	 */
	private TextView initTextview(String txt){
		TextView textView = new TextView(getContext());
    	textView.setBackgroundColor(0xffffff);
    	textView.setSingleLine(true);
    	textView.setTextColor(Color.RED);
    	textView.setGravity(Gravity.CENTER);
    	//textView.setBackgroundColor(Color.YELLOW); 
    	textView.setText("---------------text "+txt+"------------");  
    	android.view.ViewGroup.LayoutParams layoutParams = new LayoutParams(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
    	textView.setLayoutParams(layoutParams);
    	return textView;
	}
	/**
	 * 根據指定的字元,增加相應彈幕
	 * @param txt
	 */
	private void addViewItem(String txt) { 
    	int rowIndex = new Random().nextInt(getChildCount()); 
		addItemView2Viewgroup(rowIndex,txt);
	}
	/**
	 * 根據指定的字元,增加相應彈幕,並新增新的彈幕行
	 * @param txt
	 */
	private void addGroupItem(String txt) {
		RelativeLayout layout = new RelativeLayout(getContext());
		ArrayBlockingQueue<View> subViews = new ArrayBlockingQueue<View>(ROW_ITEM_COUNT);
		layout.setTag(subViews);
		addView(layout);
		int rowIndex = getChildCount() - 1; 
		addItemView2Viewgroup(rowIndex,txt);
	}    
    /**
     * 把指定的view加到指定的行viewGroup上
     * @param rowIndex 
     * @param txt 
     */
	private void addItemView2Viewgroup(final int rowIndex, final String txt) { 
		new Thread(){
			@Override
			public void run() {
				TextView textView = null;
				Holder holder; 
				int width = getResources().getDisplayMetrics().widthPixels;
				ObjectAnimator animator = null ;
				
				final RelativeLayout group = (RelativeLayout) getChildAt(rowIndex);
				ArrayBlockingQueue<View> queue = (ArrayBlockingQueue<View>) group.getTag();
				if(group.getChildCount() + queue.size() >= ROW_ITEM_COUNT){ 
					try {
						textView = (TextView) queue.take();
						group.post(new SetTextRunnable(txt, textView));
						
						Holder holder2 = (Holder) textView.getTag();
						animator = holder2.animator.get();
						animator.setFloatValues(width,0-width);
					} catch (InterruptedException e) { 
						e.printStackTrace();
					}
					
				}else { 
					
					holder = new Holder();
					holder.rowIndex = rowIndex;
					holder.startX = width;
					holder.endX = 0 - width; 
					textView = initTextview(txt);
					textView.setTextColor(getColor());
					textView.setTag(holder);
					textView.setOnClickListener(new MyClickListener());
					
					
					animator = ObjectAnimator.ofFloat(textView, "translationX", width,0-width);
					animator.addListener(new MyAnimatorListener(textView));
					animator.setInterpolator(new AccelerateInterpolator());
					holder.animator = new SoftReference<ObjectAnimator>(animator);
					animators.add(animator); 
					group.post(new AddViewRunnable(group, textView));
				}
				
				int random = new Random().nextInt(2500);
				int duration = 5000 + random; 
				Log.d("duration", " random duration = "+duration);
				animator.setDuration(duration);
				animator.setInterpolator(getInterpolator());
				if(!stop){  
					group.post(new StartAnimatorRunnable(animator));
				}else {
					pausedAnimators.add(animator);
				}
				 
			} 
		}.start();
	} 
	/**
	 * 隨機獲取顏色值
	 * @return
	 */
	protected int getColor() {
		int[] colors = new int[]{Color.BLACK,Color.BLUE, Color.CYAN,Color.RED,Color.GREEN,Color.WHITE,Color.YELLOW};
	    Random random = new Random();
		return colors[random.nextInt(colors.length)];
	}
    /**
     * 隨機獲取彈幕動畫加速器
     * @return
     */
	private TimeInterpolator getInterpolator() {
		Random random = new Random();
		int id = random.nextInt(4);
		System.out.println("------id = "+id);
		switch (id) {
		case 0:
			return new AccelerateDecelerateInterpolator(); 
		case 1:
			return new AccelerateInterpolator(); 
		case 2:
			 return new DecelerateInterpolator(); 
		case 3:
			 return new LinearInterpolator(); 
			 
		/*case 4:
			return new BounceInterpolator(); 
		case 5:
			return new CycleInterpolator(3); 
		case 6: 
			return new AnticipateInterpolator();
		case 7: 
			return new AnticipateOvershootInterpolator();
		case 8:
			return new OvershootInterpolator();*/
		default:
			break;
		}
		return new LinearInterpolator();
	}
    /**
     * 用於向指定容器裡新增指定的view
     * @author 1 
     */
	class AddViewRunnable implements Runnable{
		private ViewGroup group;
        private View view; 
        
		public AddViewRunnable(ViewGroup group,View view) {
			super();
			this.group = group;
			this.view = view; 
		}

		@Override
		public void run() { 
			group.addView(view);  
		}	
	}
	/**
	 * 啟動相應動畫
	 * @author 1
	 *
	 */
	class StartAnimatorRunnable implements Runnable{
        private ObjectAnimator animator;
        
		public StartAnimatorRunnable(ObjectAnimator animator) {
			super();
			this.animator = animator;
		}

		@Override
		public void run() {
			if(!stop){
				animator.start();
			} 
		} 
	}
	/**
	 * 為指定的TextView設定指定的文字
	 * @author 1
	 *
	 */
	class SetTextRunnable implements Runnable{
        private String txt;
        private TextView textView;
        
		public SetTextRunnable(String txt, TextView textView) {
			super();
			this.txt = txt;
			this.textView = textView;
		}

		@Override
		public void run() {
			textView.setText(txt);
			textView.setTextColor(getColor());
		}
		
	}
	/**
	 * 幫助類
	 * @author 1
	 *
	 */
	class Holder{ 
		/**
		 * view所處的行號
		 */
		public int rowIndex;
		/**
		 * view所在的列號
		 */
		public int columnIndex;
		/**
		 * 動畫持續時間
		 */
		public int duation;
		/**
		 * 動畫開始座標
		 */
		public int startX;
		/**
		 * 動畫結束座標
		 */
		public float endX; 
		/**
		 * view所繫結的動畫
		 */
		public SoftReference<ObjectAnimator> animator;
	}
	class MyClickListener implements OnClickListener{

		@Override
		public void onClick(View v) {
			TextView textView = (TextView) v;
			Toast.makeText(getContext(), textView.getText(), 0).show();
		}
		
	}
	/**
	 * 動畫監聽器
	 * @author 1
	 *
	 */
	class MyAnimatorListener implements AnimatorListener{
        private SoftReference<View> objectView; 
        public MyAnimatorListener(View view){
        	this.objectView = new SoftReference<View>(view); 
        }
		@Override
		public void onAnimationStart(Animator animation) {}

		@Override
		public void onAnimationEnd(Animator animation) {
			if(stop) {
				return;
			}
			final View view = objectView.get();
			Holder holder = (Holder) view.getTag();
			Float f = (Float) ((ValueAnimator)animation).getAnimatedValue();  
			//((ObjectAnimator)animation).setFloatValues(f,holder.endX);
			
			ViewGroup group = (ViewGroup)getChildAt(holder.rowIndex); 
			final ArrayBlockingQueue<View> queue = (ArrayBlockingQueue<View>) group.getTag();

			new Thread() {
				public void run() {
					try { 
						queue.put(view);  
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				};
			}.start(); 
			System.out.println("--------onAnimationEnd--------");
		}

		@Override
		public void onAnimationCancel(Animator animation) {
			Float f = (Float) ((ValueAnimator)animation).getAnimatedValue();
			System.out.println("ssss   f="+f);
			((ObjectAnimator)animation).setFloatValues(f,0-getContext().getResources().getDisplayMetrics().widthPixels);
			System.out.println("--------onAnimationCancel---------");
		}

		@Override
		public void onAnimationRepeat(Animator animation) {} 
		
	}
}


BarrageActivity.java
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class BarrageActivity extends Activity {
    private MyBarrageView ll;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_barrage);
		ll = (MyBarrageView) findViewById(R.id.ll);
	}
	int i = 1;
  
	public void addView(View v){
		ll.add("彈幕"+ i++);
	}
	public void stop(View v){
		ll.stop();
	}
	public void start(View v){
		ll.start();
	}
}
activity_barrage.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="@string/hello_world" />  
        <com.example.example.view.MyBarrageView 
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:background="#33333333" 
        android:id="@+id/ll"> 
    </com.example.example.view.MyBarrageView> 
    <Button 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"  
        android:text="-=彈幕=-"
        android:onClick="addView"/>
    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button 
        android:layout_width="0dp"
        android:layout_height="wrap_content"  
        android:layout_weight="1"
        android:text="stop"
        android:onClick="stop"/>
        <Button 
        android:layout_width="0dp"
        android:layout_height="wrap_content"  
        android:layout_weight="1"
        android:text="start"
        android:onClick="start"/>
    </LinearLayout>
</LinearLayout>


=========================================================================================================

最近對於自定義彈幕控制元件做了一些修訂,作了一個增強版本,主要新增了控制是否可以迴圈滾動、item換成了抽象類降低耦合

程式碼如下:

package com.example.example.view;

import java.lang.ref.SoftReference;
import java.security.acl.LastOwnerException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.util.LruCache;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
/**
 * 自定義彈幕控制元件
 * @author 1
 *
 */
public class MyBarrageView1 extends LinearLayout { 
	/**
	 * 每行有多少個彈幕item
	 */
	private static final int ROW_ITEM_COUNT = 7;
	/**
	 * 上面留出的空白區單位,單位為dp
	 */
	private static final int TOP_PADDING = 3;
	/**
	 * 是否停止彈幕動畫
	 */
	private boolean stop = false;
	/**
	 * 存放所有用到的動畫
	 */
	private HashSet<ObjectAnimator> animators = new HashSet<ObjectAnimator>(); 
	private HashSet<ObjectAnimator> pausedAnimators = new HashSet<ObjectAnimator>();
	private HashSet<BarrageViewItem> viewItems = new HashSet<MyBarrageView1.BarrageViewItem>();
	
	/**
	 * 彈幕是否可以迴圈滾動
	 */
	private boolean canLoop = false;
	public MyBarrageView1(Context context) {
		super(context);
		init(); 
	}
	
	public MyBarrageView1(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}
	public MyBarrageView1(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init();
	} 
	/**
	 * 獲取彈幕是否可以迴圈滾動
	 */
	public boolean isCanLoop() {
		return canLoop;
	} 
	/**
	 * 設定彈幕是否可以迴圈滾動
	 */
	public void setCanLoop(boolean canLoop) {
		this.canLoop = canLoop;
	}

	private HashSet<BarrageViewItem> tmpItems = new HashSet<MyBarrageView1.BarrageViewItem>();
	boolean canAdd = false;
	private void init() {
		setOrientation(LinearLayout.VERTICAL);   
		int topPading = dip2px(getContext(), TOP_PADDING);
		System.out.println("------ topPading = "+topPading);
		setPadding(0, topPading, 0, 0);
		getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
			@Override
			public void onGlobalLayout() {
				//Log.v("layout", "getMeasuredHeight()="+getMeasuredHeight()+"  getHeight()="+getHeight());
				int count = getChildCount();
				if(count > 0){ 
					View lastGroup = getChildAt(count-1);
					if(lastGroup.getHeight() > 0 && !tmpItems.isEmpty()){
						Iterator<BarrageViewItem> it = tmpItems.iterator();
						BarrageViewItem item = it.next();
						add(item);
						Log.d("data", "item.getData() ="+item.getData().toString());
						
						tmpItems.remove(item);
					}
					Log.v("layout1", "tmpItems.size()="+tmpItems.size());
					Log.v("layout1", "lastGroup.getMeasuredHeight()="+lastGroup.getMeasuredHeight()+"  lastGroup.getHeight()="+lastGroup.getHeight()+"  canAdd="+canAdd);
				}
			}
		});
	}
	/** 
     * 根據手機的解析度從 dp 的單位 轉成為 px(畫素) 
     */  
    public static int dip2px(Context context, float dpValue) {  
        final float scale = context.getResources().getDisplayMetrics().density;  
        return (int) (dpValue * scale + 0.5f);  
    }  
	/**
	 * 增加彈幕
	 * @param item
	 */
	public void add(BarrageViewItem item){
		Log.v("layout", "tmpItems.size()="+tmpItems.size());
		if(!canAdd()){
			tmpItems.add(item);
			return;
		}
		if(isFull()){
			addViewItem(item);
		}else {
			addGroupItem(item);
		}
	} 
	/**
	 * 判斷 是不是可以新加新彈幕組,要在上一次新增的彈幕組完了測量等一系列動作後,才可以再新增
	 * @return
	 */
	private boolean canAdd() {
		if(getChildCount() < 1){
			return true;
		}
		View lastChild = getChildAt(getChildCount()-1);
		
		Log.d("layout", "lastChild.getHeight() = "+lastChild.getHeight());
		return lastChild.getHeight() > 0;
	}

	/**
	 * 清屏,把所有彈幕清掉
	 */
	public void clear(){
		removeAllViews();
	}
	/**
	 * 停止彈幕滑動
	 */
	public void stop(){ 
		stop = true;
		if(!animators.isEmpty()){
			Iterator<ObjectAnimator> iterator = animators.iterator();
			while (iterator.hasNext()) {
				ObjectAnimator anim = iterator.next();
				if(anim.isRunning()){
					anim.cancel(); 
					pausedAnimators.add(anim);
				}
				
			}
		} 
	} 
	/**
	 * 開啟彈幕移動
	 */
	public void start(){ 
		if(!pausedAnimators.isEmpty()){ 
			Iterator<ObjectAnimator> iterator = pausedAnimators.iterator();
			while (iterator.hasNext()) {
				iterator.next().start();
			}
			pausedAnimators.clear(); 
		}
		stop = false;
	} 
	/**
	 * 判斷是否已經停止彈幕滾動
	 * @return
	 */
	public boolean isStop() {
		return stop;
	} 

	/**
	 * 檢查行Viewgroup是不是已加滿
	 * @return
	 */
	private boolean isFull() {
		if(getChildCount() < 1){
			return false;
		}
		View lastViewGroup = getChildAt(getChildCount()-1);  
		lastViewGroup.measure(0, 0);
		//int lastBottom = lastViewGroup.getTop()+lastViewGroup.getMeasuredHeight();
		Log.v("test", "last  getHeight()="+lastViewGroup.getHeight() +"  lastView getMeasuredHeight = "+lastViewGroup.getMeasuredHeight()+"  getMeasuredHeight="+getMeasuredHeight());
		//boolean b1 = lastViewGroup.getMeasuredHeight() > lastViewGroup.getHeight();
		boolean b2 = getHeight() - lastViewGroup.getBottom() < lastViewGroup.getMeasuredHeight();
		Log.d("test", "b1="/*+b1*/ +"  b2="+b2);
		return b2 /*b1 || b2*/;
	}
	
    /**
     * 根據指定的BarrageViewItem,增加相應彈幕
     * @param item
     */
	private void addViewItem(BarrageViewItem item) {
		int rowIndex = new Random().nextInt(getChildCount()); 
		addItemView2Viewgroup(rowIndex,item);
	}
	
	/**
	 * 根據指定的字元,增加相應彈幕,並新增新的彈幕行
	 * @param txt
	 */
	private void addGroupItem(BarrageViewItem item) {
		final RelativeLayout layout = new RelativeLayout(getContext());  
		addView(layout);
		int rowIndex = getChildCount() - 1;    
		addItemView2Viewgroup(rowIndex,item);
	}   
	/**
	 * 用來動態更新相應條目
	 */
	Handler itemUpdateHandler = new Handler(){
		public void handleMessage(Message msg) {
			BarrageViewItem item = (BarrageViewItem) msg.obj;
			item.update(item.getRootView(),item.getData());
		};
	};
	/**
	 * 把指定的item加到指定行號viewGroup上
	 * @param rowIndex 指定的行號
	 * @param item 相應的item
	 */
	private void addItemView2Viewgroup(final int rowIndex, final BarrageViewItem item) { 
		
				View v = null;
				Holder holder; 
				int width = getResources().getDisplayMetrics().widthPixels;
				ObjectAnimator animator = null ;
				
				final RelativeLayout group = (RelativeLayout) getChildAt(rowIndex); 
				if(group.getChildCount()  >= ROW_ITEM_COUNT){  
					viewItems.add(item);
					System.out.println("-----數量已夠-----");
				}else { 
					//賦值view幫助類
					holder = new Holder();
					holder.rowIndex = rowIndex;
					holder.startX = width;
					holder.endX = 0 - width; 
					item.update(item.getRootView(),item.getData());
				    v = item.getRootView(); 
					v.setTag(holder);  
					 
					animator = ObjectAnimator.ofFloat(v, "translationX", width,0-width);  
					animator.addListener(new MyAnimatorListener(item)); 
					holder.animator = new SoftReference<ObjectAnimator>(animator);
					animators.add(animator);  
					group.addView(v);
					System.out.println("-----數量未夠-----");
					 
					animator.setDuration(item.getDuration()*2);
					animator.setInterpolator(getInterpolator());
					if(!stop){  
						animator.start();
					}else {
						pausedAnimators.add(animator);
					}
				}  
	}
	/**
	 * 隨機獲取顏色值
	 * @return
	 */
	public int getColor() {
		int[] colors = new int[]{Color.BLACK,Color.BLUE, Color.CYAN,Color.RED,Color.GREEN,Color.WHITE,Color.YELLOW
				/*,0xffFFC125,0xffFFC125,0xffFF0000,0xffEEEE00,0xffFF00FF,0xffEEE8CD,0xffB8860B,0xffA52A2A,0xff7A378B,0xff787878,0xff5CACEE,0xff00EE00*/};
	    Random random = new Random();
		return colors[random.nextInt(colors.length)];
	}
    /**
     * 隨機獲取彈幕動畫加速器
     * @return
     */
	private TimeInterpolator getInterpolator() {
		Random random = new Random();
		int id = random.nextInt(4);
		System.out.println("getInterpolator------id = "+id);
		switch (id) {
		case 0:
			return new AccelerateDecelerateInterpolator(); 
		case 1:
			return new AccelerateInterpolator(); 
		case 2:
			 return new DecelerateInterpolator(); 
		case 3:
			 return new LinearInterpolator(); 
			 
		/*case 4:
			return new BounceInterpolator(); 
		case 5:
			return new CycleInterpolator(3); 
		case 6: 
			return new AnticipateInterpolator();
		case 7: 
			return new AnticipateOvershootInterpolator();
		case 8:
			return new OvershootInterpolator();*/
		default:
			break;
		}
		return new LinearInterpolator();
	} 
	/**
	 * 根據指定的字元生成Textview
	 * @param txt
	 * @return
	 */ 
	private TextView initTextview(String txt){
		TextView textView = new TextView(getContext());
    	textView.setBackgroundColor(0xffffff);
    	textView.setSingleLine(true);
    	textView.setTextColor(Color.RED);
    	textView.setGravity(Gravity.CENTER);
    	 
    	textView.setText("---------------text "+txt+"------------");  
    	android.view.ViewGroup.LayoutParams layoutParams = new LayoutParams(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
    	textView.setLayoutParams(layoutParams);
    	return textView;
	}
	/**
	 * 幫助類
	 * @author 1 
	 */
	class Holder{ 
		/**
		 * view所處的行號
		 */
		public int rowIndex; 
		/**
		 * 動畫持續時間
		 */
		public int duation;
		/**
		 * 動畫開始座標
		 */
		public int startX;
		/**
		 * 動畫結束座標
		 */
		public float endX; 
		/**
		 * view所繫結的動畫
		 */
		public SoftReference<ObjectAnimator> animator;
	} 
	Handler handler = new Handler(){
		public void handleMessage(Message msg) {
			ObjectAnimator animator = (ObjectAnimator) msg.obj; 
			animator.start();
			//System.out.println("------handleMessage------");
		};
	};
	/**
	 * 動畫監聽器
	 * @author 1
	 *
	 */
	class MyAnimatorListener implements AnimatorListener{ 
        private BarrageViewItem barrageViewItem;
        public MyAnimatorListener(BarrageViewItem item){ 
        	barrageViewItem = item;
        }
		@Override
		public void onAnimationStart(Animator animation) {}

		@Override
		public void onAnimationEnd(Animator animation) {
			//判斷是否已停止彈幕滑動或者已清屏
			if( stop || getChildCount() < 1) {
				return;
			} 
			
			boolean viewItemsIsEmpty = false;
			Holder holder = (Holder) barrageViewItem.getRootView().getTag(); 
			((ObjectAnimator) animation).setFloatValues(holder.startX,holder.endX);  
			if(!viewItems.isEmpty()){
				Log.d("TAG", "------viewItems.size()------"+viewItems.size());
				Iterator<BarrageViewItem> it = viewItems.iterator();
				BarrageViewItem item = it.next();
				barrageViewItem.update(item.getRootView(),item.getData());
				viewItems.remove(item);
				viewItemsIsEmpty = false;
			}else {
				viewItemsIsEmpty = true;
			}
			if(!viewItemsIsEmpty || canLoop){
				Message msg = handler.obtainMessage();
				msg.obj = animation;
				msg.sendToTarget();
			}
			
			System.out.println("--------onAnimationEnd--------viewItemsIsEmpty="+viewItemsIsEmpty+"   canLoop="+canLoop);
		}

		@Override
		public void onAnimationCancel(Animator animation) {
			Float f = (Float) ((ValueAnimator)animation).getAnimatedValue(); 
			System.out.println("ssss   f="+f);
			((ObjectAnimator)animation).setFloatValues(f,0-getContext().getResources().getDisplayMetrics().widthPixels);
			System.out.println("--------onAnimationCancel---------"); 
		}

		@Override
		public void onAnimationRepeat(Animator animation) {} 
		
	}
	/**
	 * 彈幕item
	 * @author 1 
	 */
	public static abstract class BarrageViewItem{  
		protected View rootView = null;
		
		protected abstract View getView();
		public abstract void setData(Object data);
		public abstract Object getData();
		/**
		 * 根據指定的資料更新相應的顯示
		 * @param data
		 */
		public abstract void update(View view,Object data);
		/**
		 * item在螢幕上出現的時長,以毫秒為單位
		 * @return
		 */
		public abstract int getDuration();
		
		final public View getRootView(){
			//Log.d("update", "----getRootView----"+getClass().getName());
			if(rootView == null){
				rootView = getView();
			}
			return rootView; 
		}
	} 
}



相關文章