1. 背景

    需要做一个跑马灯效果的文字展示,本方案更适用于开发机顶盒应用的同学们。

2. 需求

    2.1 展示书籍的页面,文字过多的时候需要折叠

    2.2 当焦点在此书籍上的时候,需要将折叠的文字滚动起来

 

3. 需求剖析

    3.1 正常情况下使用跑马灯,只需要设置Textview的以下属性即可

android:ellipsize="marquee"android:marqueeRepeatLimit="marquee_forever"android:scrollHorizontally="true"android:singleLine="true"

    设置完成之后,当这个TextView有焦点的时候,且文字过长的时候,就会展现跑马灯效果,注意当TextView请求焦点的时候,跑马灯效果才展示,否则无效。

    3.2 但是在机顶盒上,app是需要使用焦点效果来展示你所选的当前item,也就是通常所说的“落焦”。

    3.3 这时候使用跑马灯的时候会产生两个问题

        问题一:我的item是在一个recycleView当中,充当跑马灯的TextView只是recycleView中子view 中的子view,我外层的布局需要拿到焦点,才能在recycleView中正常移动。

        问题二:即使我将TextView设置请求焦点,那么当我从当前的item向上滑动的时候,recycleView就不再认为我是在他的子view间移动,recycleView的翻页效果会有问题,就是当你上一行展示了一半,但是我焦点已经在上一行了,但是上一行却没有展示完全。如下图所示:

4. 解决思路

    4.1 我需要有一个不需要焦点,仍然能够展现跑马灯的控件,避免与recycleView之间的冲突

    4.2 同时我这个控件也需要有TextView原有的功能,便于我在简单情况下使用跑马灯效果

 

5. 代码

    5.1 布局文件 resource_item.xml

<?xml version="1.0" encoding="utf-8"?>                

    5.2 自定义view

package plat.skytv.main.view;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.text.TextPaint;import android.util.AttributeSet;import androidx.appcompat.widget.AppCompatTextView;import plat.skytv.main.util.PLog;public class MarqueeText extends AppCompatTextView implements Runnable {    private int xLocation;// 当前滚动的位置    private boolean isStop = false;    private int textWidth;    private boolean isMeasure = false;    private float speed = 1; // 移动速度    private String string; // 需要绘制得文字    public MarqueeText(Context context) {        super(context);    }    public MarqueeText(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MarqueeText(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    float textHeight;    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (!isMeasure) {// 文字宽度只需获取一次就可以了            getTextWidth();            textHeight = getTextHeight(getPaint());            isMeasure = true;            string = this.getText().toString();        }        canvas.drawText(string, xLocation, getHeight() / 2 + textHeight / 2, getPaint());    }    /**     * http://blog.csdn.net/u014702653/article/details/51985821     * 详细解说了     *     * @param     * @return     */    private float getTextHeight(Paint paint) {        Paint.FontMetrics fontMetrics = paint.getFontMetrics();        return Math.abs((fontMetrics.bottom - fontMetrics.top)) / 2;    }    /**     * 获取文字宽度     */    private void getTextWidth() {        Paint paint = this.getPaint();        string = this.getText().toString();        PLog.e("getTextWidth str = " + string);        textWidth = (int) paint.measureText(string);    }    @Override    public void run() {        xLocation -= speed;// 滚动速度        if (isStop) { // 停止滚动后恢复初始状态            xLocation = 0;            return;        }        if (textWidth <= (-xLocation)) {            //也就是说文字已经到头了            xLocation = getWidth();        }        postInvalidate();        postDelayed(this, 10);    }    // 开始滚动 针对不能请求焦点的情况    public void startScroll() {        if (textWidth <= this.getWidth()) { // 文字长度 <= view长度,不需要滚动            return;        }        setText("");// 需要设置空 否则展示两个文字        setSingleLine(false); // 需要设置false,否则无法滚动        isStop = false;        this.removeCallbacks(this);        post(this);    }    // 停止滚动    public void stopScroll() {        isStop = true;        setText(string);        setSingleLine(true);    }}

    5.3 使用

    在recycleView绑定数据的时候设置焦点变化监听

ImageView mItemFocus = itemView.findViewById(R.id.item_focus); // 展示焦点效果的viewMarqueeText mItemName = itemView.findViewById(R.id.item_name);mItemFocus.setOnFocusChangeListener(new View.OnFocusChangeListener() {            @Override            public void onFocusChange(View v, boolean hasFocus) {                if (hasFocus) {                    mItemName.startScroll();                } else {                    mItemName.stopScroll();                }            }        });

6. 问题

    6.1 在布局文件中,设置了singleline = true,结果,调用  startScroll 时无法滚动。

    6.2 在滚动之前必须将本TextView的text设置为空串,否则将出现两个文本。

    6.3 先存疑,以后找到结果了再贴上去

7. 参考文档:

    7.1 http://blog.csdn.net/u014702653/article/details/51985821

    7.2 https://www.cnblogs.com/hyhy904/p/11329139.html

更多相关文章

  1. Android之玩转View
  2. Android(安卓)如何让EditText不自动获取焦点
  3. Android核心分析(14)------ Android(安卓)GWES之输入系统
  4. Android(安卓)ClickableSpan 应用实例
  5. Android—文字轮播
  6. Android自由选择TextView的文字
  7. android 控件 NumberPicker 简单使用
  8. Android(安卓)自定义控件 按钮滚动选择
  9. Android输入法扩展之外接键盘中文输入

随机推荐

  1. Android之网络开发详解
  2. 【原创】android 实现气泡式listview
  3. jqMobi + Android(安卓)试手
  4. Android(安卓)development with maven
  5. 滁州学院首页获取新闻列表
  6. Android入门:Activity四种启动模式
  7. 非常全的android manifest详解
  8. Notification学习
  9. parseSdkContent failed Could not initi
  10. 第23章 0115-Vue基础与常用指令介绍,学习