国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

android自定義View實現跑馬燈效果

2019-10-22 18:12:26
字體:
來源:轉載
供稿:網友

android自帶的TextView可以實現跑馬燈效果,但是有很多的局限性;比如需要設置ellipsize=”marquee”,獲取 focusable=”true”,設置singleLine=”true”,控件里的內容需要超過控件本身的長度,無法控制滾動速度和滾動暫停和繼續滾動功能,各種限制導致用起來特別不順手,幾乎無法使用到生產環境中,在此背景下,需要自定義View實現跑馬燈效果。

使用主要方法:自定義View重寫onDraw方法,通過canvas.drawText()方法來顯示文字,利用Handler不斷地繪制文字,并控制文字開始繪制的X軸的位置,來實現連續滾動的效果。

實現步驟:

1、自定義view的class:

import android.annotation.SuppressLint;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Paint.FontMetrics;import android.graphics.Rect;import android.os.Handler;import android.util.AttributeSet;import android.util.TypedValue;import android.view.View;public class MarqueenView extends View { /*  * 1、自定義View的屬性 2、在View的構造方法中獲得我們自定義的屬性 [ 3、重寫onMesure ] 4、重寫onDraw  */ /*  * 文本  */ private String mTitleText; /**  * 文本的顏色  */ private int mTitleTextColor; /**  * 文本的大小  */ private int mTitleTextSize; /**  * 繪制時控制文本繪制的范圍  */ private Rect mBound, usualBound; // 畫筆 private Paint mPaint; private int spead = 15; private int length = 3; private int currentLength; @SuppressLint("HandlerLeak") private Handler handler = new Handler() {  @Override  public void handleMessage(android.os.Message msg) {   if (mBound.width() <= getWidth()) {    if (currentLength >= 120 + (getWidth() / length) * length) {     currentLength = length;    } else {     currentLength = currentLength + length;    }   } else {    if (currentLength >= (mBound.width() + 120)) {     currentLength = length;    } else {     currentLength = currentLength + length;    }   }   invalidate();   handler.sendEmptyMessageDelayed(0, spead);  }; }; public MarqueenView(Context context, AttributeSet attrs) {  this(context, attrs, 0);  currentLength = length; } public MarqueenView(Context context) {  this(context, null); } public MarqueenView(Context context, AttributeSet attrs, int defStyle) {  super(context, attrs, defStyle);  TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0);  int n = a.getIndexCount();  for (int i = 0; i < n; i++) {   int attr = a.getIndex(i);   switch (attr) {   case R.styleable.CustomTitleView_titleText:    mTitleText = a.getString(attr);    break;   case R.styleable.CustomTitleView_titleTextColor:    mTitleTextColor = a.getColor(attr, Color.BLACK);    break;   case R.styleable.CustomTitleView_titleTextSize:    mTitleTextSize = a.getDimensionPixelSize(attr,      (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));    break;   }  }  a.recycle();  mPaint = new Paint();  mPaint.setTextSize(mTitleTextSize);  mBound = new Rect();  usualBound = new Rect();  mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);  mPaint.getTextBounds("1234567890QqYy你好", 0, 16, usualBound); } /*  * EXACTLY:一般是設置了明確的值或者是MATCH_PARENT AT_MOST:表示子布局限制在一個最大值內,一般為WARP_CONTENT  * UNSPECIFIED:表示子布局想要多大就多大,很少使用  */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  int widthMode = MeasureSpec.getMode(widthMeasureSpec);  int widthSize = MeasureSpec.getSize(widthMeasureSpec);  int heightMode = MeasureSpec.getMode(heightMeasureSpec);  int heightSize = MeasureSpec.getSize(heightMeasureSpec);  int width;  int height;  if (widthMode == MeasureSpec.EXACTLY) {   width = widthSize;  } else {   mPaint.setTextSize(mTitleTextSize);   mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);   float textWidth = mBound.width();// 字體寬度   // 控件padding   int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());   width = desired;  }  if (heightMode == MeasureSpec.EXACTLY) {   height = heightSize;  } else {   mPaint.setTextSize(mTitleTextSize);   mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);   float textHeight = mBound.height();   int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom());   height = desired;  }  // setMeasuredDimension((width / length) * length, height);  setMeasuredDimension(width, height + usualBound.bottom); } @Override protected void onDraw(Canvas canvas) {  mPaint.setColor(mTitleTextColor);  if (mBound.width() <= getWidth()) {   if (currentLength < mBound.width()) {    canvas.drawText(mTitleText, getPaddingLeft() - currentLength, getHeight() - usualBound.bottom, mPaint);   }   if (currentLength >= 120) {    canvas.drawText(mTitleText, getWidth() - currentLength + 120, getHeight() - usualBound.bottom, mPaint);   }  } else {   if (currentLength < mBound.width()) {    canvas.drawText(mTitleText, getPaddingLeft() - currentLength, getHeight() - usualBound.bottom, mPaint);   }   if (currentLength >= mBound.width() - getWidth() + 120) {    canvas.drawText(mTitleText, 120 - currentLength + mBound.width(), getHeight() - usualBound.bottom, mPaint);   }  } } public static int getFontHeight(Integer textSize) {  Paint paint = new Paint();  if (textSize != null) {   paint.setTextSize(textSize);  }  FontMetrics fm = paint.getFontMetrics();  return (int) (fm.descent - fm.ascent); } public void startScroll() {  handler.removeMessages(0);  handler.sendEmptyMessage(0); } public void stopScroll() {  handler.removeMessages(0);  currentLength = 0;  invalidate(); } public void setScrollLength(int length) {  this.length = length;  currentLength = length; } public void setSpead(int spead) {  this.spead = spead; } public void setText(String msg) {  mTitleText = msg;  mBound = new Rect();  mPaint.getTextBounds(msg, 0, mTitleText.length(), mBound); }}

2、在values的attrs.xml文件中需要加入自定義的屬性,字體大小、顏色、和初始內容,這里有待改進

<?xml version="1.0" encoding="utf-8"?><resources> <attr name="titleText" format="string" /> <attr name="titleTextColor" format="color" /> <attr name="titleTextSize" format="dimension" /> <declare-styleable name="CustomTitleView">  <attr name="titleText" />  <attr name="titleTextColor" />  <attr name="titleTextSize" /> </declare-styleable></resources>

3、在layout的布局文件中引用此控件

<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res/***這里寫上自己的包名***" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.MarqueenView android:id="@+id/main_marquee_view" android:layout_width="fill_parent" android:layout_height="wrap_content" custom:titleText=" " custom:titleTextColor="#666666" custom:titleTextSize="14sp"/> </LinearLayout>

4、上面準備好后,就可以在activity中設置跑馬燈并開始滾動了

mv = (MarqueenView) findViewById(R.id.main_marquee_view);mv.stopScroll();mv.setText("滾動內容");// 設置顯示內容//mv.setSpead(15);//滾動頻率,默認15毫秒一次,數值太小會影響效率//mv.setScrollLength(3);//默認每次左移3px,數值太大會有停頓感,數值太小滾動會變慢mv.startScroll();//記得在Ondestroy中停止滾動,方便回收@Override protected void onDestroy() {  try {   mv.stopScroll();   mv = null;  } catch (Throwable e) {   e.printStackTrace();  }  super.onDestroy(); }

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 郯城县| 津市市| 谷城县| 安达市| 云梦县| 个旧市| 沾化县| 崇礼县| 定南县| 泽库县| 同德县| 八宿县| 关岭| 青海省| 临夏市| 敦煌市| 利川市| 阳泉市| 县级市| 防城港市| 海口市| 新营市| 桃源县| 高邑县| 黑山县| 南充市| 合作市| 金沙县| 武功县| 博客| 浙江省| 长顺县| 平舆县| 萍乡市| 梁山县| 石嘴山市| 宁河县| 休宁县| 宁蒗| 丰宁| 洱源县|