日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > > 充電吧
[導(dǎo)讀]在很多App上我們經(jīng)常看到這些效果:淘寶首頁自動(dòng)滾動(dòng)的圖片展示效果支付寶應(yīng)用第一次啟動(dòng)啟動(dòng)的用戶引導(dǎo)畫面要實(shí)現(xiàn)這些效果,有些控件可以幫助我們:1. ViewPager2. ViewFlipper3.

在很多App上我們經(jīng)??吹竭@些效果:

淘寶首頁自動(dòng)滾動(dòng)的圖片展示效果支付寶應(yīng)用第一次啟動(dòng)啟動(dòng)的用戶引導(dǎo)畫面


要實(shí)現(xiàn)這些效果,有些控件可以幫助我們:

1. ViewPager

2. ViewFlipper

3. Fragment


好吧,我最終選擇了ViewFlipper,因?yàn)樗氖褂米罡蓜徘逅ㄍ锩娣艓讉€(gè)View就行了),而且還支持自動(dòng)播放。


不過,為了實(shí)現(xiàn)上面兩個(gè)效果,還得解決來年兩個(gè)問題:

1. 如何在ViewFlipper滾動(dòng)的時(shí)候,獲得當(dāng)前展示的child id?

2. 和ViewPager原生支持觸摸滑動(dòng)翻頁不同,ViewFlipper需要自己監(jiān)聽手勢(shì)來解決。


問題1:其實(shí),我挺奇怪的,Google既然為ViewAnimation做了個(gè)ViewFlipper的子類來支持自動(dòng)翻滾,怎么不給它添加一個(gè)listener以監(jiān)聽翻滾事件呢?

