Android 自定义View 实现跑马灯功能 (传list 集合)

最近要做一个跑马灯功能,要求滚动效果展示不同的内容,并且支持对内容进行增删。

GitHub 中已经有一些比较优秀的库,他们是基于ViewFlipper 实现的,可以设置动画效果和动画时长等
MarqueeView   
MarqueeViewLibrary

但是当设置singleLine = true  的时候,超过屏幕的数据就自动为省略号或者不显示了

这样就满足不了我的需求,当然我需要的需求也简单,仅一个TextView  就能满足。

所以我直接自定义TextView 实现效果。

废话不多说,直接上代码

public class MarqueeView extends TextView implements View.OnClickListener {

    public final static String TAG=MyText.class.getSimpleName();

    private float textLength = 0f;// 文本长度
    private float viewWidth = 0f;
    private float step = 0f;// 文字的横坐标
    private float y = 0f;// 文字的纵坐标
    private float temp_view_plus_text_length = 0.0f;// 用于计算的临时变量
    private float temp_view_plus_two_text_length = 0.0f;// 用于计算的临时变量
    public boolean isStarting = false;// 是否开始滚动
    private Paint paint = null;// 绘图样式
    private String text = "";// 文本内容
    private float currentScrollX;// 当前滚动的位置
    private float lastIndex = 0f;//上一次滚动的位置

    private List<String> strings = new ArrayList<>();
    private int marqueeIndex = 0;
    private WindowManager windowManager;


    public void setWindowManager(WindowManager windowManager) {
        this.windowManager = windowManager;
    }

    //更新list后,从第1条重新开始

    public void setStrings(List<String> strings) {
        this.strings = strings;
        marqueeIndex = 0;
    }

    public MarqueeView(Context context) {
        super(context);
        initView();
    }

    public MarqueeView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public MarqueeView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView();
    }

    /**
     * 初始化控件
     */
    private void initView() {
        setOnClickListener(this);
    }

    public void setTextContent(String text){
        setText(text);
        init();
    }

    /**
     * 文本初始化,每次更改文本内容或者文本效果等之后都需要重新初始化一下
     */
    public void init() {
        try {
            paint = getPaint();
            paint.setColor(getTextColors().getDefaultColor());
            text = getText().toString();
            textLength = paint.measureText(text);
            viewWidth = getWidth();
            if (viewWidth == 0) {
                if (windowManager != null) {
                    Display display = windowManager.getDefaultDisplay();
                    viewWidth = display.getWidth();
                }
            }
            step = textLength;
            temp_view_plus_text_length = viewWidth + textLength;
            temp_view_plus_two_text_length = viewWidth + textLength * 2;
            y = getTextSize() + getPaddingTop();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 开始滚动
     */
    public void startScroll() {
        try {
            isStarting = true;
            setViewText();
            invalidate();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void setViewText() {
        if (marqueeIndex == strings.size()){
            marqueeIndex = 0;
        }
        setTextContent(strings.get(marqueeIndex));
        marqueeIndex++;
    }

    /**
     * 停止滚动
     */
    public void stopScroll() {
        try {
            isStarting = false;
            invalidate();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDraw(Canvas canvas) {
        try {
            lastIndex = currentScrollX;
            canvas.drawText(text, temp_view_plus_text_length - step, y, paint);
            currentScrollX = temp_view_plus_text_length - step;

            //重点,通过滚动的坐标,来判断一条数据是否完全消失,

           //如果只有单条数据,可直接注释这两行代码
            Log.d(TAG,"===lastIndex==="+lastIndex +"=currentScrollX==" + currentScrollX);
            if (lastIndex < 0 && currentScrollX > 0){
                setViewText();
            }

            if (!isStarting) {
                return;
            }
            step += 5;// 速度
            if (step > temp_view_plus_two_text_length) {
                step = textLength;
            }
            invalidate();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 控制
    @Override
    public void onClick(View v) {
        try {
            if (isStarting) {
                stopScroll();
            }else {
                startScroll();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean isFocused() {
        return true;
    }


    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        if (focused) {
            super.onFocusChanged(focused, direction, previouslyFocusedRect);
        }
    }

    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        if (hasWindowFocus)
            super.onWindowFocusChanged(hasWindowFocus);
    }
}
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值