Android 单行文本的跑马灯

最近项目有一个实现跑马灯效果的需求,需求很简单,就是单行文本(只有几个字)无限循环的效果,最开始也是百度和Github上找,找寻半天不是有BUG就是无法达到需求,最后在一位博主jixiaolong<microjixl@gmail.com>的github上借鉴了他所写的自定义View,该博主的自定义控件是作为多行文本使用的,但是该控件也有BUG,就是多行文本切换的太不自然,或者说,实际中用不成。因此本文介绍的控件只针对单行文本使用,滑动自然,不反人类,先看下效果:


废话不多说,奉上具体用法,再强调一遍,只适合单行文本!!!!!!!!!!!

1.自定义View

import java.util.List;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Paint;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.TextView;

/**
 * @author jixiaolong<[email protected]>
 */
@SuppressLint("AppCompatCustomView")
public class BulletinView extends TextView implements Runnable{
	private int currentScrollX;// 当前滚动的位置
	private boolean isStop = false; 
	private int textWidth; 
	private List<String> mList;
	private final int REPEAT = 1;
	private int repeatCount = 0;
	private int currentNews = 0;

	public BulletinView(Context context) { 
		super(context); 
		init();
		// TODO Auto-generated constructor stub 
	} 
	public BulletinView(Context context, AttributeSet attrs) { 
		super(context, attrs); 
		init();
	} 
	public BulletinView(Context context, AttributeSet attrs, int defStyle) { 
		super(context, attrs, defStyle); 
		init();
	} 
	
	public void init(){
		setClickable(true);
		setSingleLine(true);
		setEllipsize(TruncateAt.MARQUEE);
		setGravity(Gravity.START|Gravity.CENTER_VERTICAL);
	}
	
	public void setData(List<String> mList){
		if(mList == null || mList.size()==0){
			return;
		}
		this.mList = mList; 
		currentNews = 0;
		String n = mList.get(currentNews);
		setText(n);
		setTag(n);
		startScroll();
	}
	
	@Override
	public void setText(CharSequence text, BufferType type) {
		super.setText(text, type);
		MeasureTextWidth(); 
	}
	
	@Override
	public void onScreenStateChanged(int screenState) {
		super.onScreenStateChanged(screenState);
		if(screenState == SCREEN_STATE_ON){
			startScroll();
		}else{
			stopScroll();
		}
	}
	
	/** 
	 * 获取文字宽度 
	 */ 
	private void MeasureTextWidth() { 
		Paint paint = this.getPaint(); 
		String str = this.getText().toString(); 
		textWidth = (int) paint.measureText(str); 
	} 

	@Override 
	public void run() { 
		if(textWidth < 1){
			//title null api error.
			if(mList != null && mList.size() > 0){
				nextNews();
			}else{
				return;
			}
		}
		currentScrollX += 5;// 滚动速度
		scrollTo(currentScrollX, 0); 
		if (isStop) { 
			return; 
		}
			if (getScrollX() >= textWidth) {
				currentScrollX = -getWidth();
				if(repeatCount >= REPEAT){
					//reach max times 我对原文的修改只有这么一点 start
					if (mList.size()==1){
						scrollTo(currentScrollX, 0);
					}else {
						nextNews();
						scrollTo(currentScrollX,0);
					}
					//我对原文的修改只有这么一点 end
				}else{
					repeatCount ++;
				}

			}
		
		postDelayed(this, 50); 
	}
	
	private void nextNews(){
		repeatCount = 0;
		currentNews ++;
		currentNews = currentNews%mList.size();//cycle index
		String n = mList.get(currentNews);
		setText(n);
		setTag(n);
	}

	// 开始滚动 
	public void startScroll() { 
		isStop = false; 
		this.removeCallbacks(this); 
		post(this); 
	} 
	// 停止滚动 
	public void stopScroll() { 
		isStop = true; 
	} 
}


2.xml使用
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.anshi.chattraining.BulletinView
        android:id="@+id/tv_bulletin"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:textColor="@android:color/white"
        android:padding="10dp"
        android:background="#b0000000"
        android:textSize="20sp" />

</RelativeLayout>
3.Activity使用
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * Created by yulu on 2017/12/12.
 */

public class MarqueeActivity extends AppCompatActivity {
    private BulletinView view;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.marquee_activity);
        view = (BulletinView) findViewById(R.id.tv_bulletin);
        List<String> mList = new ArrayList<>();
        mList.add("今天共找寻成功22对");
        view.setData(mList);
    }
    @Override
    protected void onResume() {
        view.startScroll();
        super.onResume();
    }

    @Override
    protected void onPause() {
        view.stopScroll();
        super.onPause();
    }

}
end.........................就这样把,其他的用SurfaceView做的多半都有些问题,还是用TextView做吧。博主原文地址



猜你喜欢

转载自blog.csdn.net/hardWork_yulu/article/details/78789617