首先看下效果

背景
上圖所示這種效果,在很多APP上很常見,當我們真正想著手開發(fā)時,可能會遇到很多沖突問題,很難實現(xiàn)完美效果,如果想研究事件沖突的擼友們可以看看這篇文章傳送地址,于是我本著無聊的心態(tài)做了下,下面講述下實現(xiàn)的一種常規(guī)方案,如果有不足的地方請大家提出,我將繼續(xù)完善
功能點簡單說明
- 下拉整體刷新,上拉加載(上拉隸屬于單個fragment)
- 下拉圖片視差效果,開始圖片整體放大,向下平移,達到閥值時(可自定義),下拉只保留向下平移效果,頂部title左右倆側(cè)按鈕漸變隱藏
- 上滑頂部title停留
- 上滑頂部title左右倆次按鈕改變顏色,頂部title背景顏色漸變顯示
- Tablayout停留
布局設(shè)計分析
-FrameLayout(最外層)
-ImageView(頭部背景圖)
-SmartRefreshLayout(頭部刷新控件)
-CoordinatorLayout
-AppBarLayout
-CollapsingToolbarLayout
-Toolbar
...省略中間巴拉巴拉布局
-Tablayout
-ViewPager
-Toolbar
功能點模塊分析,效果實現(xiàn)
1.下拉整體刷新,上拉加載(上拉隸屬于單個fragment)
通過上述布局分析可以看出,在最外層嵌套了一層刷新控件 SmartRefreshLayout ,此控件提供頂部刷新功能,Tablayout+ViewPager+Fragment實現(xiàn)方法可以放N多個Fragment,F(xiàn)ragment布局中設(shè)計如下
<?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>
于是會出現(xiàn)外層和內(nèi)層Fragment都會出現(xiàn)上拉和下拉功能,所以我們
禁止外層上拉加載功能 mRefreshLayout.setEnableLoadMore(false);
禁止內(nèi)層下拉刷新功能 mRefreshLayout.setEnableLoadMore(false);
這樣就實現(xiàn)了我們的需求
2.下拉圖片視差效果,開始圖片整體放大,向下平移,達到閥值時(可自定義),下拉只保留向下平移效果,頂部title左右倆側(cè)按鈕漸變隱藏
所以我們需要對RefreshLayout做向下平移監(jiān)聽,代碼如下
mRefreshLayout.setOnMultiPurposeListener(new SimpleMultiPurposeListener() {
@Override
public void onHeaderMoving(RefreshHeader header, boolean isDragging, float percent, int offset, int headerHeight, int maxDragHeight) {
//設(shè)置圖片向下移動
mIvHeader.setTranslationY(offset / 2);
//設(shè)置title漸變效果
mToolbar1.setAlpha(1 - Math.min(percent, 1));
//設(shè)置圖片寬度變化 當達到指定設(shè)置的指定值后 寬度停止 只向下移動
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)圖片向下平移實現(xiàn)我們可通過setTranslationY實現(xiàn),速度自己可以調(diào)節(jié)(offset / 2)
(2)頂部titleBar下拉漸變隱藏, mToolbar1.setAlpha(1 - Math.min(percent, 1));搞定,建議大家打印下回調(diào)的各個參數(shù)日志,以便理解
(3)圖片放大重點說一下,其實原理是動態(tài)改變圖片的寬度,如果直接改變width的話,因為圖片的坐標起始點在左上角,改變了寬度之后圖片中心點會往屏幕中心點右側(cè)偏移(在寬度變大情況下),所以需要給圖片設(shè)置一個margins,
值為=(圖片寬度-圖片放大寬度)/2
因為圖片需要實現(xiàn)向下拉升不到頭效果,所以布局MargingTop需要個給負數(shù)如( -DisplayUtil.dip2px(MainActivity.this,200)),這樣就實現(xiàn)了一直拉不到頭效果
3.如何實現(xiàn)上滑頂部title停留
這個測試了多種方法,但還是選擇了下邊這種,思路為CollapsingToolbarLayout中放一個titleBar,但是這個titleBar無任何顯示作用,只是提供滑動到頂部停留作用,這是這個控件不設(shè)置任何屬性的強大之處,真正titlebar的相關(guān)控件放在最外層,和imageView同級,它一直存在,只是對它做顯示隱藏處理
在說明一下,如果CollapsingToolbarLayout中的titleBar放置返回等按鈕,在下拉刷新時,整體布局向下移動,這樣title中返回和右邊的按鈕會一起向下移動,這樣體驗不好,所以采用了倆個titleBar這樣思路去實現(xiàn)
此外衍生一個問題,titleBar高度如何處理,比如高版本低版本等,為了適配頁面,不采用固定值做法,動態(tài)測量狀態(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.如何實現(xiàn)上滑頂部title左右倆次按鈕改變顏色,頂部title背景顏色漸變顯示
想實現(xiàn)這個效果需要監(jiān)聽上滑移動,這樣我們需要用到AppBarLayout的方法,mAppbarLayout.addOnOffsetChangedListener(this);
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
int scrollRangle = appBarLayout.getTotalScrollRange();
/**
* 如果是verticalOffset改成負數(shù) 有不一樣的效果,可以模擬試試
*/
mIvHeader.setTranslationY(verticalOffset);
/**
* 這個數(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)整體上滑時,我想讓圖片整體向上移動,所以
mIvHeader.setTranslationY(verticalOffset);,改變圖片的Y軸位置,
如果想讓圖片反方向移動,可以將verticalOffset改成負數(shù),如
mIvHeader.setTranslationY(-verticalOffset);,有不一樣的視差體驗,效果也是棒棒的,大家可以試試
(2)頂部title左右倆測按鈕改變顏色,其實也就是改變圖片,自己定義一個閾值,很好實現(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);
}
或者對圖片做漸變顯示隱藏操作也是可以的,就會有圖片漸變由白變成黑的效果,大家可以試試,方法是這個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.如何實現(xiàn)Tablayout停留
這個歸功于AppBarLayout+CollapsingToolbarLayout強大之處
AppBarLayout里放入的都可以跟著向上滑動滑出布局的的,添加app:layout_scrollFlags="scroll"屬性可以滑出布局,TabLayout沒有添加,所以停留在頂部,理解這個屬性就隨意操控了,還有很多炫酷的動畫視覺效果,大家可以去查閱下
項目提供幾個輪子演示,大家可以盡情的玩耍了
指示器輪子
刷新框架輪子
adapter適配器輪子
屏幕適配輪子,倆種實現(xiàn)方法
多字體輪子,因為頁面不好看,改了一種字體
最后,祝大家開發(fā)順利!