Android开发:TextView真正可控、不需要焦点的水平滚动--这才是真正的跑马灯
网上的TextView做跑马灯,大多都是要用到焦点,而且字数要超出滚动区域宽度才能实现滚动,使用起来十分不方便。
这里实现一种真正可控的滚动
(1)不需要焦点
(2)任意字数
(3)滚动从滚动区域右边出来,在左边消失,再从右边出来。
上代码
1、布局文件
<RelativeLayout 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" tools:context="${relativePackage}.${activityClass}" > <Button android:id="@+id/btn1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="改变滚动内容1"/> <Button android:id="@+id/btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/btn1" android:text="改变滚动内容2"/> <Button android:id="@+id/btn3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/btn2" android:text="退出程序"/> <com.using.margindemo.MarqueeTextView android:id="@+id/tvScroll" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="40dp" > </com.using.margindemo.MarqueeTextView> </RelativeLayout>
2、滚动控件
package com.using.margindemo; import android.content.Context; import android.graphics.Canvas; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.widget.TextView; public class MarqueeTextView extends TextView { /** 是否停止滚动 */ private boolean mStopMarquee; private String mText;//文本内容 private float mCoordinateX = 1280;//当前滚动位置 private float mTextWidth;//文本宽度 private int mScrollWidth = 1280;//滚动区域宽度 private int speed = 1;//滚动速度 public float getCurrentPosition() { return mCoordinateX; } public void setCurrentPosition(float mCoordinateX) { this.mCoordinateX = mCoordinateX; } public int getScrollWidth() { return mScrollWidth; } public void setScrollWidth(int mScrollWidth) { this.mScrollWidth = mScrollWidth; } public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } public MarqueeTextView(Context context, AttributeSet attrs) { super(context, attrs); } public void setText(String text) { this.mText = text; mTextWidth = getPaint().measureText(mText); //mTextWidth = 1280; if (mHandler.hasMessages(0)) mHandler.removeMessages(0); mHandler.sendEmptyMessageDelayed(0, 10); } @Override protected void onAttachedToWindow() { mStopMarquee = false; if (!isEmpty(mText)) mHandler.sendEmptyMessageDelayed(0, 2000); super.onAttachedToWindow(); } public static boolean isEmpty(String str) { return str == null || str.length() == 0; } @Override protected void onDetachedFromWindow() { mStopMarquee = true; if (mHandler.hasMessages(0)) mHandler.removeMessages(0); super.onDetachedFromWindow(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (!isEmpty(mText)) canvas.drawText(mText, mCoordinateX, 150, getPaint()); } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 0: if (mCoordinateX < (-mTextWidth)) {//文字滚动完了,从滚动区域的右边出来 mCoordinateX = mScrollWidth; invalidate(); if (!mStopMarquee) { sendEmptyMessageDelayed(0, 500); } } else { mCoordinateX -= speed; invalidate(); if (!mStopMarquee) { sendEmptyMessageDelayed(0, 30); } } break; } super.handleMessage(msg); } }; }
3、
package com.using.margindemo; import android.app.ActionBar; import android.app.Activity; import android.content.res.Configuration; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup.MarginLayoutParams; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.ImageView; import android.widget.RelativeLayout; public class MainActivity extends Activity { private ImageView image; private MarqueeTextView marqueeTextView; private Button button1; private Button button2; private Button button3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_NO_TITLE);//隐藏标题栏 setContentView(R.layout.activity_main); marqueeTextView = (MarqueeTextView)findViewById(R.id.tvScroll); MarginLayoutParams margin1 = new MarginLayoutParams( marqueeTextView.getLayoutParams()); margin1.setMargins(100, 200, 0, 0);//设置滚动区域位置:在左边距400像素,顶边距10像素的位置 RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(margin1); layoutParams1.height = 240;//设滚动区域高度 layoutParams1.width = 1000; //设置滚动区域宽度 marqueeTextView.setLayoutParams(layoutParams1); marqueeTextView.setScrollWidth(1000); marqueeTextView.setCurrentPosition(100 + 1000);//设置滚动信息从滚动区域的右边出来 marqueeTextView.setSpeed(2); marqueeTextView.setText("这才是真正的跑马灯效果!"); button1 = (Button)findViewById(R.id.btn1); button2 = (Button)findViewById(R.id.btn2); button3 = (Button)findViewById(R.id.btn3); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { marqueeTextView.setText("这才是真正的跑马灯效果!"); } }); button2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { marqueeTextView.setText("温馨提示:挂号或缴费后,请到休息区等候,我们会尽快为您服务,请留意屏幕叫号信息,谢谢!"); } }); button3.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { finish(); } }); } }