zoukankan      html  css  js  c++  java
  • Android:简单的弹幕效果达到

    首先,效果图。分类似至360检测到的骚扰电话页面:


    布局非常easy,上面是一个RelativeLayout,以下一个Button.

    功能:

    (1)弹幕生成后自己主动从右側往左側滚动(TranslateAnimation)。弹幕消失后立马被移除。

    (2)弹幕位置随机出现。而且不反复(防止文字重叠)。

    (3)字体大小在一定范围内随机改变。字体颜色也能够设置。

    (4)自己定义先减速,后加速的Interpolator,弹幕加速进入、减速停留、然后加速出去。

    1.Activity代码:

    /**
     * 简易弹幕效果实现
     * Created by admin on 15-6-4.
     */
    public class MainActivity extends ActionBarActivity {
        private MyHandler handler;
    
        //弹幕内容
        private TanmuBean tanmuBean;
        //放置弹幕内容的父组件
        private RelativeLayout containerVG;
    
        //父组件的高度
        private int validHeightSpace;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            containerVG = (RelativeLayout) findViewById(R.id.tanmu_container);
            tanmuBean = new TanmuBean();
            tanmuBean.setItems(new String[]{"測试一下", "弹幕这东西真不好做啊", "总是出现各种问题~~", "也不知道都是为什么?麻烦!", "哪位大神能够帮帮我啊?", "I need your help.",
                    "測试一下", "弹幕这东西真不好做啊", "总是出现各种问题~~", "也不知道都是为什么?麻烦!

    ", "哪位大神能够帮帮我啊?", "I need your help.", "測试一下", "弹幕这东西真不好做啊", "总是出现各种问题~~", "也不知道都是为什么?麻烦!

    ", "哪位大神能够帮帮我啊?", "I need your help."}); handler = new MyHandler(this); //開始弹幕 View startTanmuView = findViewById(R.id.startTanmu); startTanmuView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (containerVG.getChildCount() > 0) { return; } existMarginValues.clear(); new Thread(new CreateTanmuThread()).start(); } }); } //每2s自己主动加入一条弹幕 private class CreateTanmuThread implements Runnable { @Override public void run() { int N = tanmuBean.getItems().length; for (int i = 0; i < N; i++) { handler.obtainMessage(1, i, 0).sendToTarget(); SystemClock.sleep(2000); } } } //须要在主线城中加入组件 private static class MyHandler extends Handler { private WeakReference<MainActivity> ref; MyHandler(MainActivity ac) { ref = new WeakReference<>(ac); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == 1) { MainActivity ac = ref.get(); if (ac != null && ac.tanmuBean != null) { int index = msg.arg1; String content = ac.tanmuBean.getItems()[index]; float textSize = (float) (ac.tanmuBean.getMinTextSize() * (1 + Math.random() * ac.tanmuBean.getRange())); int textColor = ac.tanmuBean.getColor(); ac.showTanmu(content, textSize, textColor); } } } } private void showTanmu(String content, float textSize, int textColor) { final TextView textView = new TextView(this); textView.setTextSize(textSize); textView.setText(content); // textView.setSingleLine(); textView.setTextColor(textColor); int leftMargin = containerVG.getRight() - containerVG.getLeft() - containerVG.getPaddingLeft(); //计算本条弹幕的topMargin(随机值,可是与屏幕中已有的不反复) int verticalMargin = getRandomTopMargin(); textView.setTag(verticalMargin); LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.addRule(RelativeLayout.ALIGN_PARENT_TOP); params.topMargin = verticalMargin; textView.setLayoutParams(params); Animation anim = AnimationHelper.createTranslateAnim(this, leftMargin, -ScreenUtils.getScreenW(this)); anim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { //移除该组件 containerVG.removeView(textView); //移除占位 int verticalMargin = (int) textView.getTag(); existMarginValues.remove(verticalMargin); } @Override public void onAnimationRepeat(Animation animation) { } }); textView.startAnimation(anim); containerVG.addView(textView); } //记录当前仍在显示状态的弹幕的位置(避免反复) private Set<Integer> existMarginValues = new HashSet<>(); private int linesCount; private int getRandomTopMargin() { //计算用于弹幕显示的空间高度 if (validHeightSpace == 0) { validHeightSpace = containerVG.getBottom() - containerVG.getTop() - containerVG.getPaddingTop() - containerVG.getPaddingBottom(); } //计算可用的行数 if (linesCount == 0) { linesCount = validHeightSpace / ScreenUtils.dp2px(this, tanmuBean.getMinTextSize() * (1 + tanmuBean.getRange())); if (linesCount == 0) { throw new RuntimeException("Not enough space to show text."); } } //检查重叠 while (true) { int randomIndex = (int) (Math.random() * linesCount); int marginValue = randomIndex * (validHeightSpace / linesCount); if (!existMarginValues.contains(marginValue)) { existMarginValues.add(marginValue); return marginValue; } } } }

    2.平移动画生成工具:

    public class AnimationHelper {
        /**
         * 创建平移动画
         */
        public static Animation createTranslateAnim(Context context, int fromX, int toX) {
            TranslateAnimation tlAnim = new TranslateAnimation(fromX, toX, 0, 0);
            //自己主动计算时间
            long duration = (long) (Math.abs(toX - fromX) * 1.0f / ScreenUtils.getScreenW(context) * 4000);
            tlAnim.setDuration(duration);
            tlAnim.setInterpolator(new DecelerateAccelerateInterpolator());
            tlAnim.setFillAfter(true);
    
            return tlAnim;
        }
    }
    ScreenUtils是用来获取屏幕宽高、dp与px之间互转的工具类。

    3.自己定义的Interpolator。事实上仅仅有一行代码

    public class DecelerateAccelerateInterpolator implements Interpolator {
    
        //input从0~1,返回值也从0~1.返回值的曲线表征速度加减趋势
        @Override
        public float getInterpolation(float input) {
            return (float) (Math.tan((input * 2 - 1) / 4 * Math.PI)) / 2.0f + 0.5f;
        }
    }
    4.TanmuBean是一个实体类

    public class TanmuBean {
        private String[] items;
        private int color;
        private int minTextSize;
        private float range;
    
        public TanmuBean() {
            //init default value
            color = Color.parseColor("#eeeeee");
            minTextSize = 16;
            range = 0.5f;
        }
    
        public String[] getItems() {
            return items;
        }
    
        public void setItems(String[] items) {
            this.items = items;
        }
    
        public int getColor() {
            return color;
        }
    
        public void setColor(int color) {
            this.color = color;
        }
    
        /**
         * min textSize, in dp.
         */
        public int getMinTextSize() {
            return minTextSize;
        }
    
        public void setMinTextSize(int minTextSize) {
            this.minTextSize = minTextSize;
        }
    
        public float getRange() {
            return range;
        }
    
        public void setRange(float range) {
            this.range = range;
        }
    }

    ==========

    源代码下载:http://download.csdn.net/detail/books1958/9005279 






    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    安装 SciPy 和 scikit-learn 升级pip 及pip基本命令表
    js修改:before、:after的内容
    初试Celery
    python中的@
    python去除空格和换行符的方法
    Beautiful 疑问小记
    http://www.oreilly.com/catalog/errataunconfirmed.csp?isbn=9780596529321
    浏览器提示框事件
    从欧几里得距离、向量、皮尔逊系数到http://guessthecorrelation.com/
    win安装NLTK出现的问题
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4852550.html
Copyright © 2011-2022 走看看