android自動跑馬燈,Android-最強跑馬燈

Android--最強跑馬燈

Android 跑馬燈已經有很多版本,從最基本的TextView,到重寫TextView使TextView取消焦點限制,還有重寫TextView利用ScrollTo方法寫的,基本都能滿足一般需要。然而在使用過程中,發現一些意外---有時會不播放,刷新線程還在繼續但就是不播放,最后在github上找到一個用動畫實現跑馬燈的項目(項目地址:https://github.com/ened/Android-MarqueeView,再次對作者表示感謝),改造了一番,總算ok了。以后再也不用為跑馬燈煩惱了。

特點:

1. 文字長短都有跑馬燈效果。

2. 可以控制速度

代碼:

package com.example.test_marquee;

import android.content.Context;

import android.graphics.Paint;

import android.text.Editable;

import android.text.TextWatcher;

import android.util.AttributeSet;

import android.util.Log;

import android.view.Gravity;

import android.view.View;

import android.view.ViewGroup;

import android.view.animation.Animation;

import android.view.animation.Interpolator;

import android.view.animation.LinearInterpolator;

import android.view.animation.TranslateAnimation;

import android.widget.LinearLayout;

import android.widget.ScrollView;

import android.widget.TextView;

/**

* LinearLayout作為父View,必須有一個子TextView

*

* 利用動畫實現

*/

public class MarqueeView extends LinearLayout {

private static final int TEXTVIEW_VIRTUAL_WIDTH = 2000;/* TextView默認寬度 */

private static final int DEFAULT_SPEED = 35;/* 默認滾動速度 越大滾動越慢 */

private static final int DEFAULT_ANIMATION_PAUSE = 0;/* 出去動畫與進入動畫的時間間隔 */

private static final String TAG = MarqueeView.class.getSimpleName();

private TextView mTextField;/* 該跑馬燈的孫子View之TextView */

private ScrollView mScrollView;/* 該跑馬燈的子View之mScrollView */

private Animation mMoveTextOut = null;/* 作用于TextView的動畫 --出去 */

private Animation mMoveTextIn = null;/* 作用于TextView的動畫 --進入 */

private Paint mPaint;

private int mSpeed = DEFAULT_SPEED;

private int mAnimationPause = DEFAULT_ANIMATION_PAUSE;

private Interpolator mInterpolator = new LinearInterpolator();

private Runnable mAnimationStartRunnable;

/** 字符串之間的間隔 */

private String interval = " ";

private String stringOfItem = "";

/** str+interval的長度 */

private float widthOfItem = 0;

private float widthOfTextView;

private String stringOfTextView = "";

private float startXOfOut = 0;

private float endXOfOut = 0;

private float startXOfIn = 0;

private float endXOfIn = 0;

public MarqueeView(Context context) {

super(context);

init(context);

}

public MarqueeView(Context context, AttributeSet attrs) {

super(context, attrs);

init(context);

}

public MarqueeView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

init(context);

}

private void init(Context context) {

// init helper

mPaint = new Paint();

mPaint.setAntiAlias(true);

mPaint.setStrokeWidth(1);

mPaint.setStrokeCap(Paint.Cap.ROUND);

mInterpolator = new LinearInterpolator();

}

// 當給子View分配位置和尺寸時調用。

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

super.onLayout(changed, l, t, r, b);

Logcat.d(TAG, "onLayout called!" + "changed: " + changed);

if (getChildCount() == 0 || getChildCount() > 1) {

throw new RuntimeException(

"MarqueeView must have exactly one child element.");

}

//

if (changed) {

View v = getChildAt(0);

if (!(v instanceof TextView)) {

throw new RuntimeException(

"The child view of this MarqueeView must be a TextView instance.");

}

initView(getContext());

mTextField.setText(mTextField.getText());

}

}

/** Starts the configured marquee effect. */

public void startMarquee() {

Logcat.d(TAG, "startMarquee called");

startTextFieldAnimation();

}

// 一旦開始動畫,動畫結束開始由監聽器負責。

private void startTextFieldAnimation() {

mAnimationStartRunnable = new Runnable() {

public void run() {

mTextField.startAnimation(mMoveTextOut);

}

};

postDelayed(mAnimationStartRunnable, mAnimationPause);

}

/**

* Disables the animations.

*/

public void reset() {

if (mAnimationStartRunnable == null)

return;

removeCallbacks(mAnimationStartRunnable);

mTextField.clearAnimation();

mMoveTextOut.reset();

mMoveTextIn.reset();

invalidate();

}

