亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android可自定義神奇動效的卡片切換視圖實例

2019-10-21 21:25:32
字體:
來源:轉載
供稿:網友

前言

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

“哥哥我做不到啊.....啊.....呸”,做為一名有節操的程序猿,自然是不能說出這么沒有出息的話,哥就滿足你們,于是,出了個可自定義動效的卡片切換視圖,效果如下所示

Android,動效,卡片切換視圖

思路

首先,要展示出卡片層疊的視覺效果。在這里,我們通過方塊的縮放大小差異以及在Y方向上的位置差異,來展現這種視覺效果。

其次,要能夠方便的定義卡片視圖內容。我們通過都很熟悉的設置Adapter的方式來構建內容視圖。

最后,要能夠自定義動效。我們通過定義一個由0到1的ValueAnimator,即每個動畫的過程,其實就是該ValueAnimator在一個動畫周期內,從0變化到1的過程,0表示動畫剛開始,1表示動畫結束了,0.5則表示這一輪動畫已經執行到了一半。這樣,通過轉換器以及插值器,我們就可以根據ValueAnimator實時的值,來設置當前正在執行動畫的卡片應該有的“樣子”。

總覽

我們給出三種基本的動畫模式

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

并通過Helper類來處理所有的動畫邏輯,以及Adapter來生成卡片視圖

private CardAnimationHelper mAnimationHelper;private BaseAdapter mAdapter;

在onMeasure時根據卡片寬高比來設置卡片的尺寸,在此請注意,當前情況下卡片寬度與整體容器寬度一致,后續通過自定義的方式,通過縮放來產生卡片的視覺效果。

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

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

//卡片列表private LinkedList<CardItem> mCards;//當前正在向后以及向前移動的卡片private CardItem mCardToBack, mCardToFront;//正在向后以及向前移動卡片的位置private int mPositionToBack = 0, mPositionToFront = 0;//動畫運行的ValueAnimatorprivate ValueAnimator mValueAnimator;//當前的動畫系數private float mCurrentFraction = 1;...//以及一系列的轉換器與插值器

細節

那么,動畫到底是如何實現的,以及如何自定義的呢,我們以通用動畫為例,來看看動畫的主要流程

首先,在ValueAnimator更新的時候,獲得當前的動畫系數,依次來執行動畫

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

接著,對需要執行動畫的卡片,執行動畫,以ANIM_TYPE_FRONT動畫模式為例,當選中的卡片移動到最前的時候,原來在這張卡片之前的所有卡片,都要向后移動一位,來留出第一個的位置

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

最后,通過轉換器,對卡片進行自定義動畫處理

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

而轉換器的具體實現則以DefaultCommonTransformer為例