好吧,既然google不給,那就自己加。首先看ViewFlipper的源碼(


/*
?*?Copyright?(C)?2006?The?Android?Open?Source?Project
?*
?*?Licensed?under?the?Apache?License,?Version?2.0?(the?"License");
?*?you?may?not?use?this?file?except?in?compliance?with?the?License.
?*?You?may?obtain?a?copy?of?the?License?at
?*
?*??????http://www.apache.org/licenses/LICENSE-2.0
?*
?*?Unless?required?by?applicable?law?or?agreed?to?in?writing,?software
?*?distributed?under?the?License?is?distributed?on?an?"AS?IS"?BASIS,
?*?WITHOUT?WARRANTIES?OR?CONDITIONS?OF?ANY?KIND,?either?express?or?implied.
?*?See?the?License?for?the?specific?language?governing?permissions?and
?*?limitations?under?the?License.
?*/

package?android.widget;

import?android.content.BroadcastReceiver;
import?android.content.Context;
import?android.content.Intent;
import?android.content.IntentFilter;
import?android.content.res.TypedArray;
import?android.os.Handler;
import?android.os.Message;
import?android.util.AttributeSet;
import?android.util.Log;
import?android.view.accessibility.AccessibilityEvent;
import?android.view.accessibility.AccessibilityNodeInfo;
import?android.widget.RemoteViews.RemoteView;

/**
?*?Simple?{@link?ViewAnimator}?that?will?animate?between?two?or?more?views
?*?that?have?been?added?to?it.??Only?one?child?is?shown?at?a?time.??If
?*?requested,?can?automatically?flip?between?each?child?at?a?regular?interval.
?*
?*?@attr?ref?android.R.styleable#ViewFlipper_flipInterval
?*?@attr?ref?android.R.styleable#ViewFlipper_autoStart
?*/
@RemoteView
public?class?ViewFlipper?extends?ViewAnimator?{
????private?static?final?String?TAG?=?"ViewFlipper";
????private?static?final?boolean?LOGD?=?false;

????private?static?final?int?DEFAULT_INTERVAL?=?3000;

????private?int?mFlipInterval?=?DEFAULT_INTERVAL;
????private?boolean?mAutoStart?=?false;

????private?boolean?mRunning?=?false;
????private?boolean?mStarted?=?false;
????private?boolean?mVisible?=?false;
????private?boolean?mUserPresent?=?true;

????public?ViewFlipper(Context?context)?{
????????super(context);
????}

????public?ViewFlipper(Context?context,?AttributeSet?attrs)?{
????????super(context,?attrs);

????????TypedArray?a?=?context.obtainStyledAttributes(attrs,
????????????????com.android.internal.R.styleable.ViewFlipper);
????????mFlipInterval?=?a.getInt(
????????????????com.android.internal.R.styleable.ViewFlipper_flipInterval,?DEFAULT_INTERVAL);
????????mAutoStart?=?a.getBoolean(
????????????????com.android.internal.R.styleable.ViewFlipper_autoStart,?false);
????????a.recycle();
????}

????private?final?BroadcastReceiver?mReceiver?=?new?BroadcastReceiver()?{
????????@Override
????????public?void?onReceive(Context?context,?Intent?intent)?{
????????????final?String?action?=?intent.getAction();
????????????if?(Intent.ACTION_SCREEN_OFF.equals(action))?{
????????????????mUserPresent?=?false;
????????????????updateRunning();
????????????}?else?if?(Intent.ACTION_USER_PRESENT.equals(action))?{
????????????????mUserPresent?=?true;
????????????????updateRunning(false);
????????????}
????????}
????};

????@Override
????protected?void?onAttachedToWindow()?{
????????super.onAttachedToWindow();

????????//?Listen?for?broadcasts?related?to?user-presence
????????final?IntentFilter?filter?=?new?IntentFilter();
????????filter.addAction(Intent.ACTION_SCREEN_OFF);
????????filter.addAction(Intent.ACTION_USER_PRESENT);
????????getContext().registerReceiver(mReceiver,?filter);

????????if?(mAutoStart)?{
????????????//?Automatically?start?when?requested
????????????startFlipping();
????????}
????}

????@Override
????protected?void?onDetachedFromWindow()?{
????????super.onDetachedFromWindow();
????????mVisible?=?false;

????????getContext().unregisterReceiver(mReceiver);
????????updateRunning();
????}

????@Override
????protected?void?onWindowVisibilityChanged(int?visibility)?{
????????super.onWindowVisibilityChanged(visibility);
????????mVisible?=?visibility?==?VISIBLE;
????????updateRunning(false);
????}

????/**
?????*?How?long?to?wait?before?flipping?to?the?next?view
?????*
?????*?@param?milliseconds
?????*????????????time?in?milliseconds
?????*/
????@android.view.RemotableViewMethod
????public?void?setFlipInterval(int?milliseconds)?{
????????mFlipInterval?=?milliseconds;
????}

????/**
?????*?Start?a?timer?to?cycle?through?child?views
?????*/
????public?void?startFlipping()?{
????????mStarted?=?true;
????????updateRunning();
????}

????/**
?????*?No?more?flips
?????*/
????public?void?stopFlipping()?{
????????mStarted?=?false;
????????updateRunning();
????}

????@Override
????public?void?onInitializeAccessibilityEvent(AccessibilityEvent?event)?{
????????super.onInitializeAccessibilityEvent(event);
????????event.setClassName(ViewFlipper.class.getName());
????}

????@Override
????public?void?onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo?info)?{
????????super.onInitializeAccessibilityNodeInfo(info);
????????info.setClassName(ViewFlipper.class.getName());
????}

????/**
?????*?Internal?method?to?start?or?stop?dispatching?flip?{@link?Message}?based
?????*?on?{@link?#mRunning}?and?{@link?#mVisible}?state.
?????*/
????private?void?updateRunning()?{
????????updateRunning(true);
????}

????/**
?????*?Internal?method?to?start?or?stop?dispatching?flip?{@link?Message}?based
?????*?on?{@link?#mRunning}?and?{@link?#mVisible}?state.
?????*
?????*?@param?flipNow?Determines?whether?or?not?to?execute?the?animation?now,?in
?????*????????????addition?to?queuing?future?flips.?If?omitted,?defaults?to
?????*????????????true.
?????*/
????private?void?updateRunning(boolean?flipNow)?{
????????boolean?running?=?mVisible?&&?mStarted?&&?mUserPresent;
????????if?(running?!=?mRunning)?{
????????????if?(running)?{
????????????????showOnly(mWhichChild,?flipNow);
????????????????Message?msg?=?mHandler.obtainMessage(FLIP_MSG);
????????????????mHandler.sendMessageDelayed(msg,?mFlipInterval);
????????????}?else?{
????????????????mHandler.removeMessages(FLIP_MSG);
????????????}
????????????mRunning?=?running;
????????}
????????if?(LOGD)?{
????????????Log.d(TAG,?"updateRunning()?mVisible="?+?mVisible?+?",?mStarted="?+?mStarted
????????????????????+?",?mUserPresent="?+?mUserPresent?+?",?mRunning="?+?mRunning);
????????}
????}

????/**
?????*?Returns?true?if?the?child?views?are?flipping.
?????*/
????public?boolean?isFlipping()?{
????????return?mStarted;
????}

????/**
?????*?Set?if?this?view?automatically?calls?{@link?#startFlipping()}?when?it
?????*?becomes?attached?to?a?window.
?????*/
????public?void?setAutoStart(boolean?autoStart)?{
????????mAutoStart?=?autoStart;
????}

????/**
?????*?Returns?true?if?this?view?automatically?calls?{@link?#startFlipping()}
?????*?when?it?becomes?attached?to?a?window.
?????*/
????public?boolean?isAutoStart()?{
????????return?mAutoStart;
????}

????private?final?int?FLIP_MSG?=?1;

????private?final?Handler?mHandler?=?new?Handler()?{
????????@Override
????????public?void?handleMessage(Message?msg)?{
????????????if?(msg.what?==?FLIP_MSG)?{
????????????????if?(mRunning)?{
????????????????????showNext();
????????????????????msg?=?obtainMessage(FLIP_MSG);
????????????????????sendMessageDelayed(msg,?mFlipInterval);
????????????????}
????????????}
????????}
????};
}