private void prepareAnimation() {

// Measure

mPaint.setTextSize(mTextField.getTextSize());

mPaint.setTypeface(mTextField.getTypeface());

float mTextWidth = mPaint.measureText(mTextField.getText().toString());

float width = getMeasuredWidth();

startXOfOut = -(mTextWidth - width) % widthOfItem;

endXOfOut = -mTextWidth + width;

startXOfIn = -(mTextWidth - width) % widthOfItem;

endXOfIn = -mTextWidth + width;

final int duration = ((int) Math.abs(startXOfOut - endXOfOut) * mSpeed);

if (BuildConfig.DEBUG) {

Log.d(TAG, "(int) Math.abs(startXOfOut - endXOfOut) : "

+ (int) Math.abs(startXOfOut - endXOfOut));

Log.d(TAG, "mSpeed : " + mSpeed);

Log.d(TAG, "startXOfOut : " + startXOfOut);

Log.d(TAG, "endXOfOut : " + endXOfOut);

Log.d(TAG, "startXOfIn : " + startXOfIn);

Log.d(TAG, "endXOfIn : " + endXOfIn);

Log.d(TAG, "duration : " + duration);

}

mMoveTextOut = new TranslateAnimation(startXOfOut, endXOfOut, 0, 0);

mMoveTextOut.setDuration(duration);

mMoveTextOut.setInterpolator(mInterpolator);

mMoveTextOut.setFillAfter(true);

mMoveTextIn = new TranslateAnimation(startXOfIn, endXOfIn, 0, 0);

mMoveTextIn.setDuration(duration);

mMoveTextIn.setStartOffset(mAnimationPause);

mMoveTextIn.setInterpolator(mInterpolator);

mMoveTextIn.setFillAfter(true);

mMoveTextOut.setAnimationListener(new Animation.AnimationListener() {

public void onAnimationStart(Animation animation) {

}

public void onAnimationEnd(Animation animation) {

mTextField.startAnimation(mMoveTextIn);

}

public void onAnimationRepeat(Animation animation) {

}

});

mMoveTextIn.setAnimationListener(new Animation.AnimationListener() {

public void onAnimationStart(Animation animation) {

}

public void onAnimationEnd(Animation animation) {

startTextFieldAnimation();

}

public void onAnimationRepeat(Animation animation) {

}

});

}

/** 初始化子View */

private void initView(Context context) {

// Scroll View

LayoutParams sv1lp = new LayoutParams(LayoutParams.MATCH_PARENT,

LayoutParams.WRAP_CONTENT);

sv1lp.gravity = Gravity.CENTER_HORIZONTAL;

mScrollView = new ScrollView(context);

// Scroll View 1 - Text Field

mTextField = (TextView) getChildAt(0);

removeView(mTextField);

mScrollView.addView(mTextField, new ScrollView.LayoutParams(

TEXTVIEW_VIRTUAL_WIDTH, LayoutParams.WRAP_CONTENT));

mTextField.addTextChangedListener(new TextWatcher() {

@Override

public void beforeTextChanged(CharSequence charSequence, int i,

int i2, int i3) {

}

@Override

public void onTextChanged(CharSequence charSequence, int i, int i2,

int i3) {

}

@Override

public void afterTextChanged(Editable editable) {

Logcat.d(TAG, "afterTextChanged called");

// 如果提供的字符串未被加工過,就先加工,否則就開始動畫

if (!stringOfTextView.equals(editable.toString())) {

String str = editable.toString();

mPaint.setTextSize(mTextField.getTextSize());

mPaint.setTypeface(mTextField.getTypeface());

stringOfItem = str + interval;

widthOfItem = mPaint.measureText(stringOfItem);

stringOfTextView = stringOfItem;

widthOfTextView = widthOfItem;

while (widthOfTextView <= 2 * getMeasuredWidth()) {

stringOfTextView += stringOfItem;

widthOfTextView = mPaint.measureText(stringOfTextView);

}

Logcat.d(TAG, "string of TextView deal ok!###");

Logcat.d(TAG, "lengthOfll: " + getMeasuredWidth() + "###");

Logcat.d(TAG, "lengthOfTextView: " + widthOfTextView

+ "###");

Logcat.d(TAG, "CONTENT: " + stringOfTextView + "###");

// 設置起始

mTextField.setText(stringOfTextView);

return;

}

reset();

prepareAnimation();

expandTextView();

post(new Runnable() {

@Override

public void run() {

startMarquee();

}

});

}

});

addView(mScrollView, sv1lp);

}

