package com.iqilu.core.common.adapter.widgets.notice; import android.animation.Animator; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.util.Log; import android.view.ViewTreeObserver; import android.view.animation.DecelerateInterpolator; import android.view.animation.LinearInterpolator; import android.widget.Scroller; import androidx.appcompat.widget.AppCompatTextView; import com.blankj.utilcode.util.ScreenUtils; import com.iqilu.core.CoreStringType; import com.umeng.commonsdk.debug.E; import java.text.DecimalFormat; public class AutoScrollTextViewNew extends AppCompatTextView { private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); private boolean isScrolling = false; /** * 最大可滚动距离 */ private int maxScrollX; private String showMessage = ""; private ValueAnimator animator; private ScrollStatus scrollStatus; /** * 空格 */ private String Space = " "; /** * scrollX每次移动的坐标 * lastScrollX最后移动的坐标 */ private int scrollX = 0,lastScrollX = 0; /** * 滚动速度,数值越大,速度越快 */ private double scrollNumber = 150.00; /** * 字体大小 */ private int textSize = CoreStringType.SEVENTEEN; private DecimalFormat df; public AutoScrollTextViewNew(Context context) { super(context); init(); } public AutoScrollTextViewNew(Context context, AttributeSet attrs) { super(context, attrs); init(); } public AutoScrollTextViewNew(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { df = new DecimalFormat("#.00"); paint.setColor(Color.parseColor("#535353")); paint.setTextSize(textSize); paint.setTextAlign(Paint.Align.LEFT); setSingleLine(true); // 设置单行模式 // 监听布局变化,以便在布局完成后计算最大滚动距离 getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (getLayout() != null) { // 计算最大滚动距离 int textWidth = (int) getPaint().measureText(showMessage); int viewWidth = getWidth() - getPaddingLeft() - getPaddingRight(); maxScrollX = Math.max(0, textWidth - viewWidth); // 如果内容超出视图宽度,则开始滚动 if (maxScrollX > 0 && !isScrolling) { startScrolling(maxScrollX); }else { scrollStatus.putScrollStatus(showMessage); } // 移除监听器,避免重复调用 getViewTreeObserver().removeOnGlobalLayoutListener(this); } } }); } private void startScrolling(int scrollDistance) { /** * 这里必须减掉本身的宽度,如果不减,lastScrollX会越来越大,速度就会越来越慢 */ if(lastScrollX>scrollDistance){ lastScrollX = lastScrollX - scrollDistance; } /** * 时间不能变,时间要在scrollDistance变化之前 */ Log.e("11111111tscrollDistance",scrollDistance+""); double time = Double.parseDouble(df.format((double)(scrollDistance/scrollNumber))); Log.e("11111111time",time+""); scrollDistance = lastScrollX + scrollDistance; // 创建ValueAnimator animator = ValueAnimator.ofInt(lastScrollX, scrollDistance); // 设置动画的持续时间 animator.setDuration((long) (time*1000)); // 设置插值器,这里使用默认的(线性插值器),但你可以根据需要更改 animator.setInterpolator(new LinearInterpolator()); // 添加更新监听器,在动画的每一帧中更新TextView的滚动位置 animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { lastScrollX = scrollX; scrollStatus.putScrollStatus(showMessage); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); animator.addUpdateListener(animation -> { scrollX = (int) animation.getAnimatedValue(); setScrollX(scrollX); }); // 开始动画 animator.start(); } // 确保在视图不再需要时停止滚动 @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); isScrolling = false; if(animator!=null){ animator.pause(); } } public void setShowText(String message,ScrollStatus scrollStatus){ this.showMessage = message; setText(message); this.scrollStatus = scrollStatus; } /** * 设置接下来需要滚动的内容以及距离 */ public void setNextScrollTextMessage(){ if(maxScrollX > 0){ append(Space+showMessage); int textSize = (int) getPaint().measureText(Space); int textWidth = (int) getPaint().measureText(showMessage); int allWidth = textWidth+textSize; startScrolling(allWidth); }else { scrollStatus.putScrollStatus(showMessage); } } public interface ScrollStatus{ void putScrollStatus(String message); } }
自定义View后来想了想是不是因为不同长度文字第二次因为长度不同,算除法的时候时间这里出问题了,后来想了想,把时间预留两位,时间越精细一些,两个相邻的VIew才能更同步