代碼還是挺簡(jiǎn)單易懂的,就是用了一個(gè)Handler來定時(shí)調(diào)用showNext()。


可惜,mHandler成員是private+final的,我們無法改動(dòng)它了。

不過,既然ViewFlipper不是一個(gè)final類,那就好辦,自定義類繼承ViewFlipper,重載showNext()函數(shù):


package?com.example.viewflipper;

import?android.widget.ViewFlipper;

/**
?*?Created?by?ray?on?7/4/13.
?*/
public?class?MyViewFilpper?extends?ViewFlipper?{

????private?OnDisplayChagnedListener?mListener;

????public?MyViewFilpper(android.content.Context?context)?{
????????super(context);
????}

????public?MyViewFilpper(android.content.Context?context,?android.util.AttributeSet?attrs)?{
????????super(context,?attrs);
????}

????public?void?setOnDisplayChagnedListener(OnDisplayChagnedListener?listener)?{
????????if?(mListener?!=?listener)?{
????????????this.mListener?=?listener;
????????}
????}

????@Override
????public?void?showNext()?{
????????super.showNext();

????????if(mListener?!=?null){
????????????mListener.OnDisplayChildChanging(this,?super.getDisplayedChild());
????????}
????}

????@Override
????public?void?showPrevious()?{
????????super.showPrevious();

????????if(mListener?!=?null){
????????????mListener.OnDisplayChildChanging(this,?super.getDisplayedChild());
????????}
????}

????public?interface?OnDisplayChagnedListener?{
????????void?OnDisplayChildChanging(ViewFlipper?view,?int?index);
????}
}



問題2,就比較好解決了,OnTouchListener + GestureDetector 監(jiān)聽flipper事件,這里就不貼代碼了。


好吧,這樣基本問題都被解決了,為了讓效果好一點(diǎn),又給ViewFlipper加上了進(jìn)入動(dòng)畫和離開動(dòng)畫。


好吧,下方的1,2,3有點(diǎn)難看,大家湊合下。


當(dāng)目前為止,本人對(duì)效果還算滿意,但是,還存在兩個(gè)問題:

1. 沒有處理GestureDetectorListener的onScroll函數(shù),也就是說,在用戶的手指離開屏幕前,不會(huì)有滾動(dòng)效果。

2. 因?yàn)槭峭℅estureDetector是通過TouchListener工作的,作為一個(gè)容器,如果內(nèi)部元素消耗掉了touch事件,則touchlistener無法工作,手勢(shì)的監(jiān)聽自然也無從談起。不過,僅僅是應(yīng)付圖片瀏覽的話,還是有辦法解決的:

a. 對(duì)于用戶引導(dǎo)這樣的場(chǎng)景,圖片展示是不會(huì)消耗touch消息的。

b. 而淘寶首頁的圖片動(dòng)態(tài)則不同,在用戶點(diǎn)擊圖片的時(shí)候,把頁面轉(zhuǎn)到商品的展示頁面,這種情況下,一般會(huì)考慮使用ImageButton控件來處理Click事件,這樣就導(dǎo)致手勢(shì)無法監(jiān)聽。解決方案是,仍舊使用ImageVIew控件,但是在GestureListener的OnSingleTapUp事件上,獲取當(dāng)前展示的頁面,然后根據(jù)頁面信息轉(zhuǎn)到商品展示頁面。

但是,如果是一些比較復(fù)雜的情況,就比較難處理,雖然通過重載onInterceptTouchEvent函數(shù),父容器也能監(jiān)聽所有由子控件消耗的消息,但是也可能存在一些邏輯問題:例如在ViewFlipper容器內(nèi)包含了一個(gè)Gallary控件,那scroll消息應(yīng)該由哪個(gè)控件來處理,亦或都處理?這就是個(gè)比較費(fèi)腦筋的問題了,設(shè)計(jì)UI的時(shí)候,可以考慮設(shè)計(jì)的簡(jiǎn)單些。


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