首先看下效果
背景
上圖所示這種效果辈赋,在很多APP上很常見(jiàn),當(dāng)我們真正想著手開(kāi)發(fā)時(shí)毛俏,可能會(huì)遇到很多沖突問(wèn)題炭庙,很難實(shí)現(xiàn)完美效果饲窿,如果想研究事件沖突的擼友們可以看看這篇文章傳送地址煌寇,于是我本著無(wú)聊的心態(tài)做了下,下面講述下實(shí)現(xiàn)的一種常規(guī)方案逾雄,如果有不足的地方請(qǐng)大家提出阀溶,我將繼續(xù)完善
功能點(diǎn)簡(jiǎn)單說(shuō)明
- 下拉整體刷新,上拉加載(上拉隸屬于單個(gè)fragment)
- 下拉圖片視差效果鸦泳,開(kāi)始圖片整體放大银锻,向下平移,達(dá)到閥值時(shí)(可自定義)做鹰,下拉只保留向下平移效果击纬,頂部title左右倆側(cè)按鈕漸變隱藏
- 上滑頂部title停留
- 上滑頂部title左右倆次按鈕改變顏色,頂部title背景顏色漸變顯示
- Tablayout停留
布局設(shè)計(jì)分析
-FrameLayout(最外層)
-ImageView(頭部背景圖)
-SmartRefreshLayout(頭部刷新控件)
-CoordinatorLayout
-AppBarLayout
-CollapsingToolbarLayout
-Toolbar
...省略中間巴拉巴拉布局
-Tablayout
-ViewPager
-Toolbar
功能點(diǎn)模塊分析钾麸,效果實(shí)現(xiàn)
1.下拉整體刷新更振,上拉加載(上拉隸屬于單個(gè)fragment)
通過(guò)上述布局分析可以看出炕桨,在最外層嵌套了一層刷新控件 SmartRefreshLayout ,此控件提供頂部刷新功能肯腕,Tablayout+ViewPager+Fragment實(shí)現(xiàn)方法可以放N多個(gè)Fragment献宫,F(xiàn)ragment布局中設(shè)計(jì)如下
<?xml version="1.0" encoding="utf-8"?>
<com.scwang.smartrefresh.layout.SmartRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
于是會(huì)出現(xiàn)外層和內(nèi)層Fragment都會(huì)出現(xiàn)上拉和下拉功能,所以我們
禁止外層上拉加載功能 mRefreshLayout.setEnableLoadMore(false);
禁止內(nèi)層下拉刷新功能 mRefreshLayout.setEnableLoadMore(false);
這樣就實(shí)現(xiàn)了我們的需求
2.下拉圖片視差效果实撒,開(kāi)始圖片整體放大姊途,向下平移,達(dá)到閥值時(shí)(可自定義)知态,下拉只保留向下平移效果捷兰,頂部title左右倆側(cè)按鈕漸變隱藏
所以我們需要對(duì)RefreshLayout做向下平移監(jiān)聽(tīng),代碼如下
mRefreshLayout.setOnMultiPurposeListener(new SimpleMultiPurposeListener() {
@Override
public void onHeaderMoving(RefreshHeader header, boolean isDragging, float percent, int offset, int headerHeight, int maxDragHeight) {
//設(shè)置圖片向下移動(dòng)
mIvHeader.setTranslationY(offset / 2);
//設(shè)置title漸變效果
mToolbar1.setAlpha(1 - Math.min(percent, 1));
//設(shè)置圖片寬度變化 當(dāng)達(dá)到指定設(shè)置的指定值后 寬度停止 只向下移動(dòng)
if (offset <= 100) {
ViewGroup.LayoutParams layoutParams = mIvHeader.getLayoutParams();
layoutParams.width = (mScreenWidth + offset);
((ViewGroup.MarginLayoutParams) layoutParams).setMargins(-(layoutParams.width - mScreenWidth) / 2, -DisplayUtil.dip2px(MainActivity.this,200), 0, 0);
mIvHeader.requestLayout();
}
}
});
(1)圖片向下平移實(shí)現(xiàn)我們可通過(guò)setTranslationY實(shí)現(xiàn)负敏,速度自己可以調(diào)節(jié)(offset / 2)
(2)頂部titleBar下拉漸變隱藏寂殉, mToolbar1.setAlpha(1 - Math.min(percent, 1));搞定,建議大家打印下回調(diào)的各個(gè)參數(shù)日志原在,以便理解
(3)圖片放大重點(diǎn)說(shuō)一下友扰,其實(shí)原理是動(dòng)態(tài)改變圖片的寬度,如果直接改變width的話庶柿,因?yàn)閳D片的坐標(biāo)起始點(diǎn)在左上角村怪,改變了寬度之后圖片中心點(diǎn)會(huì)往屏幕中心點(diǎn)右側(cè)偏移(在寬度變大情況下),所以需要給圖片設(shè)置一個(gè)margins浮庐,
值為=(圖片寬度-圖片放大寬度)/2
因?yàn)閳D片需要實(shí)現(xiàn)向下拉升不到頭效果甚负,所以布局MargingTop需要個(gè)給負(fù)數(shù)如( -DisplayUtil.dip2px(MainActivity.this,200)),這樣就實(shí)現(xiàn)了一直拉不到頭效果
3.如何實(shí)現(xiàn)上滑頂部title停留
這個(gè)測(cè)試了多種方法审残,但還是選擇了下邊這種梭域,思路為CollapsingToolbarLayout中放一個(gè)titleBar,但是這個(gè)titleBar無(wú)任何顯示作用,只是提供滑動(dòng)到頂部停留作用搅轿,這是這個(gè)控件不設(shè)置任何屬性的強(qiáng)大之處病涨,真正titlebar的相關(guān)控件放在最外層,和imageView同級(jí)璧坟,它一直存在既穆,只是對(duì)它做顯示隱藏處理
在說(shuō)明一下,如果CollapsingToolbarLayout中的titleBar放置返回等按鈕雀鹃,在下拉刷新時(shí)幻工,整體布局向下移動(dòng),這樣title中返回和右邊的按鈕會(huì)一起向下移動(dòng)黎茎,這樣體驗(yàn)不好囊颅,所以采用了倆個(gè)titleBar這樣思路去實(shí)現(xiàn)
此外衍生一個(gè)問(wèn)題,titleBar高度如何處理,比如高版本低版本等踢代,為了適配頁(yè)面先鱼,不采用固定值做法,動(dòng)態(tài)測(cè)量狀態(tài)欄高度
//增加View的paddingTop,增加的值為狀態(tài)欄高度 (智能判斷奸鬓,并設(shè)置高度) titleBar
StatusBarUtil.setPaddingSmart(this, mToolbar);
StatusBarUtil.setPaddingSmart(this, mToolbar1);
/** 增加View的paddingTop,增加的值為狀態(tài)欄高度 (智能判斷焙畔,并設(shè)置高度)*/
public static void setPaddingSmart(Context context, View view) {
if (Build.VERSION.SDK_INT >= 19) {
ViewGroup.LayoutParams lp = view.getLayoutParams();
if (lp != null && lp.height > 0) {
lp.height += getStatusBarHeight(context);//增高
}
view.setPadding(view.getPaddingLeft(), view.getPaddingTop() + getStatusBarHeight(context),
view.getPaddingRight(), view.getPaddingBottom());
}
}
4.如何實(shí)現(xiàn)上滑頂部title左右倆次按鈕改變顏色,頂部title背景顏色漸變顯示
想實(shí)現(xiàn)這個(gè)效果需要監(jiān)聽(tīng)上滑移動(dòng)串远,這樣我們需要用到AppBarLayout的方法宏多,mAppbarLayout.addOnOffsetChangedListener(this);
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
int scrollRangle = appBarLayout.getTotalScrollRange();
/**
* 如果是verticalOffset改成負(fù)數(shù) 有不一樣的效果,可以模擬試試
*/
mIvHeader.setTranslationY(verticalOffset);
/**
* 這個(gè)數(shù)值可以自己定義
*/
if (verticalOffset < -10) {
mIvBack.setImageResource(R.drawable.back_black);
mIvMenu.setImageResource(R.drawable.icon_menu_black);
} else {
mIvBack.setImageResource(R.drawable.back_white);
mIvMenu.setImageResource(R.drawable.icon_menu_white);
}
int mAlpha = (int) Math.abs(255f / scrollRangle * verticalOffset);
//頂部title漸變效果
mToolbar1.setBackgroundColor(Color.argb(mAlpha, 255, 255, 255));
mToolbarUsername.setTextColor(Color.argb(mAlpha, 0, 0, 0));
}
(1)整體上滑時(shí)澡罚,我想讓圖片整體向上移動(dòng)伸但,所以
mIvHeader.setTranslationY(verticalOffset);,改變圖片的Y軸位置留搔,
如果想讓圖片反方向移動(dòng)更胖,可以將verticalOffset改成負(fù)數(shù),如
mIvHeader.setTranslationY(-verticalOffset);隔显,有不一樣的視差體驗(yàn)却妨,效果也是棒棒的,大家可以試試
(2)頂部title左右倆測(cè)按鈕改變顏色括眠,其實(shí)也就是改變圖片彪标,自己定義一個(gè)閾值,很好實(shí)現(xiàn)
if (verticalOffset < -10) {
mIvBack.setImageResource(R.drawable.back_black);
mIvMenu.setImageResource(R.drawable.icon_menu_black);
} else {
mIvBack.setImageResource(R.drawable.back_white);
mIvMenu.setImageResource(R.drawable.icon_menu_white);
}
或者對(duì)圖片做漸變顯示隱藏操作也是可以的掷豺,就會(huì)有圖片漸變由白變成黑的效果捞烟,大家可以試試,方法是這個(gè)setAlpha
(3)頂部title背景漸變效果当船,和文字漸變题画,
int mAlpha = (int) Math.abs(255f / scrollRangle * verticalOffset);
mToolbar1.setBackgroundColor(Color.argb(mAlpha, 255, 255, 255));
mToolbarUsername.setTextColor(Color.argb(mAlpha, 0, 0, 0));
5.如何實(shí)現(xiàn)Tablayout停留
這個(gè)歸功于AppBarLayout+CollapsingToolbarLayout強(qiáng)大之處
AppBarLayout里放入的都可以跟著向上滑動(dòng)滑出布局的的,添加app:layout_scrollFlags="scroll"屬性可以滑出布局德频,TabLayout沒(méi)有添加苍息,所以停留在頂部,理解這個(gè)屬性就隨意操控了抱婉,還有很多炫酷的動(dòng)畫視覺(jué)效果档叔,大家可以去查閱下
項(xiàng)目提供幾個(gè)輪子演示,大家可以盡情的玩耍了
指示器輪子
刷新框架輪子
adapter適配器輪子
屏幕適配輪子蒸绩,倆種實(shí)現(xiàn)方法
多字體輪子,因?yàn)轫?yè)面不好看铃肯,改了一種字體
最后患亿,祝大家開(kāi)發(fā)順利!