日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android高仿天天动听,Android仿天天动听歌曲自动滚动view

發(fā)布時間:2025/3/11 Android 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android高仿天天动听,Android仿天天动听歌曲自动滚动view 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

最近項目中要做一個類似天天動聽歌曲自動滾動行數(shù)的效果。首先自己想了下Android要滾動的那就是scroller類或者scrollto、scrollby結(jié)合了,或者view.layout()方法,或者使用動畫。但是要循環(huán)滾動,貌似這些到最后一行滾動到第一行都有往回滾的效果,都不是很好的解決方法。怎么會忘記了可以繪制事件萬物的的canvas呢。好吧,既然找到了,那就用這個方案吧!但是天天動聽歌曲還有一個手動滑動的效果,貌似這篇文章沒寫。既然這樣,那就自己來寫下吧!實現(xiàn)之前還是先看下天天動聽的效果:

正文

想法1:獲取滑動的距離,然后計算滑動了多少行,然后更新數(shù)據(jù)。實現(xiàn)起來貌似效果不咋地。

想法2:我們可以看的出來他滾動是一行一行的滾動的,只是根據(jù)滾動的快慢來決定滾動行數(shù)的快慢。既然這樣的話,只要滾動了,就一定時間的去一行行的滾動,然后根據(jù)滾動的速度來決定更新的間隔時間。

嗯,想好了怎么實現(xiàn),現(xiàn)在就來寫代碼吧。

先來寫一個類,繼承TextView

VerticalScrollTextView.class

public class VerticalScrollTextView extends TextView implements Runnable{

//繪制歌詞畫筆

private Paint mContentPaint;

//繪制基線畫筆

private Paint mLinePaint;

//繪制滑動進度背景畫筆

private Paint mRectPaint;

//歌詞數(shù)據(jù)

private List mDataList;

//行數(shù)

private int index = 0 ;

//當前view的寬

private float mX;

//當前view的高

private float mY;

//當前view垂直方向中線

private float middleY;

//行與行之間的間距

private final static int DY = 80 ;

//歌詞文字大小

private int mTextSize = 35;

//歌詞中間字體的大小

private int mBigTextSize = 45;

//當前是否按下

private boolean isTouch = false ;

//上一次觸摸view的y軸坐標

private float mLastY;

//是否正在滑動

private boolean isMoving;

//記錄上一次滑動的時間

private long lastMoveTime;

//滑動速度追蹤類

private VelocityTracker mVelocityTracker;

//滑動最大速度

private int mMaximumVelocity;

//歌詞是否為空

private boolean isEmpty;

public VerticalScrollTextView(Context context) {

this(context,null);

}

public VerticalScrollTextView(Context context, AttributeSet attrs) {

this(context, attrs,0);

}

public VerticalScrollTextView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

//獲取最大的滑動速度值

mMaximumVelocity = ViewConfiguration.get(context)

.getScaledMaximumFlingVelocity();

init();

}

