Android自定义TextView实现文字自动滚动

编程入门 行业动态 更新时间:2024-10-05 03:21:04

Android<a href=https://www.elefans.com/category/jswz/34/1771438.html style=自定义TextView实现文字自动滚动"/>

Android自定义TextView实现文字自动滚动

效果:循环滚动,类似广告条



思路:

开启定时器刷新绘制文本的位置即可达到效果。

步骤1:新建ScrollTextView类继承自TextView。代码如下:

public class ScrollTextView extends TextView {private static final String TAG = "ScrollTextView";private String mText = "蒹葭苍苍,白露为霜。所谓伊人,在水一方。";private int mOffsetX = 0;private Rect mRect;private Timer mTimer;private TimerTask mTimerTask;/*** 速度,负数左移,正数右移。*/private int mSpeed = -10;private static final int PFS = 24;public ScrollTextView(Context context) {this(context, null);}public ScrollTextView(Context context, AttributeSet attrs) {super(context, attrs);mRect = new Rect();mTimer = new Timer();mTimerTask = new MyTimerTask();mTimer.schedule(mTimerTask, 0, 1000 / 24);}private class MyTimerTask extends TimerTask {@Overridepublic void run() {//如果View能容下所有文字,直接返回if (mRect.right < getWidth()){return;}if (mOffsetX < - mRect.right - getPaddingEnd()){//左移时的情况mOffsetX = getPaddingStart();} else if (mOffsetX > getPaddingStart()){//右移时的情况mOffsetX = - mRect.right;}mOffsetX += mSpeed;postInvalidate();}}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//获取文本区域大小,保存在mRect中。getPaint().getTextBounds(mText, 0, mText.length(), mRect);if (mRect.right < getWidth()){canvas.drawText(mText, 0, getHeight() / 2, getPaint());}else {canvas.drawText(mText, mOffsetX, getHeight() / 2, getPaint());}}/*** 视图移除时销毁任务和定时器*/@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();Log.e(TAG, "killTimer");if (mTimerTask != null){mTimerTask.cancel();mTimerTask = null;}if (mTimer != null){mTimer.cancel();mTimer = null;}}
}

完成上面代码可以的到如下效果:

以上是硬编码文字,如果尝试在XML布局或代码设置文字,将会显示的一塌糊涂:

    <com.fanhongfei.scrolltext.ScrollTextViewandroid:id="@+id/scrollTextView"android:layout_width="150dp"android:layout_height="60dp"android:background="#EE4000"android:text="开关磁阻电机的优缺点及使用"android:textColor="#FFFF" />
    @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ScrollTextView textView = findViewById(R.id.scrollTextView);textView.setText("开关磁阻电机的优缺点及使用");}


步骤2:需要对onDraw()做一些更改,如下:

