Android:简单的弹幕效果达到

Android:简单的弹幕效果达到

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

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

Android:简单的弹幕效果达到

布局非常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 

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/116834.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Spring集成MyBaties中sqlSessionFactory的创建[通俗易懂]

    Spring集成MyBaties中sqlSessionFactory的创建[通俗易懂]Spring的核心思想就是IOC(InversionOfControl),中文意思就是控制反转,将创建对象的任务交由工厂来处理,同时还可以管理类与类之间的关系,从而提出了依赖注入的概念。先来了解对象的分类:1.简单对象:可以通过new的方式创建的对象,例如UserServiceImle、User类等2.复杂对象:不能通过new的方式创建的对象,例如sqlSessionFact…

  • 神经网络loss函数意义_lossfunction

    神经网络loss函数意义_lossfunctionL1Loss平均绝对误差(MAE),用于回归模型对于包含NNN个样本的batch数据D(x,y)D(x,y)D(x,y),losslossloss计算如下:loss=1N∑n=1Nlnloss=\frac{1}{N}\sum_{n=1}^{N}l_{n}loss=N1​∑n=1N​ln​其中,ln=∣xn−yn∣l_{n}=\left|x_{n}-y_{n}\right|ln​=∣xn​−yn​∣classL1Loss(_Loss):__constants__=[‘redu

  • 开启 MySQL 慢查询日志

    开启 MySQL 慢查询日志开启MySQL慢查询日志开启mysql的慢查询日志,可以记录查询超过指定时间的sql语句,可以方便更好的优化数据库系统的性能。一、参数说明slow_query_log:慢查询日志开启状态slow_query_log_file:慢查询日志存放位置long_query_time:查询超过多少秒才记录二、设置步骤1、查询相关参数配置mysql>showvariab…

  • vs实现用户注册登录_用户注册登录怎么填写

    vs实现用户注册登录_用户注册登录怎么填写publicstaticUserInfoGetUser(stringname,stringpwd){//填写搜索姓名和密码的sql语句stringsql=string.Format(“select*fromUserInfowhereLoginName='{0}’andPassword='{1}'”,name,pwd);DataTabledt=DBHelper.ExcuteTab.

    2022年10月13日
  • pycharm运行后出现process finished_pycharm进程已结束,退出代码0

    pycharm运行后出现process finished_pycharm进程已结束,退出代码0pycharm运行代码只显示Processfinishedwithexitcode0的解决办法通过右键xxx.py点击run按钮执行文件,提示Processfinishedwithexitcode0但是通过py.test的命令就可以执行成功且无以下的绿色执行按钮只需要在以下路径中进行设置然后重启pycharm就可以:…

  • armv7与armv8的区别(v8和w12的区别)

    ARMv7与ARMv8的处理器架构自己一直没有详细了解过,现在来学习一下,在armcommunity中文社区看到一个不错的总结。两者之间的区别主要如下:ARMv8指令集分为Aarch64和Aarch32指令集,而ARMv7使用的是A32和T16指令集(分别为32位和16位)。现今我们常见的手机处理器多为8核,采用大小核心伴侣架构,比如Kirin970处理器(4*Co…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号