使用定时器实现简单的字体闪烁并实现字体跑马灯

最近在项目中有一个小需求,实现TextView字体颜色闪烁,来表示某个功能正在运行,从网上扒了一些资料,发现实现这种效果有两种方法,一是用动画,二是用定时器

在这里,我就介绍一下用定时器如何实现字体闪烁

package com.example.timer;

import java.util.Timer;
import java.util.TimerTask;

import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.graphics.Color;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {

    private Timer timer;
	private TimerTask task;
	private TextView tv;
	private int i;
	private boolean change;
	private Handler handler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			if(change){
				change = false;
				tv.setTextColor(Color.BLUE);
			}else{
				change = true;
				tv.setTextColor(Color.TRANSPARENT);
			}
			
		};
	};
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
    }


    public void start(View v){
    	i = i+1;
    	if(timer!=null && task!=null){
    		timer.cancel();
    		task.cancel();
    	}
    	
    	if(timer==null){
    		Log.e("TAG", "Timer为空");
    	}
    	timer = new Timer();
    	task = new TimerTask() {
			
			@Override
			public void run() {
				
				Log.e("TAG", "我是定时器"+i);
				handler.sendEmptyMessage(1);
				
			}
		};
    	
		timer.schedule(task, 1, 300);
    }
    public void stop(View v){
    	if(timer!=null && task!=null){
    		timer.cancel();
    		task.cancel();
    	}
    }
}

好了,以上就是实现字体闪烁的全部代码,简单吧?就是开了个定时器定时发送消息,让handle去处理字体的颜色变化,我们需要注意的是

要是定时器存在多次启动的现象,一定要在开启定时器之前先关闭之前的定时器。



ok,接下来我们再看看怎么实现字体跑马灯吧,其实这个是老技术了,但我做完字体闪烁后,在此基础上又把跑马灯加在了上面,发现效果还是不错的。

总的来说,实现字体跑马灯我搜集到了两种方法,一种是可控的,一种是不可控的,不可控的我们用的较多,先看看不可控的吧,所谓可控制就是控制

文字滚动速度、样式、字体等属性。


TextView实现文字滚动需要以下几个要点:
1.文字长度长于可显示范围:android:singleLine="true"
2.设置可滚到,或显示样式:android:ellipsize="marquee"

3.TextView只有在获取焦点后才会滚动显示隐藏文字,因此需要在包中新建一个类,继承TextView。重写isFocused方法,这个方法默认行为是,

如果TextView获得焦点,方法返回true,失去焦点则返回false。跑马灯效果估计也是用这个方法判断是否获得焦点,所以把它的返回值始终设置为true。

package com.example.timer;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;

public class AbTextView extends TextView{

	public AbTextView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	public AbTextView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}

	public AbTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public boolean isFocused() {
		// TODO Auto-generated method stub
		return true;
	}

}

在布局XML中加入自定义的控件

 <com.example.timer.AbTextView
        android:id="@+id/tv"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:ellipsize="marquee"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:marqueeRepeatLimit="marquee_forever"
        android:scrollHorizontally="true"
        android:singleLine="true"
        android:textColor="#008001" />

ellipsize属性
设置当文字过长时,该控件该如何显示。有如下值设置:”start”—–省略号显示在开头;”end”——省略号显示在结尾;”middle”—-省略号显示在中间;”marquee” ——以跑马灯的方式显示(动画横向移动)

marqueeRepeatLimit属性
在ellipsize指定marquee的情况下,设置重复滚动的次数,当设置为marquee_forever时表示无限次。

focusable属性
自己猜测的,应该是能否获得焦点,同样focusableInTouchMode应该是滑动时能否获得焦点。


第二种实现方法,可以控制

控件类:AutoScrollTextView 继承了TextView并做了一些修改,实现了宽度的判断,文本自动滚动及开始和停止滚动等功能

package com.example.timer;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.TextView;

public class AutoScrollTextView extends TextView implements OnClickListener {

	public final static String TAG = AutoScrollTextView.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 = "";// 文本内容

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

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

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

	private void initView() {
		setOnClickListener(this);
	}

	public void init(WindowManager windowManager) {
		paint = getPaint();
		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();
	}

	@Override
	public Parcelable onSaveInstanceState() {
		Parcelable superState = super.onSaveInstanceState();
		SavedState ss = new SavedState(superState);

		ss.step = step;
		ss.isStarting = isStarting;

		return ss;

	}

	@Override
	public void onRestoreInstanceState(Parcelable state) {
		if (!(state instanceof SavedState)) {
			super.onRestoreInstanceState(state);
			return;
		}
		SavedState ss = (SavedState) state;
		super.onRestoreInstanceState(ss.getSuperState());

		step = ss.step;
		isStarting = ss.isStarting;
	}

	public static class SavedState extends BaseSavedState {
		public boolean isStarting = false;
		public float step = 0.0f;

		SavedState(Parcelable superState) {
			super(superState);
		}

		@Override
		public void writeToParcel(Parcel out, int flags) {
			super.writeToParcel(out, flags);
			out.writeBooleanArray(new boolean[] { isStarting });
			out.writeFloat(step);
		}

		public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {

			public SavedState[] newArray(int size) {
				return new SavedState[size];
			}

			@Override
			public SavedState createFromParcel(Parcel in) {
				return new SavedState(in);
			}
		};

		private SavedState(Parcel in) {
			super(in);
			boolean[] b = null;
			in.readBooleanArray(b);
			if (b != null && b.length > 0)
				isStarting = b[0];
			step = in.readFloat();
		}
	}

	public void startScroll() {
		isStarting = true;
		invalidate();
	}

	public void stopScroll() {
		isStarting = false;
		invalidate();
	}

	@Override
	public void onDraw(Canvas canvas) {
		canvas.drawText(text, temp_view_plus_text_length - step, y, paint);
		if (!isStarting) {
			return;
		}
		step += 0.5;// 0.5为文字滚动速度。
		if (step > temp_view_plus_two_text_length)
			step = textLength;
		invalidate();
	}

	@Override
	public void onClick(View v) {
		if (isStarting)
			stopScroll();
		else
			startScroll();

	}

}

在布局XML中的使用

<com.example.timer.AutoScrollTextView
        android:id="@+id/tv2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#EEE"
        android:inputType="text"
        android:text="哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈"
        android:textColor="#000"
        android:textSize="20sp" />

Activity中使用的方法

  tv2 = (AutoScrollTextView) findViewById(R.id.tv2);
        tv2.init(getWindowManager());
        tv2.startScroll();

注:如果想改变跑马灯的文字内容或者文字效果,则在调用完setText方法之后,需要再调用一下init方法,重新进行初始化和相关参数的计算。

在这里有个小问题,在使用自定义的控件时,不要再用TextView,而是使用继承TextView的那个类


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值