【移動應(yīng)用開發(fā)技術(shù)】Android中怎么使用ListView實(shí)現(xiàn)滾輪動畫效果_第1頁
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么使用ListView實(shí)現(xiàn)滾輪動畫效果_第2頁
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么使用ListView實(shí)現(xiàn)滾輪動畫效果_第3頁
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么使用ListView實(shí)現(xiàn)滾輪動畫效果_第4頁
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么使用ListView實(shí)現(xiàn)滾輪動畫效果_第5頁
已閱讀5頁,還剩21頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

【移動應(yīng)用開發(fā)技術(shù)】Android中怎么使用ListView實(shí)現(xiàn)滾輪動畫效果

今天就跟大家聊聊有關(guān)Android中怎么使用ListView實(shí)現(xiàn)滾輪動畫效果,可能很多人都不太了解,為了讓大家更加了解,在下給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。/**

*

中點(diǎn)的Y坐標(biāo)

*/

private

float

centerY

=

0f;

@Override

public

void

onScroll(AbsListView

view,

int

firstVisibleItem,

int

visibleItemCount,

int

totalItemCount)

{

//計(jì)算中點(diǎn)

centerY

=

getHeight()/2;

//判斷中點(diǎn)的有效性

if(centerY

<=

0){

return;

}

//開始對當(dāng)前顯示的View進(jìn)行縮放

for(int

i

=

0;

i

<

visibleItemCount;

i++){

//獲取item

View

temp_view

=

getChildAt(i);

//計(jì)算item的中點(diǎn)Y坐標(biāo)

float

itemY

=

temp_view.getBottom()-(temp_view.getHeight()/2);

//計(jì)算離中點(diǎn)的距離

float

distance

=

centerY;

if(itemY

>

centerY){

distance

=

itemY

-

centerY;

}else{

distance

=

centerY

-

itemY;

}

//根據(jù)距離進(jìn)行縮放

temp_view.setScaleY(1.1f

-

(distance

/

centerY)

<

0

?

0

:

1.1f

-

(distance

/

centerY));

temp_view.setScaleX(1.1f

-

(distance

/

centerY)

<

0

?

0

:

1.1f

-

(distance

/

centerY));

//根據(jù)距離改變透明度

temp_view.setAlpha(1.1f

-

(distance

/

centerY)

<

0

?

0

:

1.1f

-

(distance

/

centerY));

}

}后面不想加demo了,所以直接上整個ListView的代碼吧/**

*

模仿滾輪動畫縮放的ListView

*

Created

by

xu

on

2017/3/3.

*/

public

class

XuListView

extends

ListView

implements

AbsListView.OnScrollListener

{

private

static

final

String

TAG

=

"XuListView";

/**

*

中點(diǎn)的Y坐標(biāo)

*/

private

float

centerY

=

0f;

public

XuListView(Context

context,

AttributeSet

attrs)

{

super(context,

attrs);

//設(shè)置一個滾動監(jiān)聽

setOnScrollListener(this);

}

@Override

public

void

onScrollStateChanged(AbsListView

view,

int

scrollState)

{

}

@Override

public

void

onScroll(AbsListView

view,

int

firstVisibleItem,

int

visibleItemCount,

int

totalItemCount)

{

//計(jì)算中點(diǎn)

centerY

=

getHeight()/2;

//判斷中點(diǎn)的有效性

if(centerY

<=

0){

return;

}

//開始對當(dāng)前顯示的View進(jìn)行縮放

for(int

i

=

0;

i

<

visibleItemCount;

i++){

//獲取item

View

temp_view

=

getChildAt(i);

//計(jì)算item的中點(diǎn)Y坐標(biāo)

float

itemY

=

temp_view.getBottom()-(temp_view.getHeight()/2);

//計(jì)算離中點(diǎn)的距離

float

distance

=

centerY;

if(itemY

>

centerY){

distance

=

itemY

-

centerY;

}else{

distance

=

centerY

-

itemY;

}

//根據(jù)距離進(jìn)行縮放

temp_view.setScaleY(1.1f

-

(distance

/

centerY)

<

0

?

0

:

1.1f

-

(distance

/

centerY));

temp_view.setScaleX(1.1f

-

(distance

/

centerY)

<

0

?

0

:

1.1f

-

(distance

/

centerY));

//根據(jù)距離改變透明度

temp_view.setAlpha(1.1f

-

(distance

/

centerY)

<

0

?

0

:

1.1f

-

(distance

/

centerY));

}

}

}這樣基本就實(shí)現(xiàn)了我們想要的效果了但是現(xiàn)在有一個問題,就是第一個item和最后一個item無法滾動到中間從而放大突出顯示。對此我暫時想了兩個方法去解決:1、在頭尾各種添加一些空白的item,使我們需要顯示的數(shù)據(jù)都可以滾動到最中間。(我現(xiàn)在就是這么做的);2、使整個列表實(shí)現(xiàn)循環(huán)滾動。添加空白的item的話,我是通過修改adapter去實(shí)現(xiàn)的。數(shù)據(jù)源是一個數(shù)組,我在數(shù)組前面和后面各加一些特殊的數(shù)據(jù),adapter實(shí)現(xiàn)getview的時候,如果發(fā)現(xiàn)當(dāng)前item的數(shù)據(jù)是特殊數(shù)據(jù),那么item就變透明,從而實(shí)現(xiàn)了我們原本要顯示的數(shù)據(jù)都可以被滾動最中間;先從數(shù)據(jù)源下手,從頭尾填充特殊的數(shù)據(jù)public