    @Overrideprotected void onDraw(Canvas canvas) {//此处去掉了super.onDraw(Canvas canvas);mText = getText().toString();TextPaint textPaint = getPaint();textPaint.setColor(getCurrentTextColor());//获取文本区域大小,保存在mRect中。textPaint.getTextBounds(mText, 0, mText.length(), mRect);if (mRect.right < getWidth()){canvas.drawText(mText, 0, getHeight() / 2, textPaint);}else {canvas.drawText(mText, mOffsetX, getHeight() / 2, textPaint);}}

一切都很正常,把字体调大再看看,发现并没有居中显示,而是稍稍偏上。


问题就在于:

canvas.drawText(mText, mOffsetX, getHeight() / 2, textPaint);

第三个参数,垂直方向的中点和文字的基准点并不重合。


图片引用自 android canvas drawText()文字居中   感谢原作,侵权立删。

需做如下计算: 

        float mTextCenterVerticalToBaseLine =( - textPaint.ascent() + textPaint.descent()) / 2 - textPaint.descent();

这样就能文字居中了:

canvas.drawText(mText, mOffsetX, getHeight() / 2 + mTextCenterVerticalToBaseLine, textPaint);

别忘了在布局XML中设置单行显示,因为没有重写测量方法,布局使用wrap_content时得到的并不是我们想要的尺寸。

 android:maxLines="1"

到此就完成了。

最后附上完整代码:

自定义的ScrollTextView类:

public class ScrollTextView extends TextView {private static final String TAG = "ScrollTextView";private String mText = "蒹葭苍苍,白露为霜。所谓伊人,在水一方。";private int mOffsetX = 0;private Rect mRect;private Timer mTimer;private TimerTask mTimerTask;/*** 速度,负数左移,正数右移。*/private int mSpeed = -10;private static final int PFS = 24;public ScrollTextView(Context context) {this(context, null);}public ScrollTextView(Context context, AttributeSet attrs) {super(context, attrs);mRect = new Rect();mTimer = new Timer();mTimerTask = new MyTimerTask();//更新帧率24mTimer.schedule(mTimerTask, 0, 1000 / PFS);}private class MyTimerTask extends TimerTask {@Overridepublic void run() {//如果View能容下所有文字,直接返回if (mRect.right < getWidth()){return;}if (mOffsetX < - mRect.right - getPaddingEnd()){//左移时的情况mOffsetX = getPaddingStart();} else if (mOffsetX > getPaddingStart()){//右移时的情况mOffsetX = - mRect.right;}mOffsetX += mSpeed;postInvalidate();}}@Overrideprotected void onDraw(Canvas canvas) {//此处去掉了super.onDraw(Canvas canvas);mText = getText().toString();TextPaint textPaint = getPaint();textPaint.setColor(getCurrentTextColor());//获取文本区域大小,保存在mRect中。textPaint.getTextBounds(mText, 0, mText.length(), mRect);float mTextCenterVerticalToBaseLine =( - textPaint.ascent() + textPaint.descent()) / 2 - textPaint.descent();if (mRect.right < getWidth()){canvas.drawText(mText, 0, getHeight() / 2 + mTextCenterVerticalToBaseLine, textPaint);}else {canvas.drawText(mText, mOffsetX, getHeight() / 2 + mTextCenterVerticalToBaseLine, textPaint);}}/*** 视图移除时销毁任务和定时器*/@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();Log.e(TAG, "killTimer");if (mTimerTask != null){mTimerTask.cancel();mTimerTask = null;}if (mTimer != null){mTimer.cancel();mTimer = null;}}public void setSpeed(int speed){this.mSpeed = speed;}
}

MainActivity:

public class MainActivity extends Activity {String text1 = "桑之未落,其叶沃若。于嗟鸠兮,无食桑葚;\n" +"于嗟女兮,无与士耽。士之耽兮,犹可说也;\n" +"女之耽兮,不可说也。";String text2 = "桑之落矣,其黄而陨。自我徂尔,三岁食贫。\n" +"淇水汤汤,渐车帷裳。女也不爽,士贰其行。\n" +"士也罔极,二三其德。";String text3 = "三岁为妇,靡室劳矣;夙兴夜寐,靡有朝矣。\n" +"言既遂矣,至于暴矣。兄弟不知,咥其笑矣。\n" +"静言思之,躬自悼矣。";String text4 = "及尔偕老,老使我怨。淇则有岸,隰则有泮。\n" +"总角之宴,言笑晏晏。信誓旦旦,不思其反。\n" +"反是不思,亦已焉哉!";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ScrollTextView textView1 = findViewById(R.id.scrollTextView1);textView1.setText(text1);textView1.setSpeed(-5);ScrollTextView textView2 = findViewById(R.id.scrollTextView2);textView2.setText(text2);textView2.setSpeed(10);ScrollTextView textView3 = findViewById(R.id.scrollTextView3);textView3.setText(text3);textView3.setSpeed(-15);ScrollTextView textView4 = findViewById(R.id.scrollTextView4);textView4.setText(text4);textView4.setSpeed(20);}
}

布局文件activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=""xmlns:tools=""android:layout_width="match_parent"android:layout_height="match_parent"android:layout_margin="16dp"android:gravity="center"android:orientation="vertical"tools:context="com.fanhongfei.scrolltext.MainActivity"><com.fanhongfei.scrolltext.ScrollTextViewandroid:id="@+id/scrollTextView1"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#EE4000"android:maxLines="1"android:textColor="#FFFF"android:textSize="14sp" /><com.fanhongfei.scrolltext.ScrollTextViewandroid:id="@+id/scrollTextView2"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:background="#EE4000"android:maxLines="1"android:textColor="#DAA520"android:textSize="24sp" /><com.fanhongfei.scrolltext.ScrollTextViewandroid:id="@+id/scrollTextView3"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:background="#EE4000"android:maxLines="1"android:textColor="#FFFF"android:textSize="28sp" /><com.fanhongfei.scrolltext.ScrollTextViewandroid:id="@+id/scrollTextView4"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:background="#EE4000"android:maxLines="1"android:textColor="#CDCD00"android:textSize="32sp" /></LinearLayout>

工程文件:


更多推荐

Android自定义TextView实现文字自动滚动

本文发布于:2024-03-08 23:05:53,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1722758.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:自定义   文字   Android   TextView

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!