麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 系統(tǒng) > Android > 正文

Android可自定義神奇動(dòng)效的卡片切換視圖實(shí)例

2019-10-21 21:25:32
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

前言

面對(duì)眾多卡片層疊效果,我們的產(chǎn)品童鞋也突發(fā)奇想,搞出了另一種卡片層疊切換展示的交互,而且產(chǎn)品狗們居然要求多做幾種動(dòng)效給他們看,好讓他們選擇,這簡(jiǎn)直就是要搞事情啊,what are you 弄啥咧?!

“哥哥我做不到啊.....啊.....呸”,做為一名有節(jié)操的程序猿,自然是不能說(shuō)出這么沒(méi)有出息的話,哥就滿(mǎn)足你們,于是,出了個(gè)可自定義動(dòng)效的卡片切換視圖,效果如下所示

Android,動(dòng)效,卡片切換視圖

思路

首先,要展示出卡片層疊的視覺(jué)效果。在這里,我們通過(guò)方塊的縮放大小差異以及在Y方向上的位置差異,來(lái)展現(xiàn)這種視覺(jué)效果。

其次,要能夠方便的定義卡片視圖內(nèi)容。我們通過(guò)都很熟悉的設(shè)置Adapter的方式來(lái)構(gòu)建內(nèi)容視圖。

最后,要能夠自定義動(dòng)效。我們通過(guò)定義一個(gè)由0到1的ValueAnimator,即每個(gè)動(dòng)畫(huà)的過(guò)程,其實(shí)就是該ValueAnimator在一個(gè)動(dòng)畫(huà)周期內(nèi),從0變化到1的過(guò)程,0表示動(dòng)畫(huà)剛開(kāi)始,1表示動(dòng)畫(huà)結(jié)束了,0.5則表示這一輪動(dòng)畫(huà)已經(jīng)執(zhí)行到了一半。這樣,通過(guò)轉(zhuǎn)換器以及插值器,我們就可以根據(jù)ValueAnimator實(shí)時(shí)的值,來(lái)設(shè)置當(dāng)前正在執(zhí)行動(dòng)畫(huà)的卡片應(yīng)該有的“樣子”。

總覽

我們給出三種基本的動(dòng)畫(huà)模式

/* * ANIM_TYPE_FRONT:被選中的卡片通過(guò)自定義動(dòng)效移至第一,其他的卡片通過(guò)通用動(dòng)效補(bǔ)位 * ANIM_TYPE_SWITCH:選中的卡片和第一張卡片互換位置,并都是自定義動(dòng)效 * ANIM_TYPE_FRONT_TO_LAST:第一張圖片通過(guò)自定義動(dòng)效移至最后,其他卡片通過(guò)通用動(dòng)效補(bǔ)位 */public static final int ANIM_TYPE_FRONT = 0, ANIM_TYPE_SWITCH = 1, ANIM_TYPE_FRONT_TO_LAST = 2;

并通過(guò)Helper類(lèi)來(lái)處理所有的動(dòng)畫(huà)邏輯,以及Adapter來(lái)生成卡片視圖

private CardAnimationHelper mAnimationHelper;private BaseAdapter mAdapter;

在onMeasure時(shí)根據(jù)卡片寬高比來(lái)設(shè)置卡片的尺寸,在此請(qǐng)注意,當(dāng)前情況下卡片寬度與整體容器寬度一致,后續(xù)通過(guò)自定義的方式,通過(guò)縮放來(lái)產(chǎn)生卡片的視覺(jué)效果。

private float mCardRatio = CARD_SIZE_RATIO;//寬高比:卡片高 / 卡片寬private int mCardWidth, mCardHeight;//卡片寬高@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  ...  if (mCardWidth == 0 || mCardHeight == 0) {    setCardSize(true);  }}/* * 根據(jù)卡片比例計(jì)算卡片寬高,并傳入Helper */private void setCardSize(boolean resetAdapter) {  mCardWidth = getMeasuredWidth();  mCardHeight = (int) (mCardWidth * mCardRatio);  mAnimationHelper.setCardSize(mCardWidth, mCardHeight);  mAnimationHelper.initAdapterView(mAdapter, resetAdapter);}

那么如此之后,自然Helper中就保存了視圖的主要數(shù)據(jù)與參數(shù)

//卡片列表private LinkedList<CardItem> mCards;//當(dāng)前正在向后以及向前移動(dòng)的卡片private CardItem mCardToBack, mCardToFront;//正在向后以及向前移動(dòng)卡片的位置private int mPositionToBack = 0, mPositionToFront = 0;//動(dòng)畫(huà)運(yùn)行的ValueAnimatorprivate ValueAnimator mValueAnimator;//當(dāng)前的動(dòng)畫(huà)系數(shù)private float mCurrentFraction = 1;...//以及一系列的轉(zhuǎn)換器與插值器

細(xì)節(jié)

那么,動(dòng)畫(huà)到底是如何實(shí)現(xiàn)的,以及如何自定義的呢,我們以通用動(dòng)畫(huà)為例,來(lái)看看動(dòng)畫(huà)的主要流程

首先,在ValueAnimator更新的時(shí)候,獲得當(dāng)前的動(dòng)畫(huà)系數(shù),依次來(lái)執(zhí)行動(dòng)畫(huà)

