Android中ViewFlipper和AdapterViewFlipper使用的方法實(shí)例
一、ViewFlipper
在很多APP都有如下的公告通知效果(上下自動(dòng)翻滾)
這種效果可以使用很多方式實(shí)現(xiàn),有一個(gè)簡(jiǎn)便的方式可以使用ViewFlipper控件實(shí)現(xiàn),ViewFlipper控件繼承結(jié)果如下:
可以看出ViewFlipper繼承自ViewAnimator,ViewAnimator可以將在添加到其中的兩個(gè)或多個(gè)子View之間進(jìn)行動(dòng)畫(huà)處理的簡(jiǎn)單。一次只顯示子View。可以定期在每個(gè)子View之間自動(dòng)翻轉(zhuǎn)。
現(xiàn)在使用ViewFlipper自動(dòng)上下滾動(dòng)效果,非常簡(jiǎn)單,布局文件中定義ViewFlipper
... <ViewFlipper android:id="@+id/vf_test" android:layout_width="match_parent" android:layout_height="50dip" android:autoStart="true" android:background="#00dd00" android:inAnimation="@anim/anim_in" android:outAnimation="@anim/anim_out"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:paddingLeft="10dip" android:text="這第1條消息." android:textSize="20sp" android:textStyle="bold" /> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:paddingLeft="10dip" android:text="這第2條消息.." android:textSize="20sp" android:textStyle="bold" /> </ViewFlipper> ...
顯示效果如下:
默認(rèn)ViewFlipper是無(wú)動(dòng)畫(huà),這里通過(guò)inAnimation、outAnimation配置來(lái)子View進(jìn)入和移出動(dòng)畫(huà),
inAnimation動(dòng)畫(huà)配置如下文件(anim/anim_in.xml):
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="400" android:fromYDelta="100%p" android:toYDelta="0" /> <alpha android:duration="500" android:fromAlpha="0.0" android:toAlpha="1.0" /> </set>
outAnimation動(dòng)畫(huà)配置如下文件(anim/anim_out.xml):
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="400" android:fromYDelta="0" android:toYDelta="-100%p" /> <alpha android:duration="500" android:fromAlpha="1.0" android:toAlpha="0.0" /> </set>
可以看出,這里的兩個(gè)動(dòng)畫(huà)文件均使用的是補(bǔ)間動(dòng)畫(huà)的動(dòng)畫(huà)集合(位移動(dòng)畫(huà)、透明度動(dòng)畫(huà))
ViewFlipper可配置的參數(shù):
android:autoStart : 設(shè)置顯示該組件是否是自動(dòng)播放(默認(rèn) false)
android:inAnimation : 設(shè)置組件進(jìn)入時(shí)使用的動(dòng)畫(huà)
android:outAnimation : 設(shè)置組件移出時(shí)使用的動(dòng)畫(huà)
android:flipInterval:設(shè)置自動(dòng)播放的時(shí)間間隔(ViewFlipper默認(rèn)3000ms)
android:animateFirstView:設(shè)置顯示該組件的第一個(gè)View時(shí)是否使用動(dòng)畫(huà)(默認(rèn)true,可以手動(dòng)向空的ViewFlipper addView 方式添加View看到效果)
ViewFlipper可以通過(guò)代碼設(shè)置上述配置(不再列舉),也可以通過(guò)代碼來(lái)控制播放,具體api如下:
startFlipping() :開(kāi)始播放
stopFlipping() : 停止播放
通常情況下我們滾動(dòng)的內(nèi)容是服務(wù)器下發(fā)的,所以個(gè)數(shù)無(wú)法得知,如果個(gè)數(shù)少的情況,使用ViewFlipper展示此效果沒(méi)有什么大的問(wèn)題,一但出現(xiàn)多數(shù)據(jù)情況,可能會(huì)出現(xiàn)內(nèi)存上升。
例如:有10000條數(shù)據(jù)情況:
定義一個(gè)空的ViewFlipper,如下:
... <ViewFlipper android:id="@+id/vf_test" android:layout_width="match_parent" android:layout_height="50dip" android:autoStart="true" android:background="#00dd00" android:inAnimation="@anim/anim_in" android:outAnimation="@anim/anim_out"> </ViewFlipper> ...
每個(gè)子View布局(item_view.xml)如下:
<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:paddingLeft="10dip" android:textSize="20sp" android:textStyle="bold" />
再通過(guò)代碼方式添加子View,如下:
... ViewFlipper vf_test = (ViewFlipper) findViewById(R.id.vf_test); for (int i = 0; i < 10000; i++) { TextView textView = (TextView) LayoutInflater.from(DemoActivity.this).inflate(R.layout.item_view, null); textView.setText("這是第" + i + "條消息"); vf_test.addView(textView); } ...
運(yùn)行APP可以明顯看出頁(yè)面卡頓來(lái)幾秒后才顯示,內(nèi)存使用情況如下:
這里的每個(gè)item還僅為一個(gè)TextView,如果每個(gè)item布局復(fù)雜,所占用的內(nèi)存更高。像這種大數(shù)據(jù)的情況,我們可以使用適配器模式的ViewFlipper(AdapterViewFlipper)來(lái)替代。
二、AdapterViewFlipper
AdapterViewFlipper的繼承關(guān)系如下:
注:AdapterViewFlipper是api11(Android 3.0)中新增的,現(xiàn)在的APP最低支持版本肯定大于此版本,基本可以忽略。
從繼承關(guān)系可以看出AdapterViewFlipper同ListView類似,都繼承了AdapterView,所以AdapterViewFlipper可以像ListView一樣使用數(shù)據(jù)適配器來(lái)填充數(shù)據(jù)。
先定義一個(gè)AdapterViewFlipper如下:
... <AdapterViewFlipper android:id="@+id/avf_view" android:layout_width="match_parent" android:layout_height="50dip" android:autoStart="true" android:background="#00FF00" android:flipInterval="3000" android:inAnimation="@animator/anim_in" android:outAnimation="@animator/anim_out" /> ...
同ViewFlipper,AdapterViewFlipper默認(rèn)是無(wú)動(dòng)畫(huà),這里通過(guò)inAnimation、outAnimation配置來(lái)子View進(jìn)入和移出動(dòng)畫(huà)(注意這里只能配置單一的ObjectAnimator屬性動(dòng)畫(huà)),這里設(shè)置了一個(gè)自動(dòng)播放動(dòng)畫(huà)間隔(android:flipInterval)3000毫秒,因?yàn)锳dapterViewFlipper默認(rèn)間隔是10000毫秒,android:autoStart 同ViewFlipper設(shè)置動(dòng)畫(huà)是否自動(dòng)播放,android:animateFirstView在AdapterViewFlipper設(shè)置是無(wú)效的。
這里AdapterViewFlipper因?yàn)槔^承自AdapterViewAnimator所以它也有android:loopViews(設(shè)置循環(huán)到最后一個(gè)組件后是否自動(dòng)“轉(zhuǎn)頭”到第一個(gè)組件)配置,但是,AdapterViewFlipper設(shè)置這個(gè)屬性無(wú)效,源碼解釋為視圖翻轉(zhuǎn)器應(yīng)該循環(huán)瀏覽視圖(在AdapterViewFlipper構(gòu)造函數(shù)中將loopViews設(shè)置了true)
AdapterViewFlipper同ViewFlipper可以通過(guò)代碼設(shè)置上述配置(不再列舉),也可以通過(guò)代碼來(lái)控制播放,具體api如下:
startFlipping() :開(kāi)始播放
stopFlipping() : 停止播放
inAnimation動(dòng)畫(huà)配置如下文件(animator/anim_in.xml):
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:propertyName="translationY" android:valueFrom="150" android:valueTo="0" />
這里屬性動(dòng)畫(huà)存放在animator目錄下。
outAnimation動(dòng)畫(huà)配置如下文件(animator/anim_out.xml):
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:propertyName="translationY" android:valueFrom="0" android:valueTo="-150"/>
這里的valueFrom、valueTo是移動(dòng)距離(像素),如想適配,可使用代碼創(chuàng)建屬性動(dòng)畫(huà)計(jì)算View移動(dòng)的精確距離。
AdapterViewFlipper因?yàn)槔^承了AdapterView,所以需要通過(guò)代碼設(shè)置一個(gè)Adapter展現(xiàn)效果,數(shù)據(jù)適配器如下:
public class ViewFlipperAdapter extends BaseAdapter { private Context context; private List<String> data; public ViewFlipperAdapter(Context context, List<String> data) { this.context = context; this.data = data; } @Override public int getCount() { return data == null ? 0 : data.size(); } @Override public Object getItem(int position) { return data == null ? null : data.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view; ViewHolder viewHolder; if (convertView == null) { view = LayoutInflater.from(context).inflate(R.layout.item_view, parent,false); viewHolder = new ViewHolder(view); view.setTag(viewHolder); } else { view = convertView; viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.tv_item.setText(data.get(position)); return view; } static class ViewHolder { public TextView tv_item; public ViewHolder(View view) { this.tv_item = view.findViewById(R.id.tv_item); } } }
這里使用ViewHolder做了數(shù)據(jù)適配器View緩存處理,效率更高。
這里的每個(gè)item布局(item_view)如下:
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tv_item" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:textSize="20sp" android:textStyle="bold" />
最后設(shè)置數(shù)據(jù)適配器到AdapterViewFlipper上即可:
... AdapterViewFlipper avf_view = (AdapterViewFlipper) findViewById(R.id.avf_view); List<String> data = new ArrayList<>(); for (int i = 0; i < 10000; i++) { data.add("這是第" + i + "條消息"); } ViewFlipperAdapter viewFlipperAdapter = new ViewFlipperAdapter(this, data); //也可通過(guò)代碼設(shè)置動(dòng)畫(huà) //avf_view.setInAnimation(ObjectAnimator.ofFloat(avf_view, View.TRANSLATION_Y,150.0f,0.0f)); //avf_view.setOutAnimation(ObjectAnimator.ofFloat(avf_view, View.TRANSLATION_Y,0.0f,-150.0f)); avf_view.setAdapter(viewFlipperAdapter); ...
這里直接構(gòu)造了10000條數(shù)據(jù),因?yàn)橛辛藬?shù)據(jù)適配器,運(yùn)行很輕松。
顯示效果與ViewFlipper例子中基本一致,因?yàn)锳dapterViewFlipper只能設(shè)置單一屬性動(dòng)畫(huà),所以此處沒(méi)有漸變動(dòng)畫(huà),只有位移動(dòng)畫(huà)。
內(nèi)存使用情況如下:
AdapterViewFlipper繼承了AdapterView,所以同ListView,也可以設(shè)置setOnItemClickListener來(lái)監(jiān)聽(tīng)每個(gè)Item的點(diǎn)擊事件,當(dāng)然也可以在數(shù)據(jù)適配中為每一個(gè)Item設(shè)置點(diǎn)擊事件。這里如果setOnItemClickListener設(shè)置每個(gè)Item的點(diǎn)擊事件,默認(rèn)是不回調(diào)的,因?yàn)锳dapterViewFlipper父類AdapterViewAnimator中重寫(xiě)了onTouchEvent函數(shù),但是在MotionEvent.ACTION_DOWN時(shí)返回值一直是false,導(dǎo)致onTouchEvent函數(shù)中的MotionEvent.ACTION_UP,無(wú)法回調(diào),從而無(wú)法回調(diào)OnItemClickListener,因此要想使回調(diào)生效,只需重寫(xiě)onTouchEvent函數(shù),并返回true即可:
public class MyAdapterViewFlipper extends AdapterViewFlipper { public MyAdapterViewFlipper(Context context) { super(context); } public MyAdapterViewFlipper(Context context, AttributeSet attrs) { super(context, attrs); } public MyAdapterViewFlipper(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public MyAdapterViewFlipper(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public boolean onTouchEvent(MotionEvent ev) { super.onTouchEvent(ev); return true; } }
代碼中可以使用MyAdapterViewFlipper,這樣設(shè)置setOnItemClickListener就可以正?;卣{(diào)了。
Android ViewFlipper、AdapterViewFlipper對(duì)比
復(fù)用性
ViewFlipper中的子view只能在xml中提前寫(xiě)好,或者在代碼中通過(guò) addView 的形式添加,這種形式不具有復(fù)用性質(zhì),只能處理較少的數(shù)據(jù)。
AdapterViewFlipper 因?yàn)橛袛?shù)據(jù)適配器,所以具有復(fù)用屬性,可以處理大量的數(shù)據(jù)。
動(dòng)畫(huà)效果
ViewFlipper在設(shè)置動(dòng)畫(huà)時(shí)接收的是Animation——補(bǔ)間動(dòng)畫(huà),可以是單一動(dòng)畫(huà)效果,也可以是動(dòng)畫(huà)集合。
AdapterViewFlipper 在設(shè)置動(dòng)畫(huà)的時(shí)候接收的是 ObjectAnimator——屬性動(dòng)畫(huà),而且只能是單一動(dòng)畫(huà),不能使用動(dòng)畫(huà)集合。
屬性配置
ViewFlipper的默認(rèn)Interval為3000ms(3秒);
AdapterViewFlipper的默認(rèn)Interval為10000ms(10秒);
ViewFlipper只有1條數(shù)據(jù)也執(zhí)行動(dòng)畫(huà),AdapterViewFlipper只有1條數(shù)據(jù)時(shí)不會(huì)執(zhí)行動(dòng)畫(huà);
AdapterViewFlipper比ViewFlipper多一個(gè)android:loopViews配置,但是AdapterViewFlipper設(shè)置此屬性無(wú)效;
AdapterViewFlipper中設(shè)置android:animateFirstView是無(wú)效的,在ViewFlipper中設(shè)置有效;
總結(jié)
到此這篇關(guān)于Android中ViewFlipper和AdapterViewFlipper使用的文章就介紹到這了,更多相關(guān)Android ViewFlipper和AdapterViewFlipper使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android 基于MediatorLiveData實(shí)現(xiàn)紅點(diǎn)的統(tǒng)一管理
這篇文章主要介紹了Android 基于MediatorLiveData實(shí)現(xiàn)紅點(diǎn)的統(tǒng)一管理,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下2021-04-04Android編程實(shí)現(xiàn)獲取系統(tǒng)內(nèi)存、CPU使用率及狀態(tài)欄高度的方法示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)獲取系統(tǒng)內(nèi)存、CPU使用率及狀態(tài)欄高度的方法,涉及Android基于自定義類實(shí)現(xiàn)針對(duì)系統(tǒng)硬件信息的相關(guān)獲取操作技巧,需要的朋友可以參考下2017-08-08Android IntentService詳解及使用實(shí)例
這篇文章主要介紹了Android IntentService詳解及使用實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03MT6589平臺(tái)通話錄音時(shí)播放提示音給對(duì)方功能的具體實(shí)現(xiàn)
MT6589平臺(tái)通話錄音時(shí)如何播放提示音給對(duì)方,可以通過(guò)修改以下文件即可,希望對(duì)你有所幫助2013-06-06Android ListView數(shù)據(jù)的分批顯示功能
本文通過(guò)實(shí)例代碼給大家分享了Android ListView數(shù)據(jù)的分批顯示功能,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友參考下吧2017-04-04Android 5.0最應(yīng)該實(shí)現(xiàn)的8個(gè)期望
毫無(wú)疑問(wèn),Android 5 將是令人興奮的操作系統(tǒng),因?yàn)?Android4.0 至 4.4 版本之間并沒(méi)有顯著的差異,顯然谷歌會(huì)在 5.0 版本中進(jìn)行一些較大幅度的革新2016-01-01