Android實現(xiàn)仿魅族日歷首頁功能
flyme5.0增加了很多優(yōu)美的動畫和交互,界面也變得相當精致。我手頭現(xiàn)在就用著魅族MX5,感覺還不錯哇!經(jīng)常會打開它的日歷看計劃等,感覺它首頁的滑動效果還不錯,就試著實現(xiàn)一把。

效果分析
1 該首頁由兩部分組成:GridView展示的日歷視圖,下方的內(nèi)容視圖
2 當選中日歷的某一天后,向上滑動,內(nèi)容視圖會不斷的向上移動,直到只含有選中日期的那一行顯示為止
3 伴隨著內(nèi)容視圖向上移動,日歷視圖也會跟隨向上移動
4 還有一個效果該圖沒能體現(xiàn):當為向上滑動,松手后,視圖會自動向上隱藏;當為向上滑動時,松手后,視圖會自動向下展開
實現(xiàn)邏輯
該view繼承LinearLayout,日歷視圖和內(nèi)容視圖上下放置
1 寬高計算
// 內(nèi)容視圖的實際高度為該控件高度減去gridview一行的高度
// 這個不難得出結(jié)論,因為向上移動時,內(nèi)容視圖可以移動直到只含有選中日期的那一行顯示為止
int heightSpec = MeasureSpec.makeMeasureSpec(
getMeasuredHeight() - Tool.dip2px(mContext, 60),
MeasureSpec.EXACTLY);
contentView.measure(widthMeasureSpec, heightSpec);
2 獲取可滑動的距離
// 當視圖大小發(fā)生變化時,會回調(diào)該方法,可在這個方法獲取GridView的高度
// 而內(nèi)容視圖可滑動的距離就是:GridView的高度減去其一行的高度
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
swipHeight = gridView.getMeasuredHeight() - Tool.dip2px(mContext, 60);
}
3 事件處理
3.1 事件攔截
// 有兩種情況需要攔截:
1 向上滑動,并且contentView還沒達到最大的滑動距離時
2 向下滑動,并且contentView還沒有滑動到到底時
case MotionEvent.ACTION_MOVE:
float dy = y - mLastY;
if (Math.abs(dy) > mTouchSlop) {
if ((dy > 0 && contentView.getTranslationY() <= 0)
|| (dy < 0 && contentView.getTranslationY() >= -swipHeight)) {
mLastY = y;
return true;
}
}
break;
3.2 onTouchEvent的處理
case MotionEvent.ACTION_MOVE:
float dy = y - mLastY;
// 邊界的判斷,保證下滑只能移動到原來的位置
if (dy > 0 && contentView.getTranslationY() + dy >= 0) {
contentView.setTranslationY(0);
translationSwipView();
return true;
}
// 邊界的判斷,保證移動的位置最大為可滑動距離
if (dy < 0 && contentView.getTranslationY() + dy <= -swipHeight) {
contentView.setTranslationY(-swipHeight);
translationSwipView();
return true;
}
// 根據(jù)滑動的距離,移動contentView
contentView.setTranslationY(contentView.getTranslationY() + dy);
// 主要是讓日歷視圖伴隨contentView的移動而發(fā)生偏移
translationSwipView();
mLastY = y;
break;
3.3 日歷視圖的偏移
// 通過內(nèi)容視圖滑動的比例,計算出日歷視圖需要移動的距離,并進行移動(保證等比移動)
private void translationSwipView() {
float percent = contentView.getTranslationY() * 1.0f / swipHeight;
gridView.setTranslationY(translatDirection * percent);
}
3.4 ACTION_UP事件處理
case MotionEvent.ACTION_UP:
// 假如已經(jīng)是隱藏狀態(tài)或者是顯示狀態(tài),不用處理
if (contentView.getTranslationY() == 0
|| contentView.getTranslationY() == swipHeight) {
break;
}
// 假如松手的坐標比ACTION_DOWN的坐標要大,證明是向下滑動,通過動畫顯示日歷視圖
if (event.getY() - downY > 0) {
animateShow();
} else {
// 假如松手的坐標比ACTION_DOWN的坐標要小,證明是向上滑動,通過動畫隱藏日歷視圖
animateHide();
}
break;
}
3.5 對外處理
// 通過該方法通知該view,日歷視圖選擇的item為哪個,通過這個設(shè)置計算出日歷視圖需要移動的距離
public void setSelectPosition(int selectPosition) {
int line = (selectPosition + 7) / 7;
translatDirection = (line - 1) * Tool.dip2px(mContext, 60);
}
結(jié)語
哈哈,一個仿魅族日歷的視圖就這樣搞定啦。感謝大家對腳本之家的支持。
相關(guān)文章
Android 獲取內(nèi)外SD卡路徑幾種方法總結(jié)
這篇文章主要介紹了Android 獲得內(nèi)外SD卡路徑幾種方法總結(jié)的相關(guān)資料,需要的朋友可以參考下2016-12-12
Android編程入門之HelloWorld項目目錄結(jié)構(gòu)分析
這篇文章主要介紹了Android編程入門之HelloWorld項目目錄結(jié)構(gòu)分析,較為詳細的分析了Android項目的目錄結(jié)構(gòu)與具體作用,需要的朋友可以參考下2015-12-12
Android使用CoordinatorLayout實現(xiàn)底部彈出菜單
這篇文章主要為大家詳細介紹了Android使用CoordinatorLayout實現(xiàn)底部彈出菜單,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-11-11
Android用viewPager2實現(xiàn)UI界面翻頁滾動的效果
自學(xué)Android中,然后需要實現(xiàn)UI頁面翻頁滑動的效果,例如頭條的功能 我這邊利用了viewPager2的翻頁功能,具體流程如下:2021-05-05
Android應(yīng)用程序窗口(Activity)窗口對象(Window)創(chuàng)建指南
本文將詳細介紹Android應(yīng)用程序窗口(Activity)的窗口對象(Window)的創(chuàng)建過程,需要了解的朋友可以參考下2012-12-12