private void init(){

setFocusable(true);

setClickable(true);

//歌詞為空設置默認值

if(mDataList==null){

mDataList = new ArrayList<>();

Sentence sentence = new Sentence(0,"沒有獲取到歌詞",0);

mDataList.add(sentence);

isEmpty = true ;

}

//初始化歌詞畫筆

mContentPaint = new Paint();

mContentPaint.setTextSize(mTextSize);

mContentPaint.setAntiAlias(true);

mContentPaint.setColor(Color.parseColor("#e5e2e2"));

//設置為serif字體

mContentPaint.setTypeface(Typeface.SERIF);

//設置字體為居中

mContentPaint.setTextAlign(Paint.Align.CENTER);

//初始化基線畫筆

mLinePaint = new Paint();

mLinePaint.setAntiAlias(true);

mLinePaint.setStrokeWidth(1);

mLinePaint.setColor(Color.WHITE);

//進度背景顏色畫筆

mRectPaint = new Paint();

mLinePaint.setAntiAlias(true);

mRectPaint.setColor(Color.parseColor("#66666666"));

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//如果當前進度為-1,直接返回,不用繪制

if (index == -1)

return;

Sentence sentence = mDataList.get(index);

//繪制中間行的歌詞,設置為高亮白色,大字體

mContentPaint.setColor(Color.WHITE);

mContentPaint.setTextSize(mBigTextSize);

canvas.drawText(sentence.getName(), mX/2, middleY, mContentPaint);

//當前為歌詞不為空并且按下的情況下,繪制基線和進度

if(!isEmpty&&isTouch){

//獲取中間行字體最高的位置

float baseLine = middleY-Math.abs(mContentPaint.ascent());

//繪制進度背景

canvas.drawRect(10.0f,baseLine-70,150.0f,baseLine,mRectPaint);

//繪制基線

canvas.drawLine(10.0f,baseLine,mX-10,baseLine,mLinePaint);

//設置進度字體大小

mContentPaint.setTextSize(mTextSize);

//繪制進度字體

canvas.drawText(String.valueOf(index),85,baseLine-35,mContentPaint);

}

//初始化isEmpty

isEmpty = false ;

//初始化歌詞內(nèi)容畫筆

mContentPaint.setColor(Color.parseColor("#e5e2e2"));

mContentPaint.setTextSize(mTextSize);

//暫時保存中間線位置,來繪制中間線以上的行數(shù)字體

float tempY = middleY;

//繪制中間線以上的歌詞

for (int i = index - 1; i >= 0; i--) {

tempY = tempY - DY;

if (tempY < 0) {

break;

}

Sentence preSentence = mDataList.get(i);

canvas.drawText(preSentence.getName(), mX/2, tempY, mContentPaint);

}

tempY = middleY;

//繪制中間線以下的歌詞

for (int i = index + 1; i < mDataList.size(); i++) {

tempY = tempY + DY;

if (tempY > mY) {

break;

}

Sentence nexeSentence = mDataList.get(i);

canvas.drawText(nexeSentence.getName(), mX/2, tempY, mContentPaint);

}

//初始化isMoving,到這里表示滑動結(jié)束

isMoving = false ;

}

protected void onSizeChanged(int w, int h, int ow, int oh) {

super.onSizeChanged(w, h, ow, oh);

//獲取view的寬和高

mX = w;

mY = h;

middleY = h * 0.5f;

}

public long updateIndex(int index) {

if (index == -1)

return -1;

this.index=index;

return index;

}

public List getDataList() {

return mDataList;

}

public void setDataList(List mDataList){

this.mDataList = mDataList ;

}

public void updateUI(){

new Thread(this).start();

}

@Override

public boolean onTouchEvent(MotionEvent event) {

int action = event.getAction();

switch (action){

case MotionEvent.ACTION_DOWN:

isTouch =true;

mLastY = event.getY();

break;

case MotionEvent.ACTION_MOVE:

//創(chuàng)建速度追蹤器

initVelocityTrackerIfNotExists();

mVelocityTracker.addMovement(event);

mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);

//獲取當前速度。默認為100

float velocity = mVelocityTracker.getYVelocity()==0?100:mVelocityTracker.getYVelocity();

long currentTime = System.currentTimeMillis();

//設置一個固定值和速度結(jié)合決定滑動更新的快慢

if(!isMoving&&currentTime-lastMoveTime>20000/Math.abs(velocity)){

isMoving = true ;

lastMoveTime = System.currentTimeMillis();

float currentY = event.getY();

float mMoveY = currentY - mLastY;

//向上滑動-1向下滑動+1

int newIndex = mMoveY>0?index - 1:index+1;

//循環(huán)滾動

newIndex=newIndex<0?mDataList.size()-1:newIndex>=mDataList.size()?0:newIndex;

updateIndex(newIndex);

invalidate();

mLastY = currentY;

}

break;

case MotionEvent.ACTION_UP:

isTouch = false ;

recycleVelocityTracker();

break;

}

