




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
【移動應(yīng)用開發(fā)技術(shù)】使用Android怎么構(gòu)造一個滾輪控件
這篇文章將為大家詳細(xì)講解有關(guān)使用Android怎么構(gòu)造一個滾輪控件,文章內(nèi)容質(zhì)量較高,因此在下分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。自定義控件無非是measure,draw,layout三個過程,如果要支持手勢動作,那么就再加上touch。measure測量過程比較簡單,以文本大小所需要的尺寸,再加上padding。@Override
protected
void
onMeasure(int
widthMeasureSpec,
int
heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec,
heightMeasureSpec);
int
wantWith
=
getPaddingLeft()
+
getPaddingRight();
int
wantHeight
=
getPaddingTop()
+
getPaddingBottom();
calculateTextSize();
wantWith
+=
mTextRect.width();
//可見
item
數(shù)量計算文本尺寸
if
(mVisibilityCount
>
0)
{
wantHeight
+=
mTextRect.height()
*
mVisibilityCount;
}
else
{
wantHeight
+=
mTextRect.height()
*
DEFALUT_VISIBILITY_COUNT;
}
setMeasuredDimension(
resolveSize(wantWith,
widthMeasureSpec),
resolveSize(wantHeight,
heightMeasureSpec)
);
mNeedCalculate
=
true;
}draw繪制過程是通過canvas的位移去繪制不同位置的部件,包括文本內(nèi)容和選擇框之類的,這里可能需要注意下的地方是,不要一次性把所有文本繪制出來,只需要繪制可見文本即可。@Override
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
if
(hasDataSource())
{
//
省略
//
這里計算下需要繪制的數(shù)量,+2
只是確保不會出現(xiàn)空白
final
int
drawCount
=
mContentRect.height()
/
mTextRect.height()
+
2;
int
invisibleCount
=
0;
int
dy
=
-mDistanceY;
//
省略
//
通過
translate
繪制文本
for
(int
i
=
0;
(i
<
drawCount
&&
mDataSources.size()
>
(invisibleCount
+
i));
i++)
{
final
int
position
=
invisibleCount
+
i;
String
text
=
mDataSources.get(position);
if
(i
>
0)
{
canvas.translate(0,
mTextRect.height());
}
final
PointF
pointF
=
calculateTextGravity(text);
mTextPaint.setTextSize(mTextSize);
if
(position
==
selctPosition)
{
mTextPaint.setColor(mSelectedTextColor);
}
else
{
mTextPaint.setColor(mNormalTextColor);
}
canvas.drawText(text,
pointF.x,
pointF.y,
mTextPaint);
}
canvas.restoreToCount(saveCount);
}
//
繪制選擇框
int
saveCount
=
canvas.save();
mDrawPaint.setColor(mSelectedLineColor);
canvas.translate(mContentRect.left,
mContentRect.top);
canvas.drawLine(
mSelctedRect.left,
mSelctedRect.top,
mSelctedRect.right,
mSelctedRect.top,
mDrawPaint
);
canvas.drawLine(
mSelctedRect.left,
mSelctedRect.bottom,
mSelctedRect.right,
mSelctedRect.bottom,
mDrawPaint
);
canvas.restoreToCount(saveCount);
}layout因為這個控件是繼承于View,所以不需要處理onLayout。touch如果對touchevent分發(fā)流程熟悉的話,那么很多處理可以說是模版代碼,可以參考NestedScrollView、ScrollView。在onInterceptTouchEvent中,判斷是否開始進(jìn)行拖動手勢,保存到變量(mIsBeingDragged)中://
多指處理
final
int
pointerIndex
=
ev.findPointerIndex(activePointerId);
if
(pointerIndex
==
-1)
{
Log.e(TAG,
"Invalid
pointerId="
+
activePointerId
+
"
in
onInterceptTouchEvent");
break;
}
final
int
y
=
(int)
ev.getY(pointerIndex);
final
int
yDiff
=
Math.abs(y
-
mLastMotionY);
if
(yDiff
>
mTouchSlop
&&
(getNestedScrollAxes()
&
SCROLL_AXIS_VERTICAL)
==
0)
{
//
開始拖動
mIsBeingDragged
=
true;
mLastMotionY
=
y;
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
mNestedYOffset
=
0;
if
(mScrollStrictSpan
==
null)
{
mScrollStrictSpan
=
StrictMode.enterCriticalSpan("ScrollView-scroll");
}
final
ViewParent
parent
=
getParent();
if
(parent
!=
null)
{
//
禁止父控件攔截事件分發(fā)
parent.requestDisallowInterceptTouchEvent(true);
}
}在onTouchEvent中對ACTION_MOVR進(jìn)行拖動的處理,如果支持嵌套滾動,那么會預(yù)先進(jìn)行嵌套滾動的分發(fā)。如果支持陰影效果,那么使用EdgeEffect。//
和
onInterceptTouchEvent
一樣進(jìn)行拖動手勢開始的判斷
if
(!mIsBeingDragged
&&
Math.abs(deltaY)
>
mTouchSlop)
{
final
ViewParent
parent
=
getParent();
if
(parent
!=
null)
{
parent.requestDisallowInterceptTouchEvent(true);
}
mIsBeingDragged
=
true;
if
(deltaY
>
0)
{
deltaY
-=
mTouchSlop;
}
else
{
deltaY
+=
mTouchSlop;
}
}
if
(mIsBeingDragged)
{
//
拖動處理
//
Scroll
to
follow
the
motion
event
mLastMotionY
=
y
-
mScrollOffset[1];
final
int
oldY
=
mScrollY;
final
int
range
=
getScrollRange();
final
int
overscrollMode
=
getOverScrollMode();
boolean
canOverscroll
=
overscrollMode
==
OVER_SCROLL_ALWAYS
||
(overscrollMode
==
OVER_SCROLL_IF_CONTENT_SCROLLS
&&
range
>
0);
//
Calling
overScrollBy
will
call
onOverScrolled,
which
//
calls
onScrollChanged
if
applicable.
//
滾動處理,overScrollBy
中會處理嵌套滾動預(yù)先分發(fā)
if
(overScrollBy(0,
deltaY,
0,
mScrollY,
0,
range,
0,
mOverscrollDistance,
true)
&&
!hasNestedScrollingParent())
{
//
Break
our
velocity
if
we
hit
a
scroll
barrier.
mVelocityTracker.clear();
}
final
int
scrolledDeltaY
=
mScrollY
-
oldY;
final
int
unconsumedY
=
deltaY
-
scrolledDeltaY;
//
嵌套滾動
if
(dispatchNestedScroll(0,
scrolledDeltaY,
0,
unconsumedY,
mScrollOffset))
{
mLastMotionY
-=
mScrollOffset[1];
vtev.offsetLocation(0,
mScrollOffset[1]);
mNestedYOffset
+=
mScrollOffset[1];
}
else
if
(canOverscroll)
{
final
int
pulledToY
=
oldY
+
deltaY;
//
拖動陰影效果
if
(pulledToY
<
0)
{
mEdgeGlowTop.onPull((float)
deltaY
/
getHeight(),
ev.getX(activePointerIndex)
/
getWidth());
if
(!mEdgeGlowBottom.isFinished())
{
mEdgeGlowBottom.onRelease();
}
}
else
if
(pulledToY
>
range)
{
mEdgeGlowBottom.onPull((float)
deltaY
/
getHeight(),
1.f
-
ev.getX(activePointerIndex)
/
getWidth());
if
(!mEdgeGlowTop.isFinished())
{
mEdgeGlowTop.onRelease();
}
}
if
(mEdgeGlowTop
!=
null
&&
(!mEdgeGlowTop.isFinished()
||
!mEdgeGlowBottom.isFinished()))
{
postInvalidateOnAnimation();
}
}
}支持滾動手勢的控件,一般都會支持fling手勢,可以理解為慣性滾動。這也是模版代碼,在onTouchEvent中對ACTION_UP中對拖動速度進(jìn)行分析。case
MotionEvent.ACTION_UP:
if
(mIsBeingDragged)
{
final
VelocityTracker
velocityTracker
=
mVelocityTracker;
velocityTputeCurrentVelocity(1000,
mMaximumVelocity);
//
獲取拖動速度
int
initialVelocity
=
(int)
velocityTracker.getYVelocity(mActivePointerId);
if
((Math.abs(initialVelocity)
>
mMinimumVelocity))
{
//
可以進(jìn)行
fling
操作
flingWithNestedDispatch(-initialVelocity);
}
else
if
(mScroller.springBack(mScrollX,
mScrollY,
0,
0,
0,
getScrollRange()))
{
postInvalidateOnAnimation();
}
mActivePointerId
=
INVALID_POINTER;
endDrag();
}
break;具體的代碼可以在ScrollView中閱讀?;氐轿覍崿F(xiàn)的自定義控件來,對touchevent的處理代碼可以說是和系統(tǒng)控件的處理沒有什么兩樣,在獲取到拖動的距離后,根據(jù)這個值繪制不同位置的可見區(qū)域。這里多了兩個處理是:第一拖動結(jié)束后,進(jìn)行復(fù)位處理。拖動結(jié)束后,選擇框如果停留在兩個item之間,那么根據(jù)和兩個item的距離進(jìn)行比較,選擇更近的item。private
void
correctionDistanceY()
{
if
(mDistanceY
%
mTextRect.height()
!=
0)
{
int
position
=
mDis
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度文化創(chuàng)意產(chǎn)業(yè)方借款協(xié)議
- 二零二五年度拖欠工資解除勞動合同實務(wù)案例范文
- 二零二五年度環(huán)保產(chǎn)業(yè)合作項目終止協(xié)議范本
- 非全日制合同制員工2025年度工作績效評估及獎勵合同
- 二零二五年度辣椒種植基地節(jié)水灌溉技術(shù)合同
- 二零二五年度工業(yè)氣體產(chǎn)業(yè)園區(qū)共建合作協(xié)議
- 二零二五年度醫(yī)院聘用護(hù)士勞動合同(護(hù)理心理健康)
- 幼兒園保育員聘用合同書(二零二五年度)-幼兒成長記錄合作
- 二零二五年度車輛維修事故私了處理流程合同
- 二零二五年度茶樓租賃合同茶樓與文化活動策劃合作框架
- 2024年鄭州市公安機關(guān)招聘警務(wù)輔助人員筆試真題
- 2025年黑龍江農(nóng)墾職業(yè)學(xué)院單招職業(yè)傾向性測試題庫匯編
- 2.3品味美好情感 課 件 -2024-2025學(xué)年統(tǒng)編版道德與法治七年級下冊
- 2025年01月明光市司法局司法協(xié)理員7人筆試歷年典型考題(歷年真題考點)解題思路附帶答案詳解
- 整體施工勞務(wù)服務(wù)方案
- 第六節(jié)-固定收益證券知識分享
- 2024 貴州公務(wù)員考試行測真題(省直)
- 機械制造技術(shù)基礎(chǔ)(課程課件完整版)
- 《預(yù)防未成年人犯罪》課件(圖文)
- XX小學(xué)學(xué)生心理健康檔案(一生一案)
- 催化裂化油漿系統(tǒng)結(jié)焦原因及對策
評論
0/150
提交評論