就是大家叫的跑马灯效果。对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);
}
}
}
MainActivity.java:
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;
}
}
}
list_item.xml:
<?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>