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

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

时间: 2024-08-09 06:17:10

Android:简单的弹幕效果达到的相关文章

【Android】【沙湾】我的自定义控件-简单的弹幕效果

[写在前面] 虽然是写技术博客(技术含量未必高- -!),但想来我的博客里边第一段都应该用来发牢骚之类的,原因就是,这是我的博客,任性. 学生时代,我是一个作文水平极烂的学生,但我觉得我心里是有文艺细胞的(额...).我在博客园和CSDN等看到了众多大牛写的博客,收益颇多,于是也想分享自己的一些学习体会.学习,我不排斥那些拿来主义的人,但"拿来"要灵活.死板的拿来只用,这对自己只是增加了经验,而并不会有什么长进.关于IT界的"拿来",我相信很多人都是从"拿

Android:简易弹幕效果实现

首先上效果图,类似于360检测到骚扰电话页面: 布局很简单,上面是一个RelativeLayout,下面一个Button. 功能: (1)弹幕生成后自动从右侧往左侧滚动(TranslateAnimation),弹幕消失后立刻被移除. (2)弹幕位置随机出现,并且不重复(防止文字重叠). (3)字体大小在一定范围内随机改变,字体颜色也可以设置. (4)自定义先减速,后加速的Interpolator,弹幕加速进入.减速停留.然后加速出去. 1.Activity代码: /** * 简易弹幕效果实现 *

Android Studio 直播弹幕

我只是搬运:https://blog.csdn.net/HighForehead/article/details/55520199 写的很好很详细,挺有参考价值的 demo直通车:https://download.csdn.net/download/highforehead/9757126 直播和看视频中越来越火的控件---弹幕(Danmaku) 本文即介绍怎样实现简单的弹幕效果:咱们使用的是哔哩哔哩开源的弹幕效果库 DanmakuFlameMaster( github地址:https://gi

android 简单动画之 animtion

Android  简单的动画效果有Animtion 类提供 1.在XML中实现动画效果:2.在java代码中实现动画效果. 动画相关的属性 表一:SET属性 名称 属性 备注 android:shareInterpolator 是否共享插入器 共享时,四个子节点都用一个插入器 android:interpolator 指定一个动画的插入器 使用系统资源 android:fillEnabled 当设置为true时,fillAfter和fillBefroe将会都为true,此时会忽略fillBefo

Android弹幕功能实现,模仿斗鱼直播的弹幕效果

转载请注明出处:http://blog.csdn.net/sinyu890807/article/details/51933728 本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭霖 即可关注,每天都有文章更新. 大家好,感觉好像已经很久没更新博客了.前段时间主要是忙于新书的事情,时间比较紧张.而现在新书已经完稿,剩下的事情就都是出版社的工作了,那么我又可以抽出时间来写写博客了. 记得之前有位朋友在我的公众号里问过我,像直播的那种弹幕功能该如何实现?如今直播行业确实是非常火爆

Android 教你亲手打造酷炫的弹幕效果

公司的新产品上线需要添加的弹幕功能,于是花了一天时间写了一个Demo. 效果实现如下: 一开始的思路是: 1.首先实现一个自定义的Layout,在其中获得需要展示的弹幕数组,每个弹幕数组的项包括弹幕文本以及图片Url地址. 2.在Layout内部使用Handler或者计时线程循环发送弹幕. 3.弹幕实现采用自定义弹幕View,配合动画实现滚屏呈现. 总结之后发现主要的难点还是在弹幕的出现位置选择以及弹幕如何确保及时销毁上(我会说一开始调试的时候出现满屏弹幕的华丽场景么..),以及如何实现组件的复

Android 自定义View修炼-自定义弹幕效果View

一.概述 现在有个很流行的效果就是弹幕效果,满屏幕的文字从右到左飘来飘去.看的眼花缭乱,看起来还蛮cool的 现在就是来实现这一的一个效果,大部分的都是从右向左移动漂移,本文的效果中也支持从左向右的漂移移动 效果. 二.效果图 废话不说,先来看看效果图吧~~ 三.实现原理方案 1.自定义ViewGroup-XCDanmuView,继承RelativeLayout来实现,当然也可以继承其他三大布局类哈 2.初始化若干个TextView(弹幕的item View,这里以TextView 为例,当然也

学习Jammendo代码的心路历程(一)简单的淡出效果实现

最近在看 Jammendo代码,打算将学习过程简单的记录下来,下面开始第一篇: 打开Jammendo运行之后,出弹出一个对话框,跳过对话框之后,会有一个淡出界面跳转到首页效果的实现.那么这个效果是怎么实现的呢,其实就是Animation中动画淡出的效果——原理大概是layout不透明变成全透明这样一个原理. 我这里用到的自定义endAnimation,是执行的动画效果,这里找到我事先写好的fade_out.xml,也就是一个简单的淡出效果实现: <?xml version="1.0&quo

Android中半透明Activity效果另法

Android中的Activity有没有类似于像Windows程序样的窗口式显示呢? 答案当然是有. 下图就是一个窗口式Activity的效果图: 下面就说说实现过程: 首先看看AndroidManifest.xml 1: <?xml version="1.0" encoding="utf-8"?> 2: <manifest xmlns:android="http://schemas.android.com/apk/res/android