class

MainActivity

extends

AppCompatActivity

{

XuListView

mLisetview;

MyAdapter

adapter;

ArrayList<String>

nos

=

new

ArrayList<String>();

@Override

protected

void

onCreate(Bundle

savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mLisetview

=

(XuListView)

findViewById(R.id.list_test);

ArrayList<String>

temp

=

new

ArrayList<String>();

for(int

i

=

0;i<10;i++){

temp.add(i+"");

}

adapter

=

new

MyAdapter(this,temp);

mLisetview.setAdapter(adapter);

resetitem(mLisetview);

}

/**

*

在頭尾填充透明的item數(shù)據(jù)

*/

private

void

resetitem(ListView

listview)

{

if(listview

==

null){

return;

}

//獲取屏幕高度

WindowManager

wm

=getWindowManager();

int

displayheight

=

wm.getDefaultDisplay().getHeight();

//計(jì)算一個item的高度

int

itemhight

=

0;

if(adapter!=null){

View

v=(View)adapter.getView(0,

null,

listview);

v.measure(

View.MeasureSpec.makeMeasureSpec(0,

View.MeasureSpec.UNSPECIFIED),

View.MeasureSpec.makeMeasureSpec(0,

View.MeasureSpec.UNSPECIFIED));

itemhight=v.getMeasuredHeight();

}

//根據(jù)Item的高度和屏幕的高度計(jì)算需要多少個item可以填滿一半的屏幕

int

newcount

=

((displayheight/2)/itemhight);

//填充前面的空白item

for

(int

i

=

1;

i

<=

newcount;

i++)

{

nos.add("full");

}

//添加我們需要顯示的數(shù)據(jù)

for(int

i

=

0;i<10;i++){

nos.add(i+"");

}

//填充后面的空白item

for

(int

i

=

1;

i

<=

newcount;

i++)

{

nos.add("full");

}

//刷新數(shù)據(jù)

adapter.refreshData(nos);

}

}然后adapter里面對頭尾的特殊數(shù)據(jù)進(jìn)行識別,將item變?yōu)橥该鞯?。public

class

MyAdapter

extends

BaseAdapter

{

ArrayList<String>

nos

=

new

ArrayList<String>();

private

Context

context;

public

MyAdapter(Context

context,

ArrayList<String>

nos){

this.context

=

context;

this.nos

=

nos;

}

public

void

refreshData(ArrayList<String>

nos)

{

this.nos

=

nos;

notifyDataSetChanged();

}

@Override

public

int

getCount()

{

return

nos.size();

}

@Override

public

Object

getItem(int

position)

{

return

nos.get(position);

}

@Override

public

long

getItemId(int

position)

{

return

position;

}

@Override

public

View

getView(int

position,

View

convertView,

ViewGroup

parent)

{

ViewHolder

holder

=

null;

if

(convertView

==

null)

{

//

如果是第一次顯示該頁面(要記得保存到viewholder中供下次直接從緩存中調(diào)用)

holder

=

new

ViewHolder();

convertView

=

LayoutInflater.from(context).inflate(R.layout.item_test,

null);

holder.tv_no

=

(TextView)

convertView.findViewById(R.id.tv_no);

convertView.setTag(holder);

}

else

{

holder

=

(ViewHolder)

convertView.getTag();

}

holder.tv_no.setText(nos.get(position));

if(nos.get(position).equals("full")){

convertView.setVisibility(View.INVISIBLE);

}else{

convertView.setVisibility(View.VISIBLE);

}

return

convertView;

}

private

class

ViewHolder

{

TextView

tv_no;

}

}

