Android:简易弹幕效果实现

首先上效果图,类似于360检测到骚扰电话页面:

布局很简单,上面是一个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;
    }
}
时间: 2024-10-04 00:17:18

Android:简易弹幕效果实现的相关文章

Android:简单的弹幕效果达到

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

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

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

又一枚精彩的弹幕效果jQuery实现

精彩的弹幕效果分享给大家,具有一定的参考价值,感兴趣的朋友可以尝试制作弹幕,具体内容如下 简易弹幕效果:将发布的内容随机显示在弹幕右侧,逐渐左移最后消失. 涉及知识点:val().random().height().css().append().remove()等,主要是元素的操作 html代码: ? 1 2 3 4 5 6 7 8 9 <a href="#">弹幕技术</a>   <div class="mask">     &

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

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

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

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

Android 导航条效果实现(六) TabLayout+ViewPager+Fragment

TabLayout 一.继承结构 public class TabLayout extends HorizontalScrollView java.lang.Object ? android.view.View ? android.view.ViewGroup ? android.widget.FrameLayout ? android.widget.HorizontalScrollView ? android.support.design.widget.TabLayout 二.TabLayou

弹幕效果

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>仿弹幕效果</title> <style> *{margin: 0;padding: 0;list-style: none;} html,body{width: 100%;height: 100%;} body{background-color:

Android自定义弹窗效果

Android的弹窗效果有很多种,就最简单而言,就可以调用一个AlertDialog弹窗显示,可是要自定义弹窗效果有以下这种方法,就我个人而言感觉挺方便的,适用性也挺广的. 首先先简单写个AlertDialog的使用 public void showDialog(){ AlertDialog dialog = new AlertDialog.Builder(this) .setTitle("提示") .setMessage(getResources().getString("

Android简易实战教程--第一话《最简单的计算器》

转载请注明出处:http://blog.csdn.net/qq_32059827/article/details/51707931 从今天开始,本专栏持续更新Android简易实战类博客文章.和以往专栏不同,此专栏只有实例.每个实例尽量按照知识点对应相应一章节的内容去写,循序渐进.有些实例可能会与另一个专栏有重复的文章. 开始本专栏的第一个简易案例: 首先设置两个布局文件,一个布局文件进行输入数据,获取加法运算:另一个布局文件进行显示最终结果.Activity1启动Activity2,并传递计算