Android 横向滚动和竖向滚动的跑马灯功能

哈喽,大家好,好久没有更新内容了,最近公司需要一个控件,跑马灯效果,可以左右滚动和上下滚动的功能,本人呢,本着能不自己写就不自己写的原则,就在网上大肆搜刮抢夺别人的代码功能,结果捏,那个,大部分都是一样,我觉得是一个人写好,然后,一群人转载的那种,让我很是费解啊,为了骗分,有的竟然那么高的分,让我很是无奈啊,其实吧,用分也没关系,可是呢,用完之后,发现没用,就很是难受啊,要么是横向可以滚动,实现得也很不错,然后,改成垂直的就那么的不是很完美了,也可能是自己能力有限吧,没有改好,其实呢,各位大佬们,你们既然发了功能,就不能把功能写详细点吗 ?让我这个小渣渣看的很是摸不着北啊 ,我就想到了,既然是滚动效果,然后呢,要想平滑的话,其实,很简单,就自己想了下,用安卓的动画,来实现这个效果,所以,我就写了今天这个博客,横向平移动画,和上下平移动画 ,具体实现规则呢,就看下面听我一点一点给你们详细说一下吧,其实,很简单,就是,写一个自定义控件,继承LinearLayout,因为,虽然我是一个TextView滚动控件,但是,我这里面,一直是TextView 自己滚动,所以,就要在LinearLayout,或者别的盒子控件,RelativeLayout也可以,别的布局都行,随你,但是,你引入的布局控件一定要是这个就行

1、控件,继承LinearLayout :

public class RollTextView extends LinearLayout 

2、几个实现方法实现出来:

    public RollTextView(Context context) {
        super(context);
        init();
    }

    public RollTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

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

3、上面也看见了,有一个init(),是的,下面就是写这个了 ,里面就是引入一个布局然后获取当前的textview内容:

 private void init() {
        View inflate = inflate(getContext(), R.layout.rollview_layout, this);
        llView = inflate.findViewById(R.id.ll_view);
        llViewBg = inflate.findViewById(R.id.ll_view_bg);
        tvMsg = inflate.findViewById(R.id.tv_msg);
        crrentMsg = tvMsg.getText().toString().trim();
}

4、然后,我把布局文件rollview_layout.xml也贴出来,看明白的自然就能知道:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ll_view_bg"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:textColor="@color/colorAccent">

    <LinearLayout
        android:id="@+id/ll_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/tv_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="我是测试数据,看一下效果如何!"
            android:textSize="30sp" />
    </LinearLayout>
</LinearLayout>

5、然后呢,就需要测量数据了,并且在测量后,得到布局中textView 应该多高和多宽,因为是对tetview 进行位移,所以,你的文本有多少,就将textview 控件进行动态设置宽高,方法传入的数据就是,当前文本内容,根据你自己设置的boolean值,来确定是横向滚动还是上下滚动

    /**
     * 测量数据
     *
     * @param msg
     */
    private void getViewMesureData(String msg) {
         TextPaint tp = tvMsg.getPaint();
        String newMsg = msg;
        int textLength;
        if (!vertical) {
            if (newMsg != null) {
                Pattern p = Pattern.compile("\\s*|\t|\r|\n");
                Matcher m = p.matcher(newMsg);
                newMsg = m.replaceAll("");
            }
            tvMsg.setText(newMsg);
             textLength = (int) tp.measureText(newMsg);
        }else{
            tvMsg.setText(msg);
             textLength = (int) tp.measureText(msg);
        }
        ViewTreeObserver vto = llView.getViewTreeObserver();
        vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                int height = getHeight();
                int width = getWidth();
                int lineHeight = tvMsg.getLineHeight();
                int lineCount = tvMsg.getLineCount();
                int textWidth = Double.valueOf(textSize).intValue();
                int tvMsgheight = lineHeight * lineCount;
                LayoutParams lp = (LayoutParams) tvMsg.getLayoutParams();
                if (!vertical) {
                    lp.width *= textLength;
                    FromXposition = width - PdLeft - PdRight;
                    ToXposition = -textLength;
                    FromYposition = 0;
                    ToYposition = 0;
                    RollMilion = RollTime * (textLength + width) / 10;
                } else {
                    lp.height = tvMsgheight;
                    FromXposition = 0;
                    ToXposition = 0;
                    FromYposition = height - PdBottom - PdTop;
                    ToYposition = -tvMsgheight;
                    RollMilion = RollTime * (tvMsgheight + height) / 10;
                }
                tvMsg.setLayoutParams(lp);
                startRollAnimation();
                llView.getViewTreeObserver().removeOnPreDrawListener(this);
                return true; //返回true,继续执行draw()
            }
        });
    }