這樣我們就實(shí)現(xiàn)可以第一種解決方法第二種方法,就是讓整個ListView實(shí)現(xiàn)循環(huán)滾動,實(shí)現(xiàn)的方式有很多,大家可以自行百度,我這里就通過修改adapter的getCount方法去實(shí)現(xiàn),就是在getCount方法return一個很大的值,getView獲取數(shù)據(jù)的時候要模原本的數(shù)組大小,不然數(shù)組就越界了。然后ListView滾動到最中間,這樣就實(shí)現(xiàn)偽循環(huán)滾動了public

class

MainActivity

extends

AppCompatActivity

{

XuListView

mLisetview;

MyAdapter

adapter;

ArrayList<String>

nos

=

new

ArrayList<String>();

@Override

protected

void

onCreate(Bundle

savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mLisetview

=

(XuListView)

findViewById(R.id.list_test);

ArrayList<String>

temp

=

new

ArrayList<String>();

for(int

i

=

0;i<10;i++){

temp.add(i+"");

}

adapter

=

new

MyAdapter(this,temp);

mLisetview.setAdapter(adapter);

//滾動到中間

mLisetview.setSelection(adapter.getCount()/2);

}

}/**

*

Created

by

xu

on

2017/6/27.

*/

public

class

MyAdapter

extends

BaseAdapter

{

ArrayList<String>

nos

=

new

ArrayList<String>();

private

Context

context;

public

MyAdapter(Context

context,

ArrayList<String>

nos){

this.context

=

context;

this.nos

=

nos;

}

@Override

public

int

getCount()

{

return

Integer.MAX_VALUE;

}

@Override

public

Object

getItem(int

position)

{

return

nos.get(position);

}

@Override

public

long

getItemId(int

position)

{

return

position;

}

@Override

public

View

getView(int

position,

View

convertView,

ViewGroup

parent)

{

ViewHolder

holder

=

null;

if

(convertView

==

null)

{

//

如果是第一次顯示該頁面(要記得保存到viewholder中供下次直接從緩存中調(diào)用)

holder

=

new

ViewHolder();

convertView

=

LayoutInflater.from(context).inflate(R.layout.item_test,

null);

holder.tv_no

=

(TextView)

convertView.findViewById(R.id.tv_no);

convertView.setTag(holder);

}

else

{

holder

=

(ViewHolder)

convertView.getTag();

}

holder.tv_no.setText(nos.get(position%nos.size()));

return

convertView;

}

private

class

ViewHolder

{

TextView

tv_no;

}

}這樣我們就實(shí)現(xiàn)了使列表進(jìn)行循環(huán)滾動,從而達(dá)到每個item都可以滾動到中間突出顯示的效果了既然我們把動畫效果都做出來了,那么也可以直接做成一個滾輪選擇器,只需要加多兩步:1、把最靠近中間的item滾動到中間;2、把中間的item的序號通過一個接口返回出去。我就直接貼代碼吧,反正也不難。把最靠近中間的item滾動到中間的實(shí)現(xiàn)我是這么做的:首先決定好整個ListView可視的的item數(shù)量是多少,必須是奇數(shù),這樣才能只有一個item處于正中間,然后根據(jù)ListView的高度計(jì)算出每個item符合要求的高度,然后更改現(xiàn)有的item的高度,同時對內(nèi)容進(jìn)行縮放(不縮放內(nèi)容單純高度變小的話布局就亂了)。最后我們利用smoothScrollToPosition方法回正可視item中的第一個item,就實(shí)現(xiàn)了將最中間的item回滾到最中間的效果了。因?yàn)榭梢暤膇tem我們是根據(jù)ListView的高度去計(jì)算item的高度的,所有的可視item剛好鋪滿ListView,所以只要頂部那個回正了,其他的item也會回正。所以我們可以重寫一下OnScrollListener的onScrollStateChanged方法,每次滾動結(jié)束就執(zhí)行一次回滾/**

*

可視的item數(shù)

*/

private

int

mVisibleItemCount

=

-1;

/**

*

沒調(diào)整之前每個item的高度

*/

private

float

olditemheight

=

0;

/**

*

調(diào)整過后的每個item的高度

*/

private

float

newitemheight

=

-1;

/**

*

調(diào)整每個可視的item的高度

以及對內(nèi)容進(jìn)行縮放

*/

public

void

reSetItemHeight()

