摘要:商品詳情頁上拉查看詳情目錄介紹該庫介紹效果展示如何使用注意要點優(yōu)化問題部分代碼邏輯參考案例該庫介紹模仿淘寶京東考拉等商品詳情頁分頁加載的效果。
商品詳情頁上拉查看詳情 目錄介紹
01.該庫介紹
02.效果展示
03.如何使用
04.注意要點
05.優(yōu)化問題
06.部分代碼邏輯
07.參考案例
01.該庫介紹模仿淘寶、京東、考拉等商品詳情頁分頁加載的UI效果。可以嵌套RecyclerView、WebView、ViewPager、ScrollView等等。
項目地址:https://github.com/yangchong2...
02.效果展示 2.1 使用SlideLayout效果 2.2 使用SlideAnimLayout帶有加載動畫效果 03.如何使用 3.1 第一種,直接上拉加載分頁【SlideLayout有兩個子ChildView】SlideDetailsLayout有兩個子ChildView:一個是商品頁layout,一個是詳情頁layout
在布局中
```
在代碼中
mSlideDetailsLayout.setOnSlideDetailsListener(new SlideLayout.OnSlideDetailsListener() { @Override public void onStatusChanged(SlideLayout.Status status) { if (status == SlideLayout.Status.OPEN) { //當(dāng)前為圖文詳情頁 Log.e("FirstActivity","下拉回到商品詳情"); } else { //當(dāng)前為商品詳情頁 Log.e("FirstActivity","繼續(xù)上拉,查看圖文詳情"); } } }); //關(guān)閉商詳頁 mSlideDetailsLayout.smoothClose(true); //打開詳情頁 mSlideDetailsLayout.smoothOpen(true);3.2 第一種,上拉加載有動畫效果,然后展示分頁【SlideAnimLayout有三個子ChildView】
SlideAnimLayout有三個子ChildView:一個是商品頁layout,一個是上拉加載動畫layout,一個是詳情頁layout
在布局中
```
在代碼中
mSlideDetailsLayout.setScrollStatusListener(new SlideAnimLayout.onScrollStatusListener() { @Override public void onStatusChanged(SlideAnimLayout.Status mNowStatus, boolean isHalf) { if(mNowStatus== SlideAnimLayout.Status.CLOSE){ //打開 if(isHalf){ mTvMoreText.setText("釋放,查看圖文詳情"); mIvMoreImg.animate().rotation(0); LoggerUtils.i("onStatusChanged---CLOSE---釋放"+isHalf); }else{//關(guān)閉 mTvMoreText.setText("繼續(xù)上拉,查看圖文詳情"); mIvMoreImg.animate().rotation(180); LoggerUtils.i("onStatusChanged---CLOSE---繼續(xù)上拉"+isHalf); } }else{ //打開 if(isHalf){ mTvMoreText.setText("下拉回到商品詳情"); mIvMoreImg.animate().rotation(0); LoggerUtils.i("onStatusChanged---OPEN---下拉回到商品詳情"+isHalf); }else{//關(guān)閉 mTvMoreText.setText("釋放回到商品詳情"); mIvMoreImg.animate().rotation(180); LoggerUtils.i("onStatusChanged---OPEN---釋放回到商品詳情"+isHalf); } } } }); //關(guān)閉商詳頁 mSlideDetailsLayout.smoothClose(true); //打開詳情頁 mSlideDetailsLayout.smoothOpen(true);04.注意要點
針對SlideDetailsLayout僅獲取子節(jié)點中的前兩個View
其中第一個作為Front,即商品頁;第二個作為Behind,即圖文詳情WebView頁面。具體看代碼:
@Override protected void onFinishInflate() { super.onFinishInflate(); final int childCount = getChildCount(); if (1 >= childCount) { throw new RuntimeException("SlideDetailsLayout only accept child more than 1!!"); } mFrontView = getChildAt(0); mBehindView = getChildAt(1); if(mDefaultPanel == 1){ post(new Runnable() { @Override public void run() { //默認(rèn)是關(guān)閉狀態(tài)的 smoothOpen(false); } }); } }
針對SlideAnimLayout僅獲取子節(jié)點中三個View,且第二個為動畫節(jié)點View
其中第一個作為Front,即商品頁;第二個作為anim,即上拉動畫view。第三個作為Behind,即圖文詳情WebView頁面。具體看代碼:
@Override protected void onFinishInflate() { super.onFinishInflate(); final int childCount = getChildCount(); if (1 >= childCount) { throw new RuntimeException("SlideDetailsLayout only accept childs more than 1!!"); } mFrontView = getChildAt(0); mAnimView = getChildAt(1); mBehindView = getChildAt(2); mAnimView.post(new Runnable() { @Override public void run() { animHeight = mAnimView.getHeight(); LoggerUtils.i("獲取控件高度"+animHeight); } }); if(mDefaultPanel == 1){ post(new Runnable() { @Override public void run() { //默認(rèn)是關(guān)閉狀態(tài)的 smoothOpen(false); } }); } }05.優(yōu)化問題
異常情況保存狀態(tài)
@Override protected Parcelable onSaveInstanceState() { SavedState ss = new SavedState(super.onSaveInstanceState()); ss.offset = mSlideOffset; ss.status = mStatus.ordinal(); return ss; } @Override protected void onRestoreInstanceState(Parcelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); mSlideOffset = ss.offset; mStatus = Status.valueOf(ss.status); if (mStatus == Status.OPEN) { mBehindView.setVisibility(VISIBLE); } requestLayout(); }
當(dāng)頁面銷毀的時候,移除listener監(jiān)聽,移除動畫資源
@Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); setScrollStatusListener(null); setOnSlideStatusListener(null); if (animator!=null){ animator.cancel(); animator = null; } }06.部分代碼邏輯 6.1 如何實現(xiàn)ScrollView在最頂部或者最底部的時候,不消費事件
具體邏輯在dispatchTouchEvent分發(fā)事件中,當(dāng)滑動到頂部或者底部的時候,則直接讓父View消費事件。其他情況是自己是將事件會向上返還給View的父節(jié)點。
@Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downX = ev.getX(); downY = ev.getY(); //如果滑動到了最底部,就允許繼續(xù)向上滑動加載下一頁,否者不允許 //如果子節(jié)點不希望父進程攔截觸摸事件,則為true。 getParent().requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_MOVE: float dx = ev.getX() - downX; float dy = ev.getY() - downY; boolean allowParentTouchEvent; if (Math.abs(dy) > Math.abs(dx)) { if (dy > 0) { //位于頂部時下拉,讓父View消費事件 allowParentTouchEvent = isTop(); } else { //位于底部時上拉,讓父View消費事件 allowParentTouchEvent = isBottom(); } } else { //水平方向滑動 allowParentTouchEvent = true; } getParent().requestDisallowInterceptTouchEvent(!allowParentTouchEvent); break; default: break; } return super.dispatchTouchEvent(ev); }6.2 如何實現(xiàn)商品頁和詳情頁之間的滑動,如何處理上拉加載控件的動畫效果
SlideAnimLayout有三個子ChildView:一個是商品頁layout,一個是上拉加載動畫layout,一個是詳情頁layout
通過onInterceptTouchEvent進行事件攔截后,在onTouchEvent方法中對觸摸信息做進一步處理可以實現(xiàn)豎直方向的滑動
當(dāng)商品頁ScrollView滑動到底部時,則直接讓父View消費事件,該父View也就是SlideAnimLayout
在onInterceptTouchEvent中,當(dāng)打開詳情頁后(也就是CLOSE狀態(tài)),向下拉動,當(dāng)y軸滑動位移絕對值大于觸摸移動的像素距離,并且當(dāng)y軸滑動位移大于0,則攔截事件分發(fā)自己消費事件
在onInterceptTouchEvent中,當(dāng)關(guān)閉詳情頁后(也就是OPEN狀態(tài)),向上拉動,當(dāng)y軸滑動位移絕對值大于觸摸移動的像素距離,并且當(dāng)y軸滑動位移小于0,則攔截事件分發(fā)自己消費事件
當(dāng)處在商品頁時,向上拉動;或者處于詳情頁時,向下拉動,在拉動過程中去改變mSlideOffset值,并且調(diào)用requestLayout()方法去繪制
在屏幕區(qū)域滑動兩個面板只需要改變兩個面板在y軸方向的位移(有正負(fù)方向)即可。滑動的標(biāo)尺是控件相對于Top的移動,且所有的位移計算都是基于該標(biāo)尺。在切換面板時只需要知道對應(yīng)的offset值即可……
如何處理上拉加載控件的動畫效果
添加一個listener監(jiān)聽,可以監(jiān)聽到狀態(tài),以及是否達到一半距離,主要是和offset比較,當(dāng)?shù)竭_一半距離的時候,這個時候用屬性動畫將箭頭view旋轉(zhuǎn)180度即可實現(xiàn)。
既然要監(jiān)聽滑動距離,則首先要獲取該加載控件的高度animHeight,那么在哪里獲取比較合適呢?可以在onFinishInflate()方法中,用post形式獲取控件高度。
那么如何使滑動生效,并且看上去比較連貫
自定義布局中有非常重要的兩個環(huán)節(jié)onMeasure(測量)和onLayout(布局)。測量決定了View的所占的大小,布局決定了View所處的位置。實現(xiàn)滑動的關(guān)鍵思路就在這里,我們在onLayout方法中根據(jù)通過onInterceptTouchEvent、onTouchEvent得到的滑動信息進行計算而得到布局的位置信息,并把這個位置信息設(shè)置到子View上面即可實現(xiàn)滑動。
滑動后松開手指如何實現(xiàn)滾動效果
也就是說,當(dāng)處在商品頁時,向上拉動,拉動位移大于一半時,松開手指,則直接滑動到下一頁詳情頁頁面
具體邏輯在finishTouchEvent方法中,它主要是記錄offset值,以及close或open狀態(tài)下視圖的高度,還有是否發(fā)生切換變化
最后開啟動畫,在動畫過程中添加動畫update的監(jiān)聽,在該方法中去requestLayout()控件,這樣就達到滾動效果了。動畫滾動結(jié)束后,如果是open狀態(tài)并且是第一次顯示,則設(shè)置詳情頁控件可見。
如何使?jié)L動效果比較自然,或者如何調(diào)整滾動時長
可以自定義設(shè)置時間,直接在布局中設(shè)置……
07.參考案例感謝下面大佬的開源案例
https://github.com/jeasonlzy/...
https://github.com/hexianqiao...
https://github.com/cnbleu/Sli...
08.其他更多 01.關(guān)于博客匯總鏈接1.技術(shù)博客匯總
2.開源項目匯總
3.生活博客匯總
4.喜馬拉雅音頻匯總
5.其他匯總
02.關(guān)于我的博客我的個人站點:www.yczbj.org,www.ycbjie.cn
github:https://github.com/yangchong211
知乎:https://www.zhihu.com/people/...
簡書:http://www.jianshu.com/u/b7b2...
csdn:http://my.csdn.net/m0_37700275
喜馬拉雅聽書:http://www.ximalaya.com/zhubo...
開源中國:https://my.oschina.net/zbj161...
泡在網(wǎng)上的日子:http://www.jcodecraeer.com/me...
郵箱:yangchong211@163.com
阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV
segmentfault頭條:https://segmentfault.com/u/xi...
掘金:https://juejin.im/user/593943...
項目地址:https://github.com/yangchong2...文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/74220.html
摘要:最佳實踐良好的編碼規(guī)范單元測試持續(xù)集成文檔,從一開始就形成良好的編碼習(xí)慣。真實的電商業(yè)務(wù)所有的業(yè)務(wù)需求來自真實的客戶,并且線上良好運營中。 重要通知: Laravel + 小程序的開源電商版本源碼已經(jīng)在 github 上拉,歡迎提交 issue 和 star :) 開源電商 Server 端: Laravel API源碼 開源電商 client 端:小程序源碼 iBrand 簡介...
摘要:嗯這句話就是作為第一次做仿小程序項目的我,歷經(jīng)磨難得出來的肺腑之言。作為想要走上代碼這條不歸路的程序員,心浮氣躁就是為以后整個項目給自己挖坑奠定了良好的基礎(chǔ)。 前言 ?????關(guān)于小程序,在這里有一句話送給正準(zhǔn)備閱讀的你-世界上本沒有坑,路走的多了就有了;世界上本沒有路,坑填的多了就有了。嗯~~~這句話就是作為第一次做仿小程序項目的我,歷經(jīng)‘磨難’得出來的肺腑之言。好了,不多說,進入正...
摘要:嗯這句話就是作為第一次做仿小程序項目的我,歷經(jīng)磨難得出來的肺腑之言。作為想要走上代碼這條不歸路的程序員,心浮氣躁就是為以后整個項目給自己挖坑奠定了良好的基礎(chǔ)。 前言 ?????關(guān)于小程序,在這里有一句話送給正準(zhǔn)備閱讀的你-世界上本沒有坑,路走的多了就有了;世界上本沒有路,坑填的多了就有了。嗯~~~這句話就是作為第一次做仿小程序項目的我,歷經(jīng)‘磨難’得出來的肺腑之言。好了,不多說,進入正...
閱讀 767·2021-10-09 09:58
閱讀 635·2021-08-27 16:24
閱讀 1719·2019-08-30 14:15
閱讀 2377·2019-08-30 11:04
閱讀 2061·2019-08-29 18:43
閱讀 2166·2019-08-29 15:20
閱讀 2712·2019-08-26 12:20
閱讀 1612·2019-08-26 11:44