XRecyclerView_For_QQ_Refresh_Header
介紹
本項(xiàng)目是根據(jù) IPHONE 版 QQ 的下拉刷新布局,基于 XRecyclerView 實(shí)現(xiàn)的 Android版 QQ 下拉刷新布局。項(xiàng)目地址,歡迎使用,PR,喜歡的話請(qǐng) star 一下。效果如下:(錄屏軟件比較渣,大家可以自我運(yùn)行觀察一下效果)
QQ 的下拉刷新樣式(原來是大 Twitter 的專利)

緣由
實(shí)現(xiàn)這個(gè)的原因也沒啥,就是好奇(其實(shí)最近在看 貝賽爾曲線)。大家可以拿出自己的蘋果手機(jī)(非常抱歉,Android 版的 QQ 下拉刷新的實(shí)現(xiàn)和蘋果版不一樣,就忽略 Android 了。如果沒有蘋果手機(jī),我也沒有辦法。。。),下來刷新看一下 QQ 下拉刷新時(shí)的樣貌。
How
本項(xiàng)目的實(shí)現(xiàn)是基于以下博客的幫助
Path之貝塞爾曲線:這個(gè)講的比較全面,可以運(yùn)行一下樣例,對(duì)學(xué)習(xí)貝塞爾曲線有幫助
BezierDemo:這個(gè)是上面博客提到的一個(gè)項(xiàng)目,也正是這個(gè)項(xiàng)目,才發(fā)現(xiàn),QQ 的實(shí)現(xiàn)可能和貝塞爾曲線有關(guān)系(個(gè)人猜測(cè)而已,畢竟我就是利用貝塞爾曲線完成的)
其中,我在學(xué)習(xí)上面的Demo時(shí),通過自己稍微的改動(dòng),發(fā)下了如下的效果

大家再對(duì)比一下 QQ 的下拉刷新,發(fā)現(xiàn)是不是很相似,既然發(fā)現(xiàn)了這個(gè),那么接下來就是考慮怎么移植到下拉刷新的頭部了(這里用的是我自己寫的 XRecyclerView 控件,并稍微對(duì)齊改造了一下)
實(shí)現(xiàn)
實(shí)現(xiàn)上面的效果需要的知識(shí)儲(chǔ)備有
- 貝賽爾曲線:這次的實(shí)現(xiàn)就是和它有關(guān)系
- XRecyclerView:一款自己寫的,為 RecyclerView 添加下拉刷新和上拉加載的控件(歡迎大家使用,PR,喜歡的可以 star 一下)
第一步
如何利用貝塞爾曲線繪制出上圖顯示的效果呢?核心代碼如下:
float offsetX = mRadius;
float x1 = mStartX - offsetX;
float y1 = mStartY;
float x4 = mStartX + offsetX;
float y4 = mStartY;
float x2 = mStartX - offsetX;
float y2 = y;
float x3 = mStartX + offsetX;
float y3 = y;
mPath.reset();
mPath.moveTo(x1, y1);
mPath.quadTo(mStartX, mStartY, x2 + mStep, y2);
mPath.lineTo(x3 - mStep, y3);
mPath.quadTo(mStartX, mStartY, x4, y4);
mPath.lineTo(x1, y1);
代碼很少,其實(shí)就是找到貝塞爾曲線關(guān)鍵的兩點(diǎn):控制點(diǎn)和坐標(biāo)點(diǎn)
第二步
如何將布局放到 XRecyclerView 中呢?
XRecyclerview 添加頭部布局很簡(jiǎn)單,下面代碼就可以實(shí)現(xiàn)
mHeaderView = LayoutInflater.from(this).inflate(R.layout.qq_header_view, null);
mXRecyclerView.addHeaderView(mHeaderView, 50);
但是,有一個(gè)問題,QQ 的下拉刷新,會(huì)隨著向下拉的距離增大而變化,而 XRecyclerView 中并沒有實(shí)現(xiàn)這樣的接口,所以,需要對(duì) XRecyclerView 進(jìn)行改造,為 XRecyclerView 添加兩個(gè)接口回調(diào),分別為
/** 用于監(jiān)控是否刷新完成,用于隱藏布局*/
public interface OnRefreshCompleteListenter {
void refreshComplete();
}
/** 用于記錄下拉頭部的距離,方便形成圓抽長的效果*/
public interface OnRefreshDistanceListener {
void refreshDistance(int dy);
}
有了上面兩個(gè)接口,接下來就好辦了
第三步
根據(jù)接口實(shí)現(xiàn)功能
mXRecyclerView.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh() {
refreshData();
qqRefreshView.start();
}
});
mXRecyclerView.setOnRefreshDistanceListener(new OnRefreshDistanceListener() {
@Override
public void refreshDistance(int dy) {
qqRefreshView.setVY(dy);
}
});
mXRecyclerView.setOnRefreshCompleteListenter(new OnRefreshCompleteListenter() {
@Override
public void refreshComplete() {
qqRefreshView.stop();
}
});
其中, qqRefreshView.start() 和 qqRefreshView.stop() 用于實(shí)現(xiàn) QQ 水滴斷裂后的圓盤旋轉(zhuǎn)的效果
qqRefreshView.setVY(dy) 是將下滑的距離傳入布局中,方便讓圓逐漸抽長至斷裂
至此,就可以實(shí)現(xiàn)類似 QQ 下拉刷新的布局和操作。
不足
雖然實(shí)現(xiàn)了大概的樣貌,但是還有很多細(xì)節(jié)沒有完善好
- 下拉刷新的圓抽長的過度效果和 QQ 其實(shí)是有差距的,主要還是貝塞爾曲線公式?jīng)]有調(diào)整到完美
- QQ 的下拉刷新是等圓全部出來后,繼續(xù)往下拉才會(huì)變的修長;而目前實(shí)現(xiàn)的是,下拉的時(shí)候就開始便修長,這點(diǎn)在細(xì)節(jié)體驗(yàn)上會(huì)差一些
總結(jié)
雖然效果差強(qiáng)人意,但是在實(shí)現(xiàn)過程中,還是有很多的收獲,同時(shí)也發(fā)現(xiàn)了自己編寫的 XRecyclerView 的一些不足,學(xué)習(xí)永無止境,F(xiàn)or Google & Android,I Do。