有時候在xml中寫的跑馬燈效果不滾動:緣由有如下android
總結一下跑馬燈的實現效果,網上比較流行的有兩種,測試過了均可以實現文字滾動效果,建議使用第一種,由於能夠更好地控制文字滾動速度、樣式、字體等屬性,第二種方法,尚未找到控制的方法!canvas
第一種:ide
控件類:AutoScrollTextView 繼承了TextView並作了一些修改,實現了寬度的判斷,文本自動滾動及開始和中止滾動等功能。佈局
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.WindowManager;
import android.view.View.OnClickListener;
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();
}ui
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;this
}
public static class SavedState extends BaseSavedState {
public boolean isStarting = false;
public float step = 0.0f;
SavedState(Parcelable superState) {
super(superState);
}spa
@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中使用方法:
<cn.tigertian.ui.AutoScrollTextView
android:id="@+id/TextViewNotice"
android:layout_height="30px"
android:layout_width="fill_parent"
android:text="@string/test_notice_1"
android:textColor="#000"
android:inputType="text"
android:background="#EEE"
android:textSize="20px">
</cn.tigertian.ui.AutoScrollTextView>
Activity中使用方法:
//啓動公告滾動條
autoScrollTextView = (AutoScrollTextView)findViewById(R.id.TextViewNotice);
autoScrollTextView.init(getWindowManager());
autoScrollTextView.startScroll();
注:若是想改變跑馬燈的文字內容或者文字效果,則在調用完setText方法以後,須要再調用一下init方法,從新進行初始化和相關參數的計算。
第二種:
publicclassAlwaysMarqueeTextViewextendsTextView{
publicAlwaysMarqueeTextView(Contextcontext){
super(context);
}
publicAlwaysMarqueeTextView(Contextcontext,AttributeSetattrs){
super(context,attrs);
}
publicAlwaysMarqueeTextView(Contextcontext,AttributeSetattrs,intdefStyle){
super(context,attrs,defStyle);
}
@Override
publicbooleanisFocused(){
returntrue;
}
在佈局XML文件中加入這麼一個AlwaysMarqueeTextView,這個加入方法也是剛剛學的。
ellipsize屬性
設置當文字過長時,該控件該如何顯示。有以下值設置:」start」—–省略號顯示在開頭;」end」——省略號顯示在結尾;」middle」—-省略號顯示在中間;」marquee」 ——以跑馬燈的方式顯示(動畫橫向移動)
marqueeRepeatLimit屬性
在ellipsize指定marquee的狀況下,設置重複滾動的次數,當設置爲marquee_forever時表示無限次。
focusable屬性
本身猜想的,應該是可否得到焦點,一樣focusableInTouchMode應該是滑動時可否得到焦點。
組合View的問題:
上面示例中2個TextView組合爲一個View,因爲設置了LinearLayout爲focusable而TextView就無法取得焦點了,這樣 這個TextView的跑馬燈效果就顯示不出來,就算你也設置TextView的android:focusable=
"true"
也是 沒用的. 這個時候就要使用addStatesFromChildren 這個屬性了,在LinearLayout中設置這個屬性,而後設置TextView的focusable=
"true"
就能夠了.關於 addStatesFromChildren的說明:
Sets whether
this
ViewGroup's drawable states
also include its children's drawable states.