private void expandTextView() {

ViewGroup.LayoutParams lp = mTextField.getLayoutParams();

lp.width = (int) widthOfTextView + 5;

mTextField.setLayoutParams(lp);

}

}

使用:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

tools:context=".MainActivity" >

android:id="@+id/marqueeView"

android:layout_width="match_parent"

android:layout_height="wrap_content" >

android:id="@+id/tv_marquee"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:ellipsize="end"

android:singleLine="true"

android:text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do."

android:textSize="20sp"

android:textStyle="bold" />

下載地址:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281542.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281542.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281542.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python:軟件目錄結構規范

為什么要設計好目錄結構&#xff1f; “設計項目目錄結構”&#xff0c;就和“代碼編碼風格”一樣&#xff0c;屬于個人風格問題。對于這種風格上的規范&#xff0c;一直都存在兩種態度&#xff1a; 1.一種認為&#xff0c;這種個人風格問題“無關緊要”。理由是能讓程序work就…

開啟智能生活新時代 河北省智慧社區建設從各個擊破

智慧社區作為智慧城市的重要組成部分&#xff0c;是城市智慧落地的觸點&#xff0c;是城市管理、政務服務和市場服務的載體。隨著智慧城市的推廣以及新一代技術的普及&#xff0c;智慧社區的項目必將迎來新一輪的快速發展。2016年智慧社區成為企業業務落地的承載點&#xff0c;…

C# WPF 表格控件的前后臺數據交互?

概述GridControl控件使用我們已經進行了實例講解&#xff0c;這節內容我們列舉一個特殊的應用場景&#xff1a;表格中有一列CheckBox&#xff0c;默認都處于勾選狀態&#xff0c;當用戶通過界面操作后&#xff0c;我們要確保用戶至少選擇了一項&#xff0c;相當于一次數據驗證&…

