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

成都創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站建設(shè)、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的阜新網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
最早可以追溯到我試玩探探這個 APP 。***次進(jìn)入軟件界面,就被這種通過卡片式滑動來選擇“喜歡/不喜歡”的設(shè)計所吸引了。當(dāng)時就非常想通過自己來實現(xiàn)這種仿探探式的效果,然而卻沒什么思路。不過毋庸置疑的是,這種效果的原理肯定和 ListView / RecyclerView 類似,涉及到 Item View 的回收和重用,否則早就因為大量的 Item View 而 OOM 了。
再到后來,看到許多大神也推出了同樣仿探探效果的博客,從頭到尾閱讀下來,寫得通俗易懂,基本上沒什么問題。于是,實現(xiàn)仿探探效果的想法再次出現(xiàn)在腦海中。那么,還猶豫什么,趁熱來一發(fā)吧!就這么愉快地決定了。
首先面臨的問題就是關(guān)于實現(xiàn) View 上的考慮。毫無疑問。
RecyclerView 是***選擇!
RecyclerView 是***選擇!
RecyclerView 是***選擇!
重要的話講三遍!!!
究其原因,***,RecyclerView 是自帶 Item View 回收和重用功能的,就不需要我們考慮這個問題了;第二,RecyclerView 的布局方式是通過設(shè)置 LayoutManager 來實現(xiàn)的,這樣就充分地把布局和 RecyclerView “解耦”開來了。而 LayoutManager 是可以通過自定義的方式來實現(xiàn)的。這恰恰是我們想要的!!!再說一點,這也正是不選用 ListView 的原因之一。
下面,我們就開始動手了。帶你見證奇跡的時刻。
CardLayoutManager
創(chuàng)建 CardLayoutManager 并繼承自 RecyclerView.LayoutManager 。需要我們自己實現(xiàn) generateDefaultLayoutParams() 方法:
- @Override
- public RecyclerView.LayoutParams generateDefaultLayoutParams() {
- return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- }
一般情況下,像上面這樣寫即可。
下面這個方法就是我們的重點了。 onLayoutChildren(final RecyclerView.Recycler recycler, RecyclerView.State state) 方法就是用來實現(xiàn) Item View 布局的:
- @Override
- public void onLayoutChildren(final RecyclerView.Recycler recycler, RecyclerView.State state) {
- super.onLayoutChildren(recycler, state);
- // 先移除所有view
- removeAllViews();
- // 在布局之前,將所有的子 View 先 Detach 掉,放入到 Scrap 緩存中
- detachAndScrapAttachedViews(recycler);
- int itemCount = getItemCount();
- // 在這里,我們默認(rèn)配置 CardConfig.DEFAULT_SHOW_ITEM = 3。即在屏幕上顯示的卡片數(shù)為3
- // 當(dāng)數(shù)據(jù)源個數(shù)大于***顯示數(shù)時
- if (itemCount > CardConfig.DEFAULT_SHOW_ITEM) {
- // 把數(shù)據(jù)源倒著循環(huán),這樣,第0個數(shù)據(jù)就在屏幕最上面了
- for (int position = CardConfig.DEFAULT_SHOW_ITEM; position >= 0; position--) {
- final View view = recycler.getViewForPosition(position);
- // 將 Item View 加入到 RecyclerView 中
- addView(view);
- // 測量 Item View
- measureChildWithMargins(view, 0, 0);
- // getDecoratedMeasuredWidth(view) 可以得到 Item View 的寬度
- // 所以 widthSpace 就是除了 Item View 剩余的值
- int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
- // 同理
- int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);
- // 將 Item View 放入 RecyclerView 中布局
- // 在這里默認(rèn)布局是放在 RecyclerView 中心
- layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2,
- widthSpace / 2 + getDecoratedMeasuredWidth(view),
- heightSpace / 2 + getDecoratedMeasuredHeight(view));
- // 其實屏幕上有四張卡片,但是我們把第三張和第四張卡片重疊在一起,這樣看上去就只有三張
- // 第四張卡片主要是為了保持動畫的連貫性
- if (position == CardConfig.DEFAULT_SHOW_ITEM) {
- // 按照一定的規(guī)則縮放,并且偏移Y軸。
- // CardConfig.DEFAULT_SCALE 默認(rèn)為0.1f,CardConfig.DEFAULT_TRANSLATE_Y 默認(rèn)為14
- view.setScaleX(1 - (position - 1) * CardConfig.DEFAULT_SCALE);
- view.setScaleY(1 - (position - 1) * CardConfig.DEFAULT_SCALE);
- view.setTranslationY((position - 1) * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
- } else if (position > 0) {
- view.setScaleX(1 - position * CardConfig.DEFAULT_SCALE);
- view.setScaleY(1 - position * CardConfig.DEFAULT_SCALE);
- view.setTranslationY(position * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
- } else {
- // 設(shè)置 mTouchListener 的意義就在于我們想讓處于頂層的卡片是可以隨意滑動的
- // 而第二層、第三層等等的卡片是禁止滑動的
- view.setOnTouchListener(mOnTouchListener);
- }
- }
- } else {
- // 當(dāng)數(shù)據(jù)源個數(shù)小于或等于***顯示數(shù)時,和上面的代碼差不多
- for (int position = itemCount - 1; position >= 0; position--) {
- final View view = recycler.getViewForPosition(position);
- addView(view);
- measureChildWithMargins(view, 0, 0);
- int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
- int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);
- layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2,
- widthSpace / 2 + getDecoratedMeasuredWidth(view),
- heightSpace / 2 + getDecoratedMeasuredHeight(view));
- if (position > 0) {
- view.setScaleX(1 - position * CardConfig.DEFAULT_SCALE);
- view.setScaleY(1 - position * CardConfig.DEFAULT_SCALE);
- view.setTranslationY(position * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
- } else {
- view.setOnTouchListener
本文題目:玩轉(zhuǎn)仿探探卡片式滑動效果
網(wǎng)頁路徑:http://www.dlmjj.cn/article/dhphdoh.html


咨詢
建站咨詢
