安卓—简单实现直播间垂直聊天弹幕控件

公司项目需对扣分情况进行实时展示,类似滤镜美颜直播间垂直展示聊天弹幕。网上找实现方法后,选了简单方式。为避免Activity代码杂乱,继承LinearLayout并对外提供所需方法,还提及布局文件、动画使用等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

公司项目新加需求,可以对扣分情况进行实时展示,就像某大型滤镜美颜直播间那种垂直展示聊天弹幕一样,在网上找了好多大佬的实现方法,发现我们的需求只是简单的展示,就选了一个最简单的方式实现 链接地址
但是发现这兄弟把代码都堆在了Activity里面,我的直播界面代码已经够多了,防止Activity代码太乱,就继承了一下LinearLayout,只对外提供目前需要的几个方法

  • 继承之后的代码
/**
 * @author: OlderJiao
 * @date: 2020/12/18
 * @ClassName: yjz_student_android
 */
public class MyDanmuView extends LinearLayout {

    private LayoutTransition transition;

    //最大展示数量 默认四条
    private int maxItem = 4;

    public MyDanmuView(Context context) {
        super(context);
    }

    public MyDanmuView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyDanmuView);
        maxItem = typedArray.getInteger(R.styleable.MyDanmuView_maxItem, maxItem);
        typedArray.recycle();
        init();
    }

    public MyDanmuView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init() {
        transition = new LayoutTransition();
        //创建属性动画
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(null, "alpha", 0, 1);
        //动画监听
        objectAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationCancel(Animator animation) {
                super.onAnimationCancel(animation);

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                //动画结束
                if (getChildCount() == maxItem + 1) {
                    handler.sendEmptyMessage(2);
                }
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                super.onAnimationRepeat(animation);
            }

            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                //动画开始
                if (getChildCount() == maxItem) {
                    handler.sendEmptyMessage(1);
                }
            }
        });

        //设置layout动画属性
        transition.setAnimator(LayoutTransition.APPEARING, objectAnimator);
        //删除的动画效果
        PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0, 0);
        ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(null, new PropertyValuesHolder[]{alpha}).setDuration(transition.getDuration(LayoutTransition.DISAPPEARING));
        transition.setAnimator(LayoutTransition.DISAPPEARING, animator);
        setLayoutTransition(transition);
    }

    /**
     * 设置最大展示数量
     *
     * @param maxItem
     */
    public void setMaxItem(int maxItem) {
        this.maxItem = maxItem;
    }

    public void setData(String name, String cause) {
        View view = getTextView();
        //获取学生姓名
        TextView nameTxt = view.findViewById(R.id.studentNameTxt);
        //扣分原因
        TextView causeTxt = view.findViewById(R.id.causeTxt);

        //设置学生姓名
        nameTxt.setText(TextUtils.isEmpty(name) ? "佚名" : name);
        //扣分原因
        causeTxt.setText(TextUtils.isEmpty(cause) ? "无" : cause);
        //添加子布局
        addView(view);
    }

    /**
     * 获取子控件布局
     *
     * @return View
     */
    private View getTextView() {
        return LayoutInflater.from(getContext()).inflate(R.layout.item_live_danmu, null);
    }

    /**
     * 回收
     */
    public void destory() {
        if (handler != null) {
            handler.removeCallbacksAndMessages(null);
            handler = null;
        }
        if (transition != null) {
            if (!transition.isRunning()) {
                transition = null;
            }
        }
    }

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                    //给展示的第一个view增加渐变透明动画
                    getChildAt(0).animate().alpha(0).setDuration(transition.getDuration(LayoutTransition.APPEARING)).start();
                    break;
                case 2:
                    //删除顶部view
                    removeViewAt(0);
                    break;
            }
        }
    };

}

布局文件可以自己去定义,其中关于ObjectAnimator和PropertyValuesHolder的使用看一下这篇文章,这里就不赘述了,还有另外用到的一个动画 PropertyValuesHolder

  • 自定义属性代码
<declare-styleable name="MyDanmuView">
        <attr name="maxItem" format="integer" />
    </declare-styleable>

使用的时候,布局里面直接引用就好了

最后,让我们共同开发,共同进步。谢谢!!!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值