Android 原生的跑马灯 MarqueeTextView

Android 原生的跑马灯 MarqueeTextView

前段时间需求中有一个横向滚动公告(多条)功能,TextView采用自带的跑马灯效果时无法完全满足我的标准,因此在网上查找其它解决方案,找了不同方法实现的案例,但整体效果都不太理想,要么存在缺陷,最终找到xiaweizi/MarqueeTextView这个方案,感谢作者gitHub的开源项目。

优化后的具体代码已分享到GitHub liyazhou0221/LeaningProject需要下载的请前往下载

一、方案优点

1、原理:本方案在Android中的TextView自带跑马灯效果的基础上,通过Scroller控制器来控制整个View的滚动。
2、功能:控制滚动时间(速度)、控制滚动延迟、控制滚动模式、生命周期可以自己控制(暂停-继续-重新开始-停止)

二、新增优化内容(在原有的基础上新增部分内容)

1、支持多条数据
2、为每条数据添加点击事件监听
3、添加自定义滚动速度控制

三、具体使用方法

Java代码:


noticeTextV.setOnItemClickListener(new MarqueeTextView.OnMarqueeItemClickListener() {
                @Override
                public void onClick(int position) {
                    // 根据点击位置获取具体是那个公告
                    JSONObject jsonObject = noticeArray.getJSONObject(position);
                   // ...
                }
                @Override
                public String[] initShowTextList() {
                	// 根据需要显示的内容,生成显示数组对象
                    String[] strings = new String[noticeArray.size()];
                    for (int i = 0; i < noticeArray.size(); i++) {
                        strings[i] = noticeArray.getJSONObject(i).getString("key");
                    }
                    return strings;
                }
            });
            noticeTextV.startScroll();

2、xml配置

<!--横向滚动公告-->
<declare-styleable name="MarqueeTextView">
    <!--滚动时长毫秒-->
    <attr name="scroll_interval" format="integer" />
    <attr name="scroll_speed" format="integer" />
    <attr name="scroll_first_delay" format="integer" />
    <attr name="scroll_mode">
        <enum name="mode_forever" value="100" />
        <enum name="mode_once" value="101" />
    </attr>
</declare-styleable>

<MarqueeTextView
    android:id="@+id/notice_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:orientation="horizontal"
    android:textColor="@color/md_orange_EC8423"
    android:textSize="?text_size_normal"
    app:scroll_first_delay="0"
    app:scroll_mode="mode_forever"
    app:scroll_speed="100" />

四、具体实现

1、支持多条数据

	/**
     * 添加显示的公告列表,并
     * @param list
     */
    public void setData(String[] list) {
        this.listData = list;
        showTextData = getShowTextData();
        setText(showTextData);
    }
	/**
     * 拼接显示字符串,并计算出每个item所在的位置
     * @return
     */
    private String getShowTextData() {
        if (listData != null && listData.length > 0) {
            listDataPos = new int[listData.length];
            StringBuilder showData = new StringBuilder();
            for (int i = 0; i < listData.length; i++) {
                showData.append(listData[i]);
                // 每一条后都添加空格占位符
                showData.append("\t\t\t\t");
                listDataPos[i] = calculateScrollingLen(showData.toString());
            }
            return showData.toString();
        } else {
            return getText().toString();
        }
    }
     /**
     * 计算滚动的距离
     * @return 滚动的距离
     */
    private int calculateScrollingLen(String strTxt) {
        if (TextUtils.isEmpty(strTxt)) {
            return 0;
        }
        TextPaint tp = getPaint();
        Rect rect = new Rect();
        tp.getTextBounds(strTxt, 0, strTxt.length(), rect);
        return rect.width();
    }

2、为每条数据添加点击事件监听

	// 手势监听
	@Override
    public boolean onTouchEvent(MotionEvent event) {
        // 将触摸事件交给手势处理
        mGestureDetector.onTouchEvent(event);
        return true;//继续执行后面的代码
    }
    private GestureDetector.OnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            // 点击事件 获取点击的位置
            if (onItemClickListener != null) {
                float clickX = mScroller.getCurrX() + e.getX();
                for (int i = 0; i < listDataPos.length; i++) {
                    if (clickX >= 0 && clickX <= listDataPos[i]) {
                        onItemClickListener.onClick(i);
                        break;
                    }
                }
            }
            return super.onSingleTapConfirmed(e);
        }
    };

3、添加自定义接口

	/**
     * 提供一个对外的初始化显示数据集合的方法
     *
     * @return 显示点数组
     */
    public interface OnMarqueeItemClickListener {
        void onClick(int position);
        String[] initShowTextList();
    }
上一篇:el-table ,数据更新,但是里面的 el-table-column 下的template,无法更新


下一篇:寒假学习笔记06