android textview实现走马灯效果
第一篇正好写一下正在弄的一个小软件上的这一块内容吧.
需求是在软件底部实现滚动文字广告的效果,当然肯定是在网上找了一下,找到了很多网页但是归结起来就是两种方法,我这里只写其中一种因为另外一种我也没实现出来。
一、首先把代码贴出来
1.新建一个TextView的扩展类,来实现自定义的滚动TextView控件效果,像下面这个AutoScrollAdsView.
1 import android.content.Context; 2 import android.graphics.Canvas; 3 import android.graphics.Paint; 4 import android.os.Bundle; 5 import android.os.Parcel; 6 import android.os.Parcelable; 7 import android.util.AttributeSet; 8 import android.util.DisplayMetrics; 9 import android.widget.TextView; 10 import android.view.View; 11 import android.view.View.OnClickListener; 12 import android.view.WindowManager; 13 14 public class AutoScrollAdsView extends TextView implements OnClickListener { 15 16 private static final float STEP = 2; 17 18 private float mTextLength = 0f; 19 private float mWidth = 0f; 20 private float mStep = 0f; 21 private float mY = 0f; 22 private float mMinMarqueeLength = 0.0f; 23 private float mMaxMarqueeLength = 0.0f; 24 public boolean mScroll = false; 25 private Paint mPaint = null; 26 private String mText = ""; 27 28 public AutoScrollAdsView(Context context) { 29 super(context); 30 // TODO Auto-generated constructor stub 31 setOnClickListener(this); 32 } 33 34 public AutoScrollAdsView(Context context, AttributeSet attrs, int defStyle) { 35 super(context, attrs, defStyle); 36 // TODO Auto-generated constructor stub 37 setOnClickListener(this); 38 } 39 40 public AutoScrollAdsView(Context context, AttributeSet attrs) { 41 super(context, attrs); 42 // TODO Auto-generated constructor stub 43 setOnClickListener(this); 44 } 45 46 @Override 47 public void onClick(View v) { 48 // TODO Auto-generated method stub 49 if(mScroll){ 50 stopScroll(); 51 }else{ 52 startScroll(); 53 } 54 } 55 56 @Override 57 public void onRestoreInstanceState(Parcelable state) { 58 // TODO Auto-generated method stub 59 super.onRestoreInstanceState(state); 60 } 61 62 @Override 63 public Parcelable onSaveInstanceState() { 64 // TODO Auto-generated method stub 65 return super.onSaveInstanceState(); 66 } 67 68 public void initView(WindowManager windowManager){ 69 mPaint = getPaint(); 70 mText = getText().toString(); 71 mTextLength = mPaint.measureText(mText); 72 mWidth = getWidth(); 73 74 if(mWidth == 0){ 75 if(windowManager != null){ 76 DisplayMetrics dm = new DisplayMetrics(); 77 windowManager.getDefaultDisplay().getMetrics(dm); 78 mWidth = dm.widthPixels; 79 } 80 } 81 82 mStep = mTextLength; 83 mMinMarqueeLength = mWidth + mTextLength; 84 mMaxMarqueeLength = mWidth + mTextLength * 2; 85 mY = getTextSize() + getPaddingTop(); 86 } 87 88 public static class SavedState extends BaseSavedState{ 89 90 public boolean scroll = false; 91 public float step = 0f; 92 93 public SavedState(Parcel arg0) { 94 super(arg0); 95 // TODO Auto-generated constructor stub 96 Bundle bundle = new Bundle(); 97 bundle = arg0.readBundle(); 98 scroll = bundle.getBoolean("scroll"); 99 step = bundle.getFloat("step"); 100 } 101 102 public SavedState(Parcelable arg0) { 103 super(arg0); 104 // TODO Auto-generated constructor stub 105 } 106 107 @Override 108 public void writeToParcel(Parcel dest, int flags) { 109 // TODO Auto-generated method stub 110 super.writeToParcel(dest, flags); 111 Bundle bundle = new Bundle(); 112 bundle.putBoolean("scroll", scroll); 113 bundle.putFloat("step", step); 114 dest.writeBundle(bundle); 115 } 116 117 public static final Parcelable.Creator<SavedState> CREATOR = 118 new Parcelable.Creator<AutoScrollAdsView.SavedState>() { 119 120 @Override 121 public SavedState createFromParcel(Parcel source) { 122 // TODO Auto-generated method stub 123 return new SavedState(source); 124 } 125 126 @Override 127 public SavedState[] newArray(int size) { 128 // TODO Auto-generated method stub 129 return new SavedState[size]; 130 } 131 }; 132 } 133 134 @Override 135 protected void onDraw(Canvas canvas) { 136 // TODO Auto-generated method stub 137 canvas.drawText(mText, mMinMarqueeLength - mStep, mY, mPaint); 138 139 if(!mScroll){ 140 return ; 141 } 142 143 mStep += STEP; 144 if(mStep > mMaxMarqueeLength){ 145 mStep = mTextLength; 146 } 147 148 invalidate(); 149 } 150 151 public void startScroll(){ 152 mScroll = true; 153 invalidate(); 154 } 155 156 public void stopScroll(){ 157 mScroll = false; 158 invalidate(); 159 } 160 }
2.待会儿再来说一说这个类的原理,紧接着是在xml中使用这个类,其中只要引用名称和id/layout等必要元素设置好,其他的自定义的一些东西都看你自己随意了
1 <com.xxxx.tmms.AutoScrollAdsView 2 android:id="@+id/scroll_ads" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:textSize="25sp" 6 android:text="@string/scroll_tips"/>
3.在Activity中使用这个控件,其实也就三行代码
1 AutoScrollAdsView asav = (AutoScrollAdsView)findViewById(R.id.scroll_ads); 2 asav.initView(getWindowManager()); 3 asav.startScroll();
这个时候运行就可以看到走马灯效果了,当然在这个基础上可以添加更多的功能,实现更加灵活多样的效果,就不再赘述了。
二、原理(这里纯用文字描述会有点儿乱)
接下来说一下这个AutoScrollAdsView这个class的原理,其实代码很简单,多看两遍再自己写一写就可以看懂。这里主要给一些刚开始学习的朋友一些参考和写出来对我自己也是一个记录。
要理解这个原理,主要是要了解mMinMarqueeLength,mMaxMarqueeLength和mStep这三个变量的意义。
本来画个图很容易说明,但是我画不好,就直接用文字来尝试解释一下了。
让一个字符串从TextView的右端往左端滚动,想象一下这个画面,其实就是开始时候在控件最右端绘制(这里姑且用这个词吧)字符串首字符,然后字符串往左移动一定的步长(就是mStep来控制的偏移量),重新绘制,然后再往左移动一点儿,再重新绘制,一直到字符串的末尾字符位移到控件的最左端。这样不断的重绘过程,就会表现出字符滚动的效果。
其实仔细想一想mMinMarqueeLength和mMaxMarqueeLength的值也可以有其他设置方法,因为一开始这段代码也是参照网上写下来的,我就顺着这个意思解释了。
mMinMarqueeLength这里设置是viewWidth + textLength.
从canvas.drawText(mText, mMinMarqueeLength - mStep, mY, mPaint);这个函数可以看出来,重绘的实现其实就是在控件的x/y坐标位置来显示某一字符串,所以初始的x坐标位置就是mMinMarqueeLength - mStep,其实就等于TextView控件的最右端。
然后mStep不断的自增,当mStep = mMinMarqueeLength时候,这个时候x坐标为0,但是这个时候这是表示字符串首字符在x为0的位置显示,只有当mStep = mMinMarqueeLength + textLength(也就是mMaxMarqueeLength)的时候,才代表字符串的完全绘制在TextView以外,也就是完成一次从左到右的移动。
然后这句if语句实现的就是循环滚动了,当mStep达到mMaxMarqueeLength以后,重新还原,然后再从头绘制
if(mStep > mMaxMarqueeLength){ mStep = mTextLength; }
而重绘操作其实是由invalidate()这个函数来实现的,具体这个函数的意思,可以自己google一下或者参考android官方网站的解释
三、最后当然是要感谢原作者的分享和聪明才智,转载至这个链接

浙公网安备 33010602011771号