/** * ValueAnimator動(dòng)畫(huà)更新 */@Overridepublic void onAnimationUpdate(ValueAnimator animation) {  //獲取當(dāng)前動(dòng)畫(huà)系數(shù)  mCurrentFraction = (float) animation.getAnimatedValue();  //通過(guò)插值器獲取插值系數(shù)  fractionInterpolated = mAnimInterpolator.getInterpolation(mCurrentFraction);  doAnimationCommon(mCurrentFraction, fractionInterpolated);  ...}

接著,對(duì)需要執(zhí)行動(dòng)畫(huà)的卡片,執(zhí)行動(dòng)畫(huà),以ANIM_TYPE_FRONT動(dòng)畫(huà)模式為例,當(dāng)選中的卡片移動(dòng)到最前的時(shí)候,原來(lái)在這張卡片之前的所有卡片,都要向后移動(dòng)一位,來(lái)留出第一個(gè)的位置

/** * 執(zhí)行通用動(dòng)畫(huà) */private void doAnimationCommon(float fraction, float fractionInterpolated) {  //如果當(dāng)前動(dòng)畫(huà)模式為選中的卡片移到最前  if (mAnimType == InfiniteCardView.ANIM_TYPE_FRONT) {    //則遍歷在選中卡片之前的卡片    for (int i = 0; i < mPositionToFront; i++) {      CardItem card = mCards.get(i);      //對(duì)卡片執(zhí)行動(dòng)畫(huà),從當(dāng)前位置移動(dòng)到后一個(gè)位置      doAnimationCommonView(card.view, fraction, fractionInterpolated, i, i + 1);      ...    }  }...}

最后,通過(guò)轉(zhuǎn)換器,對(duì)卡片進(jìn)行自定義動(dòng)畫(huà)處理

/** * 對(duì)視圖執(zhí)行通用動(dòng)畫(huà) * @param view         卡片視圖 * @param fromPosition     從該位置 * @param toPosition      移動(dòng)到該位置 */private void doAnimationCommonView(View view, float fraction, float fractionInterpolated, int    fromPosition, int toPosition) {  //通用轉(zhuǎn)換器轉(zhuǎn)換動(dòng)畫(huà)  mTransformerCommon.transformAnimation(view, fraction, mCardWidth,      mCardHeight, fromPosition, toPosition);  if (mAnimInterpolator != null) {    //通用轉(zhuǎn)換器轉(zhuǎn)換插值動(dòng)畫(huà)    mTransformerCommon.transformInterpolatedAnimation(view, fractionInterpolated,            mCardWidth,mCardHeight, fromPosition, toPosition);  }}

而轉(zhuǎn)換器的具體實(shí)現(xiàn)則以DefaultCommonTransformer為例

@Overridepublic void transformAnimation(View view, float fraction, int cardWidth, int cardHeight, int fromPosition, int toPosition) {  //需要跨越的卡片數(shù)量  int positionCount = fromPosition - toPosition;  //以0.8做為第一張的縮放尺寸,每向后一張縮小0.1  //(0.8f - 0.1f * fromPosition) = 當(dāng)前位置的縮放尺寸  //(0.1f * fraction * positionCount) = 移動(dòng)過(guò)程中需要改變的縮放尺寸  float scale = (0.8f - 0.1f * fromPosition) + (0.1f * fraction * positionCount);  ViewHelper.setScaleX(view, scale);  ViewHelper.setScaleY(view, scale);  //在Y方向的偏移量,每向后一張,向上偏移卡片寬度的0.02  //-cardHeight * (0.8f - scale) * 0.5f 對(duì)卡片做整體居中處理  ViewHelper.setTranslationY(view, -cardHeight * (0.8f - scale) * 0.5f - cardWidth * (0.02f *     fromPosition - 0.02f * fraction * positionCount));}

對(duì)于向第一位移動(dòng)的選中卡片,也是同理,只不過(guò)是根據(jù)該卡片對(duì)應(yīng)的轉(zhuǎn)換器來(lái)進(jìn)行自定義動(dòng)畫(huà)的轉(zhuǎn)換。

最后的效果,就像演示圖中第一次點(diǎn)擊,圖片向前翻轉(zhuǎn)到第一位的效果一樣。

對(duì)于產(chǎn)品狗突如其來(lái)的想法,咱們程序猿不善于口水仗的,就只能用代碼來(lái)讓他們來(lái)服氣了。畢竟,大家還都是伐木累嘛,哈哈。

當(dāng)實(shí)現(xiàn)某個(gè)東西遇到困難時(shí),不妨想想Android系統(tǒng)自身的一些實(shí)現(xiàn)方式,比如參考ListView的Adapter,ViewPager定義翻頁(yè)動(dòng)畫(huà)的Transformer等等,總會(huì)有意想不到的啟發(fā)。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)VEVB武林網(wǎng)的支持。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到Android開(kāi)發(fā)頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 黄视频网站免费 | 精品国产一区二区久久 | 精品视频 久久久 | 天堂成人国产精品一区 | 欧美一级特级 | a视频网站| caoporn国产一区二区 | 中文字幕涩涩久久乱小说 | 日韩欧美色综合 | 午夜噜噜噜 | 亚洲午夜在线观看 | 美女黄色毛片免费看 | 欧美一级淫片a免费播放口 91九色蝌蚪国产 | 亚洲综合网站 | 色网站在线免费观看 | 久啪视频 | 国产精品99久久久久久董美香 | 欧美成年人在线视频 | 日本搞逼视频 | 国产69精品久久久久久久久久 | 最新在线中文字幕 | 天天干天天碰 | chinese乱子伦xxxx国语对白 | 中文亚洲视频 | 最新在线中文字幕 | 综合网日日天干夜夜久久 | 午夜小视频免费观看 | 日日狠狠久久偷偷四色综合免费 | 视频一区二区三区免费观看 | 国产美女一区二区在线观看 | 久久av喷吹av高潮av懂色 | 中文字幕综合在线观看 | 玩偶姐姐在线观看免费 | 久久色伦理资源站 | 92看片淫黄大片欧美看国产片 | 成人在线视频播放 | 一级爱爱 | av在线播放亚洲 | 精品久久久久久中文字幕 | 黄色大片免费网站 | av在线播放观看 |