今年上海的七月和八月在小編看來是有特殊紀念意義的夏季蚁署。哈哈,感覺總是那么美好蚂四,雖然今年確實很熱光戈,但是好在正真炎熱的夏季已經(jīng)過去了。行了吧遂赠,寒暄的話久妆,小編不說了;那現(xiàn)在開始跷睦,小編直奔主題吧:自定義時間軸的實現(xiàn)筷弦;首先,根據(jù)公司產(chǎn)品的設計需要寫一個上有刻度和時間顯示的時間軸送讲,下有具體的日期可選與否的進度條奸笤,那首先來看看小編實現(xiàn)的效果吧。
以上便是小編實現(xiàn)后的效果哼鬓。小編為了方便顯示該控件的功能监右,特意截圖了三張不同時間軸和三張不同顯示可選和不可選的進度條的時間段。
實現(xiàn)思路:1.根據(jù)接口傳來的數(shù)據(jù)來選擇性的繪制需要顯示的刻度時刻的刻度尺异希。2.根據(jù)接口傳來的數(shù)據(jù)來顯示繪制可選與不可選的進度條健盒。
小編覺得一般情況下,兄弟們看到這種需求一般都是這樣寫的称簿,但是還是有個我們不得不考慮的問題扣癣。那就是后臺接口會傳給我們什么樣的數(shù)據(jù)結構呢。這個是需要考慮的問題憨降。這個也是本次自定義控件的最難點所在父虑,他的數(shù)據(jù)結構是什么樣的呢?
也許各位兄弟們可能有更好的辦法或更可行的數(shù)據(jù)結構的排布授药,但是在這里小編先介紹下我們的數(shù)據(jù)結構的排布士嚎。先展示下小編我們請求接口返回的數(shù)據(jù)結構吧。
首先悔叽,小編簡單介紹下我們自己的數(shù)據(jù)結構的字段莱衩,其中的time字段對應的分別是整個時間軸的最小起始時刻和整個時間軸的最大結束時刻。對于每個刻度的間隔時間娇澎,我們這邊是根據(jù)后臺數(shù)據(jù)cutTimePoint的決定的笨蚁,最后剩下的dayArray便是選中的時間段。其次趟庄,我們還要對這些數(shù)據(jù)字段進行處理展示括细。那么問題來了,對于刻度尺的時間點戚啥,和刻度尺的繪制怎么實現(xiàn)呢勒极?
這里小編先說下我的實現(xiàn)過程吧
1.根據(jù)時間軸的最小時刻,最大時刻和刻度間隔時間得到可顯示的時間點的集合虑鼎,代碼如下:
```
/**
* 刻度上顯示的時間數(shù)值 單位:小時
*
*@param startTime ?最小時刻點
*@param distanceTime ?刻度間隔時間(分鐘)
*@return
*/
privateListgetScaleTextList(intstartTime,intdistanceTime){
List mResultList =newArrayList<>();
intintegerCount = mScaleCount /2;//? 把最后的一個時間點加上
for(inti =0; i < integerCount +1; i++) {
// 分鐘
intresult = startTime +2* distanceTime * i;
// 取小時整數(shù)
String hourStr = String.valueOf((result /60));
mResultList.add(hourStr);
}
return ?mResultList;
}
```
2.根據(jù)得到可繪制刻度時間尺的實現(xiàn)手機像素距離辱匿,再次得到刻度間隔實際對應的手機像素距離
一般我們會重寫onMeasure方法得到實際的間隔,小編得到的方法如下:
this.mScaleMargin = getFloatValue((viewWidth - leftMargin - rightMargin), mScaleCount);
3.開始繪制時間刻度吃的時間軸炫彩,廢話不多說了匾七,小編直接上代碼:
```
/**
* 畫刻度
*
*@paramcanvas
*/
privatevoiddrawScale(Canvas canvas){
if(mScaleCount ==0)
return;
for(inti =1; i < mScaleCount +3; i++) {
if(i >=2) {
if(i %2==0) {// 雙數(shù)大刻度
canvas.drawLine(leftMargin + (i -2) * mScaleMargin, mRectHeight, leftMargin + (i -2) * mScaleMargin, mRectHeight - mScaleMaxHeight, scalePaint);
canvas.drawText(mScaleTextList.get(i /2-1), leftMargin + (i -2) * mScaleMargin, mRectHeight - mScaleMaxHeight -10, scalePaint);
}else{// 單數(shù)小刻度
canvas.drawLine(leftMargin + (i -2) * mScaleMargin, mRectHeight, leftMargin + (i -2) * mScaleMargin, mRectHeight - mScaleHeight, scalePaint);
}
}else{// 寫時段字樣
canvas.drawText(title, titleMargin, mRectHeight - mScaleHeight, textPaint);
}
}
canvas.drawLine(0, mRectHeight, viewWidth, mRectHeight, scalePaint);
//? ? ? ? canvas.drawLine(leftMargin,mRectHeight,viewWidth -rightMargin,mRectHeight,progressPaint);
}
```
4.當我們繪制好了刻度尺的顯示時間軸,接下來繪制時間可選與不可選擇的進度條江兢。
在這里主要有倆步非常重要昨忆,第一步,根據(jù)接口返回的時間段得到可預約的時間 所占的 實際寬度杉允。實現(xiàn)方法如下:
```
/**
* 可預約的時間 所占的 實際寬度
*
*@parambookTime
*/
private ?float ? getTimePointFactViewWidth(BookTime.TimePoint bookTime){
if(bookTime ==null)
return0;
if(distanceLong ==0)
return0;
intstartTime = timeToMinter(bookTime.startTime);
intendTime = timeToMinter(bookTime.endTime);
intdistance = Math.abs(endTime - startTime);
if(distance ==0)
return0;
intfactScaleWidth = viewWidth - leftMargin - rightMargin;// 實際顯示刻度的ViewWidth
floatratioToMinter = getFloatValue(factScaleWidth, distanceLong);// 每分鐘所占的比例
float ?bookTimeWidth = distance * ratioToMinter;
return ?bookTimeWidth;
}
```
第二步邑贴,根據(jù)接口返回的時間段的起始時刻點得到在進度條中開始繪制的位置席里,實現(xiàn)方法如下:
```
/**
* 得到開始繪制的位置
*
*@parambookTime
*/
privatefloatgetStartDrawProgressPosition(BookTime.TimePoint bookTime){
if(distanceLong ==0)
return0;
intfactScaleWidth = viewWidth - leftMargin - rightMargin;// 實際顯示刻度的ViewWidth
floatratioToMinter = getFloatValue(factScaleWidth, distanceLong);// 每分鐘所占的比例
intstartTime = timeToMinter(bookTime.startTime);
if(allStartTime <0)
return0;
if(startTime < allStartTime)
return0;
intdistance = Math.abs((startTime - allStartTime));// 兩個啟動的時間間距
return(distance * ratioToMinter);
}
```
根據(jù)以上兩步得到每次繪制時間段的在實際手機上繪制的實際位置和繪制的距離,那么接下來就是需要繪制顯示的時間進度條拢驾;小編廢話不多說了奖磁,直接上代碼了:
```
/**
* 畫預約進度條
*
*@paramcanvas
*/
privatevoiddrawBookProgress(Canvas canvas){
if(ListUtils.isEmpty(bookTimeList))
return;
linePaint.setStrokeWidth(stringHeight *2);
progressPaint.setStrokeWidth(stringHeight *2);
inti =1;
for(BookTime bookTime : bookTimeList) {
// 繪制默認進度條
canvas.drawText((i <= defaultDateSize ? bookTime.dateDesc : bookTime.shortDate), titleMargin, mRectHeight + mRectHeight /4* i + stringHeight * (i +1), textPaint);// 寫字
canvas.drawLine(leftMargin, mRectHeight + mRectHeight /4* i + stringHeight * i, viewWidth - rightMargin, mRectHeight + mRectHeight /4* i + stringHeight * i, linePaint);// 畫進度
// 繪制有色進度條
if(!ListUtils.isEmpty(bookTime.timeVoList)) {
List timeVoList = bookTime.timeVoList;
for(BookTime.TimePoint timePoint : timeVoList) {
floatdrawFactWidth = getTimePointFactViewWidth(timePoint);
floatstartDrawPosition = getStartDrawProgressPosition(timePoint);
floatstartX = leftMargin + startDrawPosition;
canvas.drawLine(startX, mRectHeight + mRectHeight /4* i + stringHeight * i, drawFactWidth + startX, mRectHeight + mRectHeight /4* i + stringHeight * i, progressPaint);// 繪制可預約進度
}
}
i++;
}
}
```
以上是小編實現(xiàn)此控件的實現(xiàn)過程。
感覺以上的實現(xiàn)過程相當還是比較簡單的繁疤,就是有些思路實現(xiàn)起來比較繞還有就是有些細節(jié)處理起來比較撓咖为。其他的處理起來還是相當挺簡單的。在本次代碼的處理中最難的部分就是對時間段和實際手機像素距離的轉化處理稠腊。