Android不间断跑马灯效果
来源:互联网 发布:免费留学中介 知乎 编辑:程序博客网 时间:2024/05/29 15:50
最近公司有个轮播中奖信息的需求,就是那种跑马灯的效果,产品要求跑马灯不能间断,不能等到一轮播完了再播下一轮。但是textview自带的跑马灯效果很不灵活,既不能改变速度,又是间断的。于是网上找了很多那种自定义的跑马灯的例子,但是很不幸的是,目前还没找到那种不间断的跑马灯,于是我寻思着,用自己的办法来实现跑马灯,最终还是弄出来了,虽然用起来不是很方便,但是功能是实现了。
主要思想:先自定义一个surfaceView,名为MarqueeTextView,用线程来实现跑马灯效果。然后再在layout文件里面加入两个一模一样的MarqueeTextView,这两个MarqueeTextView重叠在一起,先启动第一个MarqueeTextView,让他开始播,等它的最后一个字播出来的时候,再启动第二个一个MarqueeTextView。第一个MarqueeTextView播完以后就停止,等到第二个MarqueeTextView的最后一个字播出来的时候,再启动第一个MarqueeTextView,如此循环播放,相互启动,就形成了不间断的跑马灯效果。可能说得有点绕,直接上代码,注释写详细点。
自定义的MaqueeTextView:
import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.PixelFormat;import android.graphics.PorterDuff;import android.os.Handler;import android.os.Message;import android.text.TextPaint;import android.text.TextUtils;import android.util.AttributeSet;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.WindowManager;public class MarqueeTextView extends SurfaceView implements SurfaceHolder.Callback{ public Context mContext; private float mTextSize = 100; //字体大小 private int mTextColor = Color.RED; //字体的颜色 private int mStartPoint;// 开始滚动的位置 0是从最左面开始 1是从最末尾开始 private int mDirection;//滚动方向 0 向左滚动 1向右滚动 private int mSpeed;//滚动速度 private SurfaceHolder holder; private TextPaint mTextPaint; private MarqueeViewThread mThread; private String margueeString; private int textWidth=0,textHeight=0; private int ShadowColor=Color.BLACK; public int currentX=0;// 当前x的位置 public int sepX=2;//每一步滚动的距离 public static boolean isScroling1 = false;//1是否正在滚动 public static boolean isScroling2 = false;//2是否正在滚动 public MarqueeTextView(Context context) { this(context,null); } public MarqueeTextView(Context context, AttributeSet attrs) { this(context, attrs,0); } public MarqueeTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.mContext=context; init(attrs, defStyleAttr); } private void init(AttributeSet attrs, int defStyleAttr) { TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MarqueeView, defStyleAttr, 0); mTextColor = a.getColor(R.styleable.MarqueeView_textcolor, Color.RED); mTextSize = a.getDimension(R.styleable.MarqueeView_textSize, 48); mStartPoint=a.getInt(R.styleable.MarqueeView_startPoint,0); mDirection=a.getInt(R.styleable.MarqueeView_direction,0); mSpeed=a.getInt(R.styleable.MarqueeView_speed,20); a.recycle(); holder = this.getHolder(); holder.addCallback(this); mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); mTextPaint.setTextAlign(Paint.Align.LEFT); setZOrderOnTop(true);//使surfaceview放到最顶层 getHolder().setFormat(PixelFormat.TRANSLUCENT);//使窗口支持透明度 } public void setText(String msg){ if(!TextUtils.isEmpty(msg)){ measurementsText(msg); } } protected void measurementsText(String msg) { margueeString=msg; mTextPaint.setTextSize(mTextSize); mTextPaint.setColor(mTextColor); mTextPaint.density = getResources().getDisplayMetrics().density; // mTextPaint.setStrokeWidth(0.5f); // mTextPaint.setFakeBoldText(true); // 设定阴影(柔边, X 轴位移, Y 轴位移, 阴影颜色)// mTextPaint.setShadowLayer(5, 3, 3, ShadowColor); textWidth = (int)mTextPaint.measureText(margueeString); Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics(); textHeight = (int) fontMetrics.bottom; WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); int width = wm.getDefaultDisplay().getWidth(); if(mStartPoint==0) currentX=0; else currentX=width-getPaddingLeft()-getPaddingRight(); } @Override public void surfaceCreated(SurfaceHolder holder) { this.holder=holder; } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if(mThread!=null) mThread.isRun = true; } @Override public void surfaceDestroyed(SurfaceHolder holder) { if(mThread!=null) mThread.isRun = false; } /** * 开始滚动 */ public void startScroll(){ if(mThread!=null&&mThread.isRun) return; mThread = new MarqueeViewThread(holder);//创建一个绘图线程 mThread.start(); } /** * 停止滚动 */ public void stopScroll(){ if(mThread!=null){ mThread.isRun = false; mThread.interrupt(); } mThread=null; } /** * 线程 */ class MarqueeViewThread extends Thread{ private SurfaceHolder holder; public boolean isRun ;//是否在运行 public MarqueeViewThread(SurfaceHolder holder) { this.holder =holder; isRun = true; } public void onDraw() { try { synchronized (holder) { if (TextUtils.isEmpty(margueeString)) { Thread.sleep(1000);//睡眠时间为1秒 return; } Canvas canvas = holder.lockCanvas(); int paddingLeft = getPaddingLeft(); int paddingTop = getPaddingTop(); int paddingRight = getPaddingRight(); int paddingBottom = getPaddingBottom(); int contentWidth = getWidth() - paddingLeft - paddingRight; int contentHeight = getHeight() - paddingTop - paddingBottom; int centeYLine = paddingTop + contentHeight / 2;//中心线 if(mDirection==0) {//向左滚动 if(currentX<=contentWidth-textWidth){//这里是关键,当 //currentX<=contentWidth-textWidth时就启动另一个,这个靠接口来完成 //如果两轮之间间距还是有点大的话,可以在此处加或者减一个合适的距离,来调整间距大小 if(mOnMargueeListener!=null){ mOnMargueeListener.onRollOver(); } } if(currentX <=-textWidth){ mHandler.sendEmptyMessage(ROLL_OVER); currentX=contentWidth; }else{ currentX-=sepX; } }else {// 向右滚动 if(currentX>textWidth){ if(mOnMargueeListener!=null){ mOnMargueeListener.onRollOver(); } } if(currentX>=contentWidth){ mHandler.sendEmptyMessage(ROLL_OVER); currentX=-textWidth; }else{ currentX+=sepX; } } if(canvas!=null) canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//绘制透明色 canvas.drawText(margueeString,currentX, centeYLine+dip2px(getContext(),textHeight)/2,mTextPaint); holder.unlockCanvasAndPost(canvas);//结束锁定画图,并提交改变。 int a=textWidth/margueeString.trim().length(); int b=a/sepX; int c=mSpeed/b==0?1:mSpeed/b; Thread.sleep(c);//睡眠时间为移动的频率 } } catch (Exception e) { e.printStackTrace(); } } @Override public void run() { while (isRun) { onDraw(); } } } public static final int ROLL_OVER =100; public static final int START = 101; Handler mHandler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case ROLL_OVER: stopScroll(); break; } } }; /** * dip转换为px * @param context * @param dpValue * @return */ public static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } public void reset(){ int contentWidth = getWidth() - getPaddingLeft() - getPaddingRight(); if(mStartPoint==0) currentX=0; else currentX=contentWidth; } /** * 滚动回调 */ public interface OnMargueeListener{ void onRollOver();//滚动完毕 } OnMargueeListener mOnMargueeListener; public void setOnMargueeListener(OnMargueeListener mOnMargueeListener){ this.mOnMargueeListener=mOnMargueeListener; }}
资源文件:attrs.xml
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="MarqueeView"> <attr name="textcolor" format="color" /> <attr name="textSize" format="dimension" /> <attr name="isRepeat" format="boolean" /> <attr name="speed" format="integer"/> <attr name="startPoint" format="integer"> <enum name="start" value="0"/> <enum name="end" value="1"/> </attr> <attr name="direction" format="integer"> <enum name="left" value="0"/> <enum name="right" value="1"/> </attr> </declare-styleable></resources>layout文件cativity_main.xml:
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:background="#ffffff"> <com.test.testdemo.MarqueeTextView android:id="@+id/annoText1" app:textcolor="#ffffff" android:background="#000000" app:textSize="25sp" app:startPoint="end" app:direction="left" app:speed="30" android:layout_width="1425dp" android:layout_height="50dp" android:layout_marginTop="5dp" android:layout_gravity="center_vertical"/> <com.test.testdemo.MarqueeTextView android:id="@+id/annoText2" app:textcolor="#ffffff" android:background="#000000" app:textSize="25sp" android:layout_marginTop="5dp" app:startPoint="end" app:direction="left" app:speed="30" android:layout_width="1425dp" android:layout_height="50dp" android:layout_gravity="center_vertical"/></FrameLayout>
Activity中的调用:
import android.app.Activity;import android.os.Bundle;public class MainActivity extends Activity { private MarqueeTextView text1,text2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init(){ text1 = (MarqueeTextView)this.findViewById(R.id.annoText1); text2 = (MarqueeTextView)this.findViewById(R.id.annoText2); text1.setText("12345678hftghgqerrgmitewthenrtywrtfwert"); text2.setText("12345678hftghgqerrgmitewthenrtywrtfwert"); text1.startScroll();//先启动一个; text1.setOnMargueeListener(new MarqueeTextView.OnMargueeListener() { @Override public void onRollOver() { if(!MarqueeTextView.isScroling2) { MarqueeTextView.isScroling2 = true; text2.startScroll();//等接口被调用之后再启动另一个。 MarqueeTextView.isScroling1 = false; } } }); text2.setOnMargueeListener(new MarqueeTextView.OnMargueeListener() { @Override public void onRollOver() { if(!MarqueeTextView.isScroling1) { MarqueeTextView.isScroling1 = true; text1.startScroll(); MarqueeTextView.isScroling2 = false; } } }); } @Override protected void onPause() { text1.stopScroll(); text2.stopScroll(); super.onPause(); }}
所有的代码都在这里了,需要的可以自行复制粘贴,应该是可以直接运行的。也可以继续进行优化的。毕竟不是很简洁。
0 0
- Android不间断跑马灯效果
- 不间断跑马灯效果
- 不间断跑马灯
- 不间断可变跑马灯
- Android 跑马灯效果
- android跑马灯效果
- android跑马灯效果
- Android跑马灯效果
- Android 跑马灯效果
- android跑马灯效果
- android 跑马灯效果
- Android跑马灯效果
- android 跑马灯效果
- android 跑马灯效果
- Android跑马灯效果
- android 跑马灯效果
- Android 跑马灯效果
- Android跑马灯效果
- java session
- Android应用程序的Activity启动过程简要介绍和学习计划
- 精通 CSS+DIV 网页样式与布局 70
- Android - 自定义View Demo - LinearLayout
- 淘宝css reset
- Android不间断跑马灯效果
- 使用JAXP进行SAX解析(XMLReaderFactory、XMLReader 、SAXParserFactory与SAXParser)
- 使用JAXP进行SAX解析(XMLReaderFactory、XMLReader 、SAXParserFactory与SAXParser)
- 深入理解epoll
- Angularjs 学习笔记总结之二
- JAVA 读取文件及反编译
- 调整数组顺序使奇数位于偶数的前面
- win7的激活
- Java this关键字的用法