1.布局文件:activity_main.xml
2.主类: MainActivity
/**
* @author ClamLaw
* @time 2016/11/26
* @desc MainActivity
*/
public class MainActivity extends AppCompatActivity {
private EditText mText;
private ListmList = new ArrayList<>();
private DanMuView mDanMuView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();//初始化
initData();
}
private void initData() {
String[] array = getResources().getStringArray(R.array.danmuList);//先获取部分数据
for (int i = 0; i < array.length; i++) {
mList.add(array[i]);
}
mDanMuView.setData(mList);//向弹幕框添加数据
mDanMuView.startDanmu();//开始弹幕
}
//初始化
private void initView() {
mText = (EditText) findViewById(R.id.text);
mDanMuView = (DanMuView) findViewById(R.id.danmu);
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {//发送按钮
@Override
public void onClick(View v) {
//发送评论
String str = mText.getText().toString();
mDanMuView.insertDanmu(str);
}
});
}
}
3.自定义弹幕显示框控件: DanMuView
/**
* @author ClamLaw
* @time 2016/11/26 19:01
* @desc 自定义弹幕的view
*/
public class DanMuView extends RelativeLayout {
private Context mContext;
private View view;
private RelativeLayout mContainerVG;
private ListmList;
//父组件的高度
private int validHeightSpace;
private Set existMarginValues = new HashSet<>();
private int lastMarginValue;
ExecutorService executorService = Executors.newFixedThreadPool(1);//线程池
Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1:
int index = msg.arg1;
String data = mList.get(index);
showDanmu(data);
break;
}
}
};
public DanMuView(Context context) {
super(context);
}
public DanMuView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
view = LayoutInflater.from(context).inflate(R.layout.danmu_view, null, false);
mContainerVG = (RelativeLayout) view.findViewById(R.id.danmu);
mContainerVG.setBackgroundDrawable(null);
addView(view);
}
/**
* 添加数据到弹幕中
*
* @param list
*/
public void setData(Listlist) {
this.mList = list;
}
/**
* 用户发送评论弹幕
*
* @param data
*/
public void insertDanmu(String data) {
showDanmu(data);//显示弹幕
mList.add(data);//将弹幕信息添加到集合的第一位
startDanmu();//开始弹幕
}
/**
* 开始弹幕
*/
public void startDanmu() {
existMarginValues.clear();
executorService.execute(new Runnable() {
@Override
public void run() {
for (int i =0 ;i= (count + 1) * 2) {
int end = count * 2;
String result = new String(b, 0, end, encoding);
if (str.indexOf(result) == -1) {
return new String(b, 0, end - 1, encoding) + "...";
}
return result + "...";
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return str;
}
//动画
public class AnimationHelper{
public AnimationHelper() {
}
//fromX 开始的位置 ,toX结束的位置
public Animation createTranslateAnim(Context context, int fromX, int toX){
TranslateAnimation translateAnimation = new TranslateAnimation(fromX, toX, 0, 0);
int width = getScreenWidth((Activity)context);//获取屏幕的宽度
//自动计算时间
long duration = (long) (Math.abs(toX - fromX) * 1.0f / width * 6000);
translateAnimation.setDuration(duration);//动画时间
// translateAnimation.setInterpolator(new DecelerateAccelerateInterpolator());//动画速率
translateAnimation.setFillAfter(true);//终止时停留最后一帧
return translateAnimation;
}
}
public class DecelerateAccelerateInterpolator implements Interpolator {
@Override
public float getInterpolation(float input) {
return (float) (Math.tan((input * 2 - 1) / 4 * Math.PI)) / 2.0f + 0.5f;
}
}
}
4.弹幕容器布局:danmu_view.xml
5.弹幕子控件布局:item_danmu.xml
本Demo的源码下载链接:DanMuDemo.