{

for

(int

i

=

0;

i

<

getChildCount();

i++)

{

//獲取item

View

temp_view

=

getChildAt(i);

//設(shè)置item的高度

ViewGroup.LayoutParams

lp

=

temp_view.getLayoutParams();

lp.height

=

(int)

newitemheight;

temp_view.setLayoutParams(lp);

//縮放內(nèi)容

我的item的內(nèi)容用一個LinearLayout包了起來

所以直接縮放LinearLayout

LinearLayout

item_ll_value

=

(LinearLayout)

temp_view.findViewById(R.id.item_ll_value);

item_ll_value.setScaleY((newitemheight

/

olditemheight)

<

0

?

0

:

(newitemheight

/

olditemheight));

item_ll_value.setScaleX((newitemheight

/

olditemheight)

<

0

?

0

:

(newitemheight

/

olditemheight));

}

}

/**

*

計(jì)算在給定的可視item數(shù)目下

每個item應(yīng)該設(shè)置的高度

*

*/

private

void

getNewItemHeight()

{

//先把舊的item存起來

olditemheight

=

getChildAt(0).getHeight();

//計(jì)算新的高度

newitemheight

=

getHeight()

/

mVisibleItemCount;

if

((getHeight()

/

mVisibleItemCount)

%

newitemheight

>

0)

{

//除不盡的情況下把余數(shù)分給各個item,暫時發(fā)現(xiàn)分一次余數(shù)就夠了,如果效果不理想就做個遞歸多分幾次

float

remainder

=

(getHeight()

/

mVisibleItemCount)

%

newitemheight;

newitemheight

=

remainder

/

mVisibleItemCount;

}

}

@Override

public

void

onScrollStateChanged(AbsListView

view,

int

scrollState)

{

//滾動結(jié)束之后開始回滾item

if

(scrollState

==

AbsListView.OnScrollListener.SCROLL_STATE_IDLE

&&

mVisibleItemCount

!=

-1)

{

//使離中間最近的item回滾到中點(diǎn)位置

smoothScrollToPosition(getFirstVisiblePosition());

}

}實(shí)現(xiàn)了把最靠近中間的item滾動到中間,那么選擇的item就是滾動結(jié)束后處于最中間的item。對此我們需要再次重寫一下OnScrollListener的onScrollStateChanged方法。每次滾動結(jié)束后,取可視item中的第一個item的序號加上我們之前設(shè)置的可視item數(shù)的一半(舍去小數(shù)部分)就是最中間的item的序號了,也是當(dāng)前選擇項(xiàng)的序號。/**

*

當(dāng)前選中項(xiàng)發(fā)生變化的監(jiān)聽者

*/

private

onSelectionChangeLisenter

selectionChangeLisenter;

/**

*

設(shè)置選中項(xiàng)的監(jiān)聽者

*/

public

void

setSelectionChangeLisenter(onSelectionChangeLisenter

selectionChangeLisenter)

{

this.selectionChangeLisenter

=

selectionChangeLisenter;

}

@Override

public

void

onScrollStateChanged(AbsListView

view,

int

scrollState)

{

//滾動結(jié)束之后開始正常回滾item并記錄最中間的item為選中項(xiàng)

(必須設(shè)置可視項(xiàng),ListView才會改為選擇器模式)

if(

scrollState

==

AbsListView.OnScrollListener.SCROLL_STATE_IDLE

&&

mVisibleItemCount

!=

-1){

//使離中間最近的item回滾到中點(diǎn)位置

smoothScrollToPosition(getFirstVisiblePosition());

//計(jì)算當(dāng)前選中項(xiàng)的序號

int

nowPosition

=

getFirstVisiblePosition()

+

mVisibleItemCount/2;

//把當(dāng)前選中項(xiàng)的序號存起來并通過listener回調(diào)出去

if(selectionChangeLisenter

!=

null

&&

nowPosition

!=

curPosition){

curPosition

=

nowPosition;

selectionChangeLisenter.onSelectionChange(curPosition);

}

}

}此處我是使用了一個接口去,用以實(shí)時把最新的數(shù)據(jù)返回出去/**

*

Created

by

xu

on

2017/3/3.

*/

public

interface

onSelectionChangeLisenter

{

void

onSelectionChange(int

position);

}使用這個滾輪選擇器的方法也非常簡單,除了跟正常的ListView初始化和綁定adapter之外,只需要額外調(diào)用兩個方法就行了//設(shè)置ListView的可視item數(shù)(必須是奇數(shù))