Java(C#)基礎差異-語法

1、long類型 Java long類型&#xff0c;若賦值大于int型的最大值&#xff0c;或小于int型的最小值&#xff0c;則需要在數字后加L或者l&#xff0c;表示該數值為長整數&#xff0c;如long num2147483650L。 舉例如下&#xff1a; public static void main(String[] args) {/** …

android防止左向右滑出程序,Android——ViewPager禁止左右滑動的實現

目錄1 背景用ViewPagerBottomNavigationView多個Fragment快速搭建的頁面切換架構&#xff0c;一個有四個頁面&#xff0c;因為測試需要&#xff0c;需要屏蔽掉中間的兩個&#xff0c;做法是&#xff1a;設置不可點擊選擇&#xff1a;xml布局文件中&#xff0c;BottomNavigation…

Yii2 的快速配置 api 服務 yii2-fast-api

yii2-fast-api yii2-fast-api是一個Yii2框架的擴展&#xff0c;用于配置完善Yii2&#xff0c;以實現api的快速開發。 此擴展默認的場景是APP的后端接口開發&#xff0c;因此偏向于實用主義&#xff0c;并未完全采用restfull的標準&#xff0c;方便前端開發處理接口數據以及各種…

.NET6打包部署到Windows Service

1.安裝Nuget包安裝以下nuget包支持windows service<PackageReference Include"Microsoft.AspNetCore.Hosting.WindowsServices" Version"6.0.10" /> <PackageReference Include"Microsoft.Extensions.Hosting.WindowsServices" Version…

傳統家電在智能家居變革的五大優勢

而在眾多向智能家居領域轉型變革的企業中&#xff0c;看似落后的傳統家電企業&#xff0c;卻占據著一定的優勢。 產品優勢 傳統家電企業在產品上的優勢主要體現在企業擁有產品本身的設計、技術、生產、制造和營銷渠道&#xff0c;其產品不論是從外觀設計、零件制造還是零件組裝…

《Apache Kafka實戰》讀書筆記-調優Kafka集群

《Apache Kafka實戰》讀書筆記-調優Kafka集群 作者&#xff1a;尹正杰 版權聲明&#xff1a;原創作品&#xff0c;謝絕轉載&#xff01;否則將追究法律責任。 一.確定調優目標 1>.常見的非功能性要求 一.性能&#xff08;performance&#xff09;最重要的非功能性需求之一。…

android emoji unicode編碼表,unicode編碼

unicode編碼app是一款字符查找客戶端應用&#xff0c;通過unicode編碼可以方便尋找特定字符&#xff0c;查看字符表情詳細的描述&#xff0c;并且利用unicode編碼就可以快捷復制任意unicode編碼&#xff0c;提高開發效率&#xff0c;非常的實用&#xff0c;快來下載unicode編碼…

物聯網商機誘人 芯片商大力搭建生態系統

應用需求變化多端的物聯網&#xff0c;雖具備龐大的發展潛力及應用商機&#xff0c;但由于市場過于分散&#xff0c;幾乎沒有殺手應用可言&#xff0c;因此對有意耕耘相關市場的半導體業者而言&#xff0c;如何借力使力&#xff0c;尋找盟友共同搭建出的生態系統&#xff0c;遂…

ASP.NET Core 6框架揭秘實例演示[30]:利用路由開發REST API

借助路由系統提供的請求URL模式與對應終結點之間的映射關系&#xff0c;我們可以將具有相同URL模式的請求分發給與之匹配的終結點進行處理。ASP.NET的路由是通過EndpointRoutingMiddleware和EndpointMiddleware這兩個中間件協作完成的&#xff0c;它們在ASP.NET平臺上具有舉足輕…

數據庫(二)tab補全功能,使數據庫支持簡體中文,日志管理,備份腳本

一、如何在MySQL數據庫中使用tab鍵補全功能 1.修改主配置文件/etc/my.cnf vim /etc/my.cnf [mysql] #no-auto-rehash auto-rehash 2.重啟MySQL服務&#xff0c;登錄測試 /etc/init.d/mysqld restart mysql -uroot -p (可在數據庫中使用tab鍵&#xff09; 3.&#xff1b;臨時支持…

php new self()關鍵字的用法

今天開框架源碼&#xff0c;發現有用到new self()的用法 有點不懂 在網上查了一下&#xff0c;給大家說一下&#xff1a; 在類中 self的用法 和this的用法差不多 &#xff0c; php new self() 一般在類內部使用&#xff0c;作用是對自身類實例化&#xff0c;下面給個實例講解…

android listview item置頂,ListView的item置頂

ListView的item設置置頂1.activitypublic class TopListViewActivity extends Activity {private static int ON_TOP 1;private static int CANCEL_TOP 0;public static String TOP_STATES "TOP";private ListView mListView;private List sessionList;private Se…

電信運營商x86服務器定制策略

近幾年&#xff0c;伴隨云計算、大數據、移動互聯網、物聯網等新技術從概念到實踐&#xff0c;業務、用戶數據海量式爆發增長&#xff0c;作為承載這些業務發展的服務器行業也面臨巨大的機遇和挑戰。一方面&#xff0c;需求的爆發式增長大幅提升了市場空間&#xff0c;尤其是大…

企業數字化轉型服務+方案

前言&#xff1a;本文的閱讀對象是公司老板、或企業高層管理者&#xff01;1【背景介紹】數字經濟與實體經濟深度融合是助推我國經濟高質量發展的重要環節。為加快數字中國建設&#xff0c;中央和地方政府都出臺各類政策扶植數字化轉型相關項目。馬云在接受采訪時也提到&#x…

在 MongoDB 上模擬事務操作來實現支付

我們的產品叫「學海密探」&#xff0c;屬于在線教育行業&#xff0c;產品需要有支付功能&#xff0c;然而支付最蛋疼是什么&#xff1f;有人會說是支付寶和微信等支付接口的接入開發&#xff01;沒錯&#xff0c;但支付接口的開發算是比較簡單的了&#xff0c;我覺得凡是跟錢有…

Zabbix server is not running

問題描述 Dashbord中提示Zabbix server is not running 分析過程 首先查看zabbix-server的運行狀態 systemctl status zabbix-server 確定是否是active(running)狀態&#xff0c;如果不是&#xff0c;重啟zabbix-server查看log tail -f /var/log/zabbix/zabbix_server.log 導致…

android 把異常寫入到文本里,嘗試在Android中將文件寫入sdcard時發生FileNotFoundException(權限被拒絕)...

從標題中可以看到&#xff0c;我在Android中將文件寫入sdcard時遇到問題.我想寫入將在sdcard上的公共空間中的文件&#xff0c;以便任何其他應用程序都可以讀取它。首先&#xff0c;我檢查sdcard是否已安裝&#xff1a;Environment.getExternalStorageState();然后&#xff0c;…