@Overridepublic void transformAnimation(View view, float fraction, int cardWidth, int cardHeight, int fromPosition, int toPosition) {  //需要跨越的卡片數量  int positionCount = fromPosition - toPosition;  //以0.8做為第一張的縮放尺寸,每向后一張縮小0.1  //(0.8f - 0.1f * fromPosition) = 當前位置的縮放尺寸  //(0.1f * fraction * positionCount) = 移動過程中需要改變的縮放尺寸  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 對卡片做整體居中處理  ViewHelper.setTranslationY(view, -cardHeight * (0.8f - scale) * 0.5f - cardWidth * (0.02f *     fromPosition - 0.02f * fraction * positionCount));}

對于向第一位移動的選中卡片,也是同理,只不過是根據該卡片對應的轉換器來進行自定義動畫的轉換。

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

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

當實現某個東西遇到困難時,不妨想想Android系統自身的一些實現方式,比如參考ListView的Adapter,ViewPager定義翻頁動畫的Transformer等等,總會有意想不到的啟發。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人a视频在线观看| 久久久国产精品x99av| 欧美成人免费va影院高清| 欧美激情一区二区三区高清视频| 欧美日韩在线视频首页| 国产ts一区二区| 成人黄色片网站| 91在线无精精品一区二区| 欧美午夜宅男影院在线观看| 欧美成人性色生活仑片| 91久久精品美女高潮| 日本国产精品视频| 国产综合久久久久| 久久免费成人精品视频| 57pao成人国产永久免费| 欧美日韩国产综合视频在线观看中文| 精品中文字幕在线观看| 国外视频精品毛片| 久久久电影免费观看完整版| 日韩中文字幕视频| 日韩av在线网页| 午夜精品久久久久久久久久久久久| 日本aⅴ大伊香蕉精品视频| 国产精品视频色| 亚洲无av在线中文字幕| 91国产视频在线| 亚洲国产精品人人爽夜夜爽| 国产mv免费观看入口亚洲| 久久网福利资源网站| 日韩中文字幕第一页| 国产精品久久婷婷六月丁香| 久久精品在线播放| 最新的欧美黄色| 97香蕉久久超级碰碰高清版| 欧美另类极品videosbest最新版本| 北条麻妃99精品青青久久| 亚洲欧美三级在线| 久久亚洲国产精品成人av秋霞| 国产一区二区精品丝袜| 夜夜嗨av一区二区三区免费区| 奇米一区二区三区四区久久| 日韩久久午夜影院| 91九色视频导航| 欧美视频在线观看免费网址| 2019中文字幕在线免费观看| 亚洲理论电影网| 97欧美精品一区二区三区| 91精品国产一区| 中文字幕欧美视频在线| 成人免费视频97| 亚洲人a成www在线影院| 中文字幕日韩视频| 欧美成人免费在线观看| 国内精品免费午夜毛片| 在线观看欧美日韩| 一本色道久久综合亚洲精品小说| 精品亚洲国产成av人片传媒| 91老司机精品视频| 国产精品电影网| 国产视频精品在线| 日韩精品一区二区三区第95| 日韩av网站导航| 亚洲视频免费一区| 久久综合伊人77777| 国产日韩欧美在线视频观看| 久久成人免费视频| 自拍偷拍亚洲区| 国产91精品久久久久| 懂色aⅴ精品一区二区三区蜜月| 一区二区三区动漫| 欧美日韩性视频在线| 亚洲欧美日韩一区二区在线| 国产精品国模在线| 亚洲一区二区三区乱码aⅴ| 国产欧美 在线欧美| yw.139尤物在线精品视频| 在线播放国产一区中文字幕剧情欧美| 北条麻妃久久精品| 91免费精品国偷自产在线| 宅男66日本亚洲欧美视频| 福利一区福利二区微拍刺激| 亚洲欧美变态国产另类| 欧美亚洲日本网站| 91av成人在线| 亚洲人a成www在线影院| 日韩在线一区二区三区免费视频| 欧美精品中文字幕一区| 国产精品久久99久久| 狠狠做深爱婷婷久久综合一区| 亚洲成人精品视频在线观看| 久久久久久91| 欧美性xxxxxxx| 国产精品露脸自拍| 中文字幕在线看视频国产欧美在线看完整| 亚洲美女福利视频网站| 国产精品天天狠天天看| 亚洲精品美女在线观看| 久久av红桃一区二区小说| 久久久这里只有精品视频| 国产精品私拍pans大尺度在线| 国产亚洲精品一区二555| 国产成人福利夜色影视| 亚洲三级黄色在线观看| 日本精品久久久久久久| 色先锋久久影院av| 国产+成+人+亚洲欧洲| 欧美性视频网站| 日韩福利伦理影院免费| 精品久久在线播放| 成人国产精品一区| 国语自产精品视频在线看抢先版图片| 国产91精品视频在线观看| 国产69精品久久久久久| 久久九九热免费视频| 欧美视频在线观看免费网址| 亚洲一区二区久久久久久久| 激情成人在线视频| 久久手机精品视频| 一区二区三区黄色| 国产在线观看一区二区三区| 日韩免费不卡av| 日韩视频亚洲视频| 久久91超碰青草是什么| 欧美福利视频网站| 欧美日韩在线观看视频| 亚洲精品网站在线播放gif| 日韩激情av在线播放| 国产91在线高潮白浆在线观看| 精品久久久一区二区| 久久亚洲综合国产精品99麻豆精品福利| 精品女厕一区二区三区| 中文字幕日韩欧美在线视频| 欧美电影在线播放| 成人免费看吃奶视频网站| 尤物九九久久国产精品的特点| 欧美精品精品精品精品免费| 国产精品99久久久久久久久久久久| 久久久免费高清电视剧观看| 亚洲人av在线影院| 日本免费一区二区三区视频观看| 久久久久中文字幕| 国产精品久久久999| 久久精品国产成人精品| 亚洲国产小视频在线观看| 日本在线观看天堂男亚洲| 精品国产欧美一区二区三区成人| 久久人人爽人人爽人人片av高清| 一区三区二区视频| 亚洲欧美日韩国产中文专区| 日韩女优在线播放| 国外成人性视频| 久久精品国产亚洲7777| 欧美制服第一页| 91色视频在线导航| 精品国产一区二区三区久久狼黑人| 91伊人影院在线播放| 国产成人精品在线播放| 欧美成人精品激情在线观看| 欧美夜福利tv在线| 国产精品美腿一区在线看| 久久天天躁日日躁| 国产日韩欧美自拍| 亚洲国产美女久久久久| 97热在线精品视频在线观看|