6、下面将动画功能加进来:

   /**
     * 开始滚动
     */
    private void startRollAnimation() {
        if (rollTranslateAnimation != null) {
            rollTranslateAnimation = null;
        }
        rollTranslateAnimation = new TranslateAnimation(FromXposition, ToXposition, FromYposition, ToYposition);
        rollTranslateAnimation.setDuration(RollMilion);
        rollTranslateAnimation.setRepeatMode(Animation.RESTART);
        if (linearInterpolator == null) {
            linearInterpolator = new LinearInterpolator();
        }
        rollTranslateAnimation.setInterpolator(linearInterpolator);
        rollTranslateAnimation.setRepeatCount(ValueAnimator.INFINITE);
        tvMsg.startAnimation(rollTranslateAnimation);
    }

7、暂停动画:

    /**
     * 暂停动画
     */
    public void stopViewRoll() {
        if (rollTranslateAnimation != null)
            rollTranslateAnimation.cancel();
    }

8、更改文本内容:

    /**
     * 更改文本内容
     *
     * @param msg
     */
    public void setRollText(String msg) {
        crrentMsg = msg;
        tvMsg.setText(crrentMsg);
        stopViewRoll();
        getViewMesureData(crrentMsg);
    }

9、设置滚动方向:

   /**
     * 设置滚动方向
     *
     * @param type
     */
    public void setDirection(String type) {
        if (type.equals("1")) {
            vertical = false;
        } else if (type.equals("2")) {
            vertical = true;
        }
    }

10、设置背景,颜色或者背景图片:

    /**
     * 设置view背景颜色
     *
     * @param bgcolor
     */
    public void setRollbackground(int bgcolor) {
        llViewBg.setBackgroundColor(bgcolor);
    }

    /**
     * 设置view背景图片
     *
     * @param background
     */
    public void setRollbackground(Drawable background) {
        llViewBg.setBackground(background);
    }

11、设置字体大小:

   /**
     * 设置字体大小
     */
    public void setTextSize(int size) {
        tvMsg.setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
        stopViewRoll();
    }

12、设置padding值:

   /**
     * 设置内部间距
     *
     * @param paddingLeft
     * @param paddingTop
     * @param paddingRight
     * @param paddingBottom
     */
    public void setPadding(int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
        LayoutParams lp = (LayoutParams) llView.getLayoutParams();
        lp.leftMargin = paddingLeft;
        lp.topMargin = paddingTop;
        lp.rightMargin = paddingRight;
        lp.bottomMargin = paddingBottom;
        llView.setLayoutParams(lp);
        PdLeft = paddingLeft;
        PdTop = paddingTop;
        PdRight = paddingRight;
        PdBottom = paddingBottom;
        stopViewRoll();
    }

13、设置滚动速度:

   /**
     * 设置控件滚动速度
     * 基准值:1000
     *
     * @param speedValue
     */
    public void setRollSpeed(int speedValue) {
        RollTime = speedValue;
    }

14、设置字体颜色:

   /**
     * 设置字体颜色
     *
     * @param color
     */
    public void setRollTextColor(int color) {
        tvMsg.setTextColor(color);
    }

