Android 自定義View之TextView跑馬燈效果
阿新 • • 發佈:2019-01-06
public class MarqueeView extends SurfaceView implements SurfaceHolder.Callback{
public Context mContext;
private float mTextSize = 100; //字型大小
private int mTextColor = Color.RED; //字型的顏色
private int mBackgroundColor=Color.WHITE;//背景色
private boolean mIsRepeat;//是否重複滾動
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=5;//每一步滾動的距離
public MarqueeView(Context context) {
this(context,null);
}
public MarqueeView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MarqueeView(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);
mBackgroundColor=a.getColor(R.styleable.MarqueeView_marqueebackground,Color.BLACK);
mIsRepeat=a.getBoolean(R.styleable.MarqueeView_isRepeat,false);
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();
mTextPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextAlign(Paint.Align.LEFT);
}
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.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 <=-textWidth){
if(!mIsRepeat){//如果是不重複滾動
mHandler.sendEmptyMessage(ROLL_OVER);
}
currentX=contentWidth;
}else{
currentX-=sepX;
}
}else {// 向右滾動
if(currentX>=contentWidth){
if(!mIsRepeat){//如果是不重複滾動
mHandler.sendEmptyMessage(ROLL_OVER);
}
currentX=-textWidth;
}else{
currentX+=sepX;
}
}
if(canvas!=null)
canvas.drawColor(mBackgroundColor);
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;
Handler mHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case ROLL_OVER:
stopScroll();
if(mOnMargueeListener!=null){
mOnMargueeListener.onRollOver();
}
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;
}
}