日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
玩轉(zhuǎn)仿探探卡片式滑動效果

講起本篇博客講起本篇博客的歷史起源,估計有一段“歷史”了。的歷史起源,估計有一段“歷史”了。

成都創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務領域包括:網(wǎng)站建設、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務,滿足客戶于互聯(lián)網(wǎng)時代的阜新網(wǎng)站設計、移動媒體設計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡建設合作伙伴!

最早可以追溯到我試玩探探這個 APP 。***次進入軟件界面,就被這種通過卡片式滑動來選擇“喜歡/不喜歡”的設計所吸引了。當時就非常想通過自己來實現(xiàn)這種仿探探式的效果,然而卻沒什么思路。不過毋庸置疑的是,這種效果的原理肯定和 ListView / RecyclerView 類似,涉及到 Item View 的回收和重用,否則早就因為大量的 Item View 而 OOM 了。

再到后來,看到許多大神也推出了同樣仿探探效果的博客,從頭到尾閱讀下來,寫得通俗易懂,基本上沒什么問題。于是,實現(xiàn)仿探探效果的想法再次出現(xiàn)在腦海中。那么,還猶豫什么,趁熱來一發(fā)吧!就這么愉快地決定了。

首先面臨的問題就是關于實現(xiàn) View 上的考慮。毫無疑問。

RecyclerView 是***選擇!

RecyclerView 是***選擇!

RecyclerView 是***選擇!

重要的話講三遍!!!

究其原因,***,RecyclerView 是自帶 Item View 回收和重用功能的,就不需要我們考慮這個問題了;第二,RecyclerView 的布局方式是通過設置 LayoutManager 來實現(xiàn)的,這樣就充分地把布局和 RecyclerView “解耦”開來了。而 LayoutManager 是可以通過自定義的方式來實現(xiàn)的。這恰恰是我們想要的!!!再說一點,這也正是不選用 ListView 的原因之一。

下面,我們就開始動手了。帶你見證奇跡的時刻。

CardLayoutManager

創(chuàng)建 CardLayoutManager 并繼承自 RecyclerView.LayoutManager 。需要我們自己實現(xiàn) generateDefaultLayoutParams() 方法:

 
 
 
 
  1. @Override
  2. public RecyclerView.LayoutParams generateDefaultLayoutParams() {
  3.     return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

一般情況下,像上面這樣寫即可。

下面這個方法就是我們的重點了。 onLayoutChildren(final RecyclerView.Recycler recycler, RecyclerView.State state) 方法就是用來實現(xiàn) Item View 布局的:

  1. @Override
  2. public void onLayoutChildren(final RecyclerView.Recycler recycler, RecyclerView.State state) {
  3.     super.onLayoutChildren(recycler, state);
  4.     // 先移除所有view
  5.     removeAllViews();
  6.     // 在布局之前,將所有的子 View 先 Detach 掉,放入到 Scrap 緩存中
  7.     detachAndScrapAttachedViews(recycler);
  8.     int itemCount = getItemCount();
  9.     // 在這里,我們默認配置 CardConfig.DEFAULT_SHOW_ITEM = 3。即在屏幕上顯示的卡片數(shù)為3
  10.     // 當數(shù)據(jù)源個數(shù)大于***顯示數(shù)時
  11.     if (itemCount > CardConfig.DEFAULT_SHOW_ITEM) {
  12.         // 把數(shù)據(jù)源倒著循環(huán),這樣,第0個數(shù)據(jù)就在屏幕最上面了
  13.         for (int position = CardConfig.DEFAULT_SHOW_ITEM; position >= 0; position--) {
  14.             final View view = recycler.getViewForPosition(position);
  15.             // 將 Item View 加入到 RecyclerView 中
  16.             addView(view);
  17.             // 測量 Item View
  18.             measureChildWithMargins(view, 0, 0);
  19.             // getDecoratedMeasuredWidth(view) 可以得到 Item View 的寬度
  20.             // 所以 widthSpace 就是除了 Item View 剩余的值
  21.             int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
  22.             // 同理
  23.             int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);
  24.             // 將 Item View 放入 RecyclerView 中布局
  25.             // 在這里默認布局是放在 RecyclerView 中心
  26.             layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2,
  27.                     widthSpace / 2 + getDecoratedMeasuredWidth(view),
  28.                     heightSpace / 2 + getDecoratedMeasuredHeight(view));
  29.             // 其實屏幕上有四張卡片,但是我們把第三張和第四張卡片重疊在一起,這樣看上去就只有三張
  30.             // 第四張卡片主要是為了保持動畫的連貫性
  31.             if (position == CardConfig.DEFAULT_SHOW_ITEM) {
  32.                 // 按照一定的規(guī)則縮放,并且偏移Y軸。
  33.                 // CardConfig.DEFAULT_SCALE 默認為0.1f,CardConfig.DEFAULT_TRANSLATE_Y 默認為14
  34.                 view.setScaleX(1 - (position - 1) * CardConfig.DEFAULT_SCALE);
  35.                 view.setScaleY(1 - (position - 1) * CardConfig.DEFAULT_SCALE);
  36.                 view.setTranslationY((position - 1) * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
  37.             } else if (position > 0) {
  38.                 view.setScaleX(1 - position * CardConfig.DEFAULT_SCALE);
  39.                 view.setScaleY(1 - position * CardConfig.DEFAULT_SCALE);
  40.                 view.setTranslationY(position * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
  41.             } else {
  42.                 // 設置 mTouchListener 的意義就在于我們想讓處于頂層的卡片是可以隨意滑動的
  43.                 // 而第二層、第三層等等的卡片是禁止滑動的
  44.                 view.setOnTouchListener(mOnTouchListener);
  45.             }
  46.         }
  47.     } else {
  48.         // 當數(shù)據(jù)源個數(shù)小于或等于***顯示數(shù)時,和上面的代碼差不多
  49.         for (int position = itemCount - 1; position >= 0; position--) {
  50.             final View view = recycler.getViewForPosition(position);
  51.             addView(view);
  52.             measureChildWithMargins(view, 0, 0);
  53.             int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
  54.             int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);
  55.             layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2,
  56.                     widthSpace / 2 + getDecoratedMeasuredWidth(view),
  57.                     heightSpace / 2 + getDecoratedMeasuredHeight(view));
  58.             if (position > 0) {
  59.                 view.setScaleX(1 - position * CardConfig.DEFAULT_SCALE);
  60.                 view.setScaleY(1 - position * CardConfig.DEFAULT_SCALE);
  61.                 view.setTranslationY(position * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
  62.             } else {
  63.                 view.setOnTouchListener

    名稱欄目:玩轉(zhuǎn)仿探探卡片式滑動效果
    網(wǎng)址分享:http://www.5511xx.com/article/dhphdoh.html