15、这里是控件最上面的抽取的公共变量部分:

    private boolean vertical = true;
    private TextView tvMsg;
    private LinearInterpolator linearInterpolator = new LinearInterpolator();//动画滚动类型
    private int RollMilion = 1;
    private int RollTime = 2000;   //默认滚动速度
    private Animation rollTranslateAnimation;
    private Animation verticalTranslateAnimation;

    private int FromXposition = 0;
    private int FromYposition = 0;
    private int ToXposition = 0;
    private int ToYposition = 0;
    private LinearLayout llView, llViewBg;
    private String crrentMsg = "";
    private int PdTop = 0;
    private int PdLeft = 0;
    private int PdRight = 0;
    private int PdBottom = 0;
    private float textSize;
    private int textLength;

16、还有一些需要的,自己看着改吧,其实,很简单,我这个功能,不用自己画,只需要自己计算一下滚动时间可以初始位置和结束位置就可以了,所以很容易理解,为了大家能更容易看些,我就将全部的代码都贴出来吧,嘿嘿,肯定有人问,为啥不直接就贴出来,在这废话一大堆,我说为了装13,你们信不信,这样显得我写的长,哈哈:

package com.tiekeyuan.rolltextview;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.Nullable;

public class RollTextView extends LinearLayout {

    private boolean vertical = true;
    private TextView tvMsg;
    private LinearInterpolator linearInterpolator = new LinearInterpolator();
    private int RollMilion = 1;
    private int RollTime = 2000;
    private Animation rollTranslateAnimation;
    private Animation verticalTranslateAnimation;

    private int FromXposition = 0;
    private int FromYposition = 0;
    private int ToXposition = 0;
    private int ToYposition = 0;
    private LinearLayout llView, llViewBg;
    private String crrentMsg = "";
    private int PdTop = 0;
    private int PdLeft = 0;
    private int PdRight = 0;
    private int PdBottom = 0;
    private float textSize;
    private int textLength;

    public RollTextView(Context context) {
        super(context);
        init();
    }

    public RollTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

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

    private void init() {
        View inflate = inflate(getContext(), R.layout.rollview_layout, this);
        llView = inflate.findViewById(R.id.ll_view);
        llViewBg = inflate.findViewById(R.id.ll_view_bg);
        tvMsg = inflate.findViewById(R.id.tv_msg);
        crrentMsg = tvMsg.getText().toString().trim();
    }