return super.onTouchEvent(event);

}

@Override

public void run() {

//自動滾動刷新的時間間隔

long time = 1000;

//控制進度

int i=0;

while (true) {

//當前不在按下的情況下自動滾動

if(!isTouch){

//設置當前的進度值

long sleeptime = updateIndex(i);

//使用handle刷新ui

mHandler.post(mUpdateResults);

if (sleeptime == -1)

return;

try {

Thread.sleep(time);

i++;

//當?shù)搅俗詈笠恍械臅r候自動跳轉(zhuǎn)到第一行

if(i==getDataList().size())

i=0;

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

Handler mHandler = new Handler();

Runnable mUpdateResults = new Runnable() {

public void run() {

invalidate();

}

};

//創(chuàng)建速度追蹤器

private void initVelocityTrackerIfNotExists() {

if (mVelocityTracker == null) {

mVelocityTracker = VelocityTracker.obtain();

}

}

//釋放

private void recycleVelocityTracker() {

if (mVelocityTracker != null) {

mVelocityTracker.recycle();

mVelocityTracker = null;

}

}

}

自定義view基本就是這樣了,我們可以把要定義的一些屬性寫在attrs里面了,這里就懶得寫了。大概的思路就是先繪制指定的index行的歌詞,然后繪制index上面行的歌詞,然后繪制index下面行的歌詞。然后新建一個線程,讓它通過handle隔一定的時間定時刷新歌詞行數(shù)。然后在onTouchEvent處理觸摸滾動行數(shù),獲取到當前滾動速度來決定一個更新的時間間隔。從而實現(xiàn)觸摸滾動刷新的快慢?;旧暇褪沁@樣了。其他的看注釋。

再看下初始化數(shù)據(jù)測試的Activity:

VerticalScrollTextActivity.class

public class VerticalScrollTextActivity extends Activity {

VerticalScrollTextView mSampleView;

String[] str = {"你在南方的艷陽里 大雪紛飛",

"我在北方的寒夜里 四季如春",

"如果天黑之前來的及",

"我要忘了你的眼睛",

"窮極一生 做不完一場夢",

"他不在和誰談論相逢的孤島",

"因為心里早已荒無人煙",

"他的心里在裝不下一個家",

"做一個只對自己說謊的啞巴",

"他說你任何為人稱道的美麗",

"不及他第一次遇見你",

"時光茍延殘喘 無可奈何",

"如果所有土地連在一起",

"走上一生只為擁抱你",

"喝醉了他的夢 晚安",

"你在南方的艷陽里 大雪紛飛",

"我在北方的寒夜里 四季如春",

"如果天黑之前來的及",

"我要忘了你的眼睛",

"窮極一生 做不完一場夢",

"他不在和誰談論相逢的孤島",

"因為心里早已荒無人煙",

"他的心里在裝不下一個家",

"做一個只對自己說謊的啞巴",

"他說你任何為人稱道的美麗",

"不及他第一次遇見你",

"時光茍延殘喘 無可奈何",

"如果所有土地連在一起",

"走上一生只為擁抱你",

"喝醉了他的夢 晚安"

};

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mSampleView = (VerticalScrollTextView) findViewById(R.id.sampleView1);

List lst=new ArrayList<>();

for(int i=0;i

Sentence sen=new Sentence(i,str[i],i+1202034);

lst.add(i, sen);

}

mSampleView.setDataList(lst);

mSampleView.updateUI();

}

}

模擬了一首歌詞數(shù)據(jù),然后setDataList,在調(diào)用updateUI()就行了。

最后看下布局文件

activity_main.xml

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/sampleView1"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@drawable/bg"

/>

測試下,我們就可以看到效果了:

以上就是本文的全部內(nèi)容,希望對大家學習Android軟件編程有所幫助。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的android高仿天天动听,Android仿天天动听歌曲自动滚动view的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。