就是大家叫的跑马灯效果。对4.0以上,简单地在TextView里面加上4句就可以了:
android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:singleLine="true"
但是如果这个TextView属于ListView的子View,并且list item设置了android:descendantFocusability="blocksDescendants"等比较复杂的情况时,上述方法不行。必须在自定义View上drawText,在http://gundumw100.iteye.com/blog/965366的基础上,整理了些干货:
FloatableTextView.java:
package com.example.floatabletextview; import android.content.Context; import android.graphics.Canvas; import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; /** * 单行TextView,容纳不下就左移 */ public class FloatableTextView extends TextView implements OnClickListener { public boolean mIsFloating = false; //是否开始滚动 private float mSpeed = 0.5f; private float mStep = 0f; private String mStr = ""; //文本内容 private float mTextLength = 0f; //文本长度 private float mViewWidth = 0f; private float mY = 0f; //文字的纵坐标 public FloatableTextView(Context context) { super(context); initView(); } public FloatableTextView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } public FloatableTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(); } private void initView() { setOnClickListener(this); } public void init(String str, float speed, float width) { setText(str); mSpeed = speed; mStr = getText().toString(); mTextLength = getPaint().measureText(mStr); mViewWidth = width; mStep = mTextLength + mViewWidth; mY = getTextSize() + getPaddingTop(); getPaint().setColor(0xff0000ff); } @Override public void onClick(View v) { if (mIsFloating) stopFloating(); else startFloating(); } @Override public void onDraw(Canvas canvas) { canvas.drawText(mStr, 0, mStr.length(), mViewWidth + mTextLength - mStep, mY, getPaint()); if (!mIsFloating) return; mStep += mSpeed; if (mStep > mViewWidth + mTextLength * 2) mStep = mTextLength; invalidate(); } @Override public void onRestoreInstanceState(Parcelable state) { if (!(state instanceof SavedState)) { super.onRestoreInstanceState(state); return; } SavedState savedState = (SavedState) state; super.onRestoreInstanceState(savedState.getSuperState()); mStep = savedState.mStep; mIsFloating = savedState.mIsFloating; } @Override public Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState savedState = new SavedState(superState); savedState.mStep = mStep; savedState.mIsFloating = mIsFloating; return savedState; } public void setSpeed(float speed) { mSpeed = speed; } public void startFloating() { mIsFloating = mTextLength > mViewWidth; // mIsFloating = true; invalidate(); } public void stopFloating() { mIsFloating = false; invalidate(); } public static class SavedState extends BaseSavedState { public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { @Override public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; public boolean mIsFloating = false; public float mStep = 0.0f; private SavedState(Parcel in) { super(in); boolean[] b = new boolean[1]; in.readBooleanArray(b); mIsFloating = b[0]; mStep = in.readFloat(); } SavedState(Parcelable superState) { super(superState); } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeBooleanArray(new boolean[] { mIsFloating }); out.writeFloat(mStep); } } }
package com.example.floatabletextview; import android.app.ListActivity; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import com.example.zlistmarquee.R; public class MainActivity extends ListActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setListAdapter(new MyAdapter()); } class MyAdapter extends BaseAdapter { @Override public int getCount() { return 9; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = getLayoutInflater().inflate(R.layout.list_item, null); FloatableTextView floatableTextView = (FloatableTextView) v.findViewById(R.id.floatable_text_view); floatableTextView.init("速度 岁的 电话 离开 的灯光 撒旦斯蒂芬 无污染", 0.9f, 100); floatableTextView.startFloating(); return v; } } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="30dp" android:orientation="horizontal" > <LinearLayout android:layout_width="90dp" android:layout_height="fill_parent" android:background="@android:color/holo_green_dark" > </LinearLayout> <com.example.floatabletextview.FloatableTextView android:id="@+id/floatable_text_view" android:layout_width="80dp" android:layout_height="30dp" android:background="@android:color/holo_blue_bright" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@android:color/holo_green_light" > </LinearLayout> </LinearLayout>
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@android:id/list" android:layout_width="fill_parent" android:layout_height="wrap_content" > </ListView> </LinearLayout>