    /**
     * 测量数据
     *
     * @param msg
     */
    private void getViewMesureData(String msg) {
        TextPaint tp = tvMsg.getPaint();
        String newMsg = msg;
        int textLength;
        if (!vertical) {
            if (newMsg != null) {
                Pattern p = Pattern.compile("\\s*|\t|\r|\n");
                Matcher m = p.matcher(newMsg);
                newMsg = m.replaceAll("");
            }
            tvMsg.setText(newMsg);
             textLength = (int) tp.measureText(newMsg);
        }else{
            tvMsg.setText(msg);
             textLength = (int) tp.measureText(msg);
        }
        ViewTreeObserver vto = llView.getViewTreeObserver();
        vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                int height = getHeight();
                int width = getWidth();
                int lineHeight = tvMsg.getLineHeight();
                int lineCount = tvMsg.getLineCount();
                int textWidth = Double.valueOf(textSize).intValue();
                int tvMsgheight = lineHeight * lineCount;
                LayoutParams lp = (LayoutParams) tvMsg.getLayoutParams();
                if (!vertical) {
                    lp.width *= textLength;
                    FromXposition = width - PdLeft - PdRight;
                    ToXposition = -textLength;
                    FromYposition = 0;
                    ToYposition = 0;
                    RollMilion = RollTime * (textLength + width) / 10;
                } else {
                    lp.height = tvMsgheight;
                    FromXposition = 0;
                    ToXposition = 0;
                    FromYposition = height - PdBottom - PdTop;
                    ToYposition = -tvMsgheight;
                    RollMilion = RollTime * (tvMsgheight + height) / 10;
                }
                tvMsg.setLayoutParams(lp);
                startRollAnimation();
                llView.getViewTreeObserver().removeOnPreDrawListener(this);
                return true; //返回true,继续执行draw()
            }
        });
    }

    /**
     * 开始滚动
     */
    private void startRollAnimation() {
        if (rollTranslateAnimation != null) {
            rollTranslateAnimation = null;
        }
        rollTranslateAnimation = new TranslateAnimation(FromXposition, ToXposition, FromYposition, ToYposition);
        rollTranslateAnimation.setDuration(RollMilion);
        rollTranslateAnimation.setRepeatMode(Animation.RESTART);
        if (linearInterpolator == null) {
            linearInterpolator = new LinearInterpolator();
        }
        rollTranslateAnimation.setInterpolator(linearInterpolator);
        rollTranslateAnimation.setRepeatCount(ValueAnimator.INFINITE);
        tvMsg.startAnimation(rollTranslateAnimation);
    }


    /**
     * 暂停动画
     */
    public void stopViewRoll() {
        if (rollTranslateAnimation != null)
            rollTranslateAnimation.cancel();
    }

    /**
     * 开始动画
     */
    public void startViewRoll() {
        getViewMesureData(crrentMsg);
    }

    /**
     * 更改文本内容
     *
     * @param msg
     */
    public void setRollText(String msg) {
        crrentMsg = msg;
        tvMsg.setText(crrentMsg);
        stopViewRoll();
        getViewMesureData(crrentMsg);
    }

    /**
     * 设置滚动方向
     *
     * @param type
     */
    public void setDirection(String type) {
        if (type.equals("1")) {
            vertical = false;
        } else if (type.equals("2")) {
            vertical = true;
        }
    }

    /**
     * 设置view背景颜色
     *
     * @param bgcolor
     */
    public void setRollbackground(int bgcolor) {
        llViewBg.setBackgroundColor(bgcolor);
    }

    /**
     * 设置view背景图片
     *
     * @param background
     */
    public void setRollbackground(Drawable background) {
        llViewBg.setBackground(background);
    }

    /**
     * 设置字体大小
     */
    public void setTextSize(int size) {
        tvMsg.setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
        stopViewRoll();
    }

    /**
     * 设置内部间距
     *
     * @param paddingLeft
     * @param paddingTop
     * @param paddingRight
     * @param paddingBottom
     */
    public void setPadding(int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
        LayoutParams lp = (LayoutParams) llView.getLayoutParams();
        lp.leftMargin = paddingLeft;
        lp.topMargin = paddingTop;
        lp.rightMargin = paddingRight;
        lp.bottomMargin = paddingBottom;
        llView.setLayoutParams(lp);
        PdLeft = paddingLeft;
        PdTop = paddingTop;
        PdRight = paddingRight;
        PdBottom = paddingBottom;
        stopViewRoll();
    }

    /**
     * 设置控件滚动速度
     * 基准值:1000
     *
     * @param speedValue
     */
    public void setRollSpeed(int speedValue) {
        RollTime = speedValue;
    }

    /**
     * 设置字体颜色
     *
     * @param color
     */
    public void setRollTextColor(int color) {
        tvMsg.setTextColor(color);
    }
}

 

最后,当然,个人写的是根据个人公司需要的功能写的,很多属性,你们可以直接配置一下,那样就可以直接在调用的地方,xml里面直接将属性写上不用那么多方法调用,所以根据个人项目需要吧,然后呢,个人觉得,还是有必要将demo也发一下,我需要一点积分,如果可以的话,大家支持一下,给我点积分,谢谢大家了!

资源Demo下载:点我点我,对,就是,点我,就能下载了 .

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值