mLisetview.setVisibleItemCount(3);//設(shè)置監(jiān)聽者監(jiān)聽選中項(xiàng)的變化

mLisetview.setSelectionChangeLisenter(new

onSelectionChangeLisenter()

{

@Override

public

void

onSelectionChange(final

int

position)

{

mHandler.post(new

Runnable()

{

@Override

public

void

run()

{

Toast.makeText(MainActivity.this,"選擇項(xiàng)發(fā)生變化

當(dāng)前選中序號:"+(temp.get(position)),Toast.LENGTH_SHORT).show();

}

});

}

});這樣我們就實(shí)現(xiàn)滾輪數(shù)字選擇器的效果了現(xiàn)在貼下整個滾輪選擇器的完整代碼/**

*

模仿滾輪動畫縮放的ListView

*

Created

by

xu

on

2017/3/3.

*/

public

class

XuListView

extends

ListView

implements

AbsListView.OnScrollListener

{

private

static

final

String

TAG

=

"XuListView";

/**

*

中點(diǎn)的Y坐標(biāo)

*/

private

float

centerY

=

0f;

/**

*

可視的item數(shù)

*/

private

int

mVisibleItemCount

=

-1;

/**

*

沒調(diào)整之前每個item的高度

*/

private

float

olditemheight

=

0;

/**

*

調(diào)整過后的每個item的高度

*/

private

float

newitemheight

=

-1;

/**

*

當(dāng)前選中項(xiàng)發(fā)生變化的監(jiān)聽者

*/

private

onSelectionChangeLisenter

selectionChangeLisenter;

/**

*

當(dāng)前選中項(xiàng)的序號

*/

private

int

curPosition

=

-1;

public

XuListView(Context

context,

AttributeSet

attrs)

{

super(context,

attrs);

//設(shè)置一個滾動監(jiān)聽

setOnScrollListener(this);

}

/**

*

設(shè)置選中項(xiàng)的監(jiān)聽者

*/

public

void

setSelectionChangeLisenter(onSelectionChangeLisenter

selectionChangeLisenter)

{

this.selectionChangeLisenter

=

selectionChangeLisenter;

}

/**

*

設(shè)置ListView的顯示item數(shù)

*

@param

count

:必須是奇數(shù)

如果為-1

則表示只是使用動畫效果的普通ListView

*/

public

boolean

setVisibleItemCount(int

count){

if(count

%

2

==

0){

return

false;

}else{

mVisibleItemCount

=

count;

return

true;

}

}

/**

*

在這里第一次調(diào)整item高度

*/

@Override

public

void

onWindowFocusChanged(boolean

hasWindowFocus)

{

super.onWindowFocusChanged(hasWindowFocus);

if(mVisibleItemCount

!=

-1){

getNewItemHeight();

reSetItemHeight();

}

}

/**

*

調(diào)整每個可視的item的高度

以及對內(nèi)容進(jìn)行縮放

*/

public

void

reSetItemHeight(){

for(int

i

=

0;

i

<

getChildCount();

i++){

//獲取item

View

temp_view

=

getChildAt(i);

//設(shè)置item的高度

ViewGroup.LayoutParams

lp

=

temp_view.getLayoutParams();

lp.height

=

(int)newitemheight;

temp_view.setLayoutParams(lp);

//縮放內(nèi)容

我的item的內(nèi)容用一個LinearLayout包了起來

所以直接縮放LinearLayout

LinearLayout

item_ll_value

=

(LinearLayout)temp_view.findViewById(R.id.item_ll_value);

item_ll_value.setScaleY((newitemheight

/

olditemheight)

<

0

?

0

:

(newitemheight

/

olditemheight));

item_ll_value.setScaleX((newitemheight

/

olditemheight)

<

0

?

0

:

(newitemheight

/

olditemheight));

}

}

/**

*

計(jì)算在給定的可視item數(shù)目下

每個item應(yīng)該設(shè)置的高度

*/

private

void

getNewItemHeight(){

//先把舊的item存起來

olditemheight

=

getChildAt(0).getHeight();

//計(jì)算新的高度

newitemheight

=

getHeight()/mVisibleItemCount;

if((getHeight()/mVisibleItemCount)

%

newitemheight

>

0){

//除不盡的情況下把余數(shù)分給各個item,暫時發(fā)現(xiàn)分一次余數(shù)就夠了,如果效果不理想就做個遞歸多分幾次

float

remainder

=

(getHeight()/mVisibleItemCount)

%

newitemheight;

newitemheight

=

remainder/mVisibleItemCount;

}

}

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論