日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Android 界面滑动实现---Scroller类 从源码和开发文档中学习(让你的布局动起来)...

發(fā)布時(shí)間:2025/4/14 72 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 界面滑动实现---Scroller类 从源码和开发文档中学习(让你的布局动起来)... 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
在android學(xué)習(xí)中,動(dòng)作交互是軟件中重要的一部分,其中的Scroller就是提供了拖動(dòng)效果的類,在網(wǎng)上,比如說(shuō)一些Launcher實(shí)現(xiàn)滑屏都可以通過(guò)這個(gè)類去實(shí)現(xiàn)。。 ? 例子相關(guān)博文:Android 仿 窗簾效果 和 登錄界面拖動(dòng)效果 (Scroller類的應(yīng)用) 附 2個(gè)DEMO及源碼 ? 在廣泛使用的側(cè)邊滑動(dòng)導(dǎo)航開(kāi)源庫(kù) --SlidingLayer其實(shí)就是使用到了Scroller類進(jìn)行的實(shí)現(xiàn),下載地址:GITHUB? ,下面要講的不是這個(gè)庫(kù),而是這個(gè)庫(kù)的實(shí)現(xiàn)過(guò)程中使用到的---Scroller類,懂了之后你看庫(kù)的源碼就知道,原來(lái)它是這樣實(shí)現(xiàn)的。 ? ? Scroller類使用過(guò)程中,懂得以下機(jī)制可能會(huì)對(duì)開(kāi)發(fā)更有幫助: ? 1.視圖的VIEW的自定義以及其在屏幕中布局。 ? 2.scrollTo()和scrollBy()方法的作用區(qū)別 ? ? 可以點(diǎn)擊此處了解:android 布局之滑動(dòng)探究 scrollTo 和 scrollBy 方法使用說(shuō)明 ? 3.屏幕中的觸摸事件分發(fā)機(jī)制(這一塊在涉及到觸摸的任何情況下都十分重要) ? ? ? 首先看看發(fā)開(kāi)文檔里面說(shuō)了些什么:

android發(fā)開(kāi)文檔

? 開(kāi)發(fā)文檔參考鏈接:http://developer.android.com/reference/android/widget/Scroller.html

Scroller

一.結(jié)構(gòu)關(guān)系

extends?Object ?

二.概述

Class Overview


This class encapsulates scrolling. You can use scrollers (Scroller?or?OverScroller) to collect the data you need to produce a scrolling animation—for example, in response to a fling gesture. Scrollers track scroll offsets for you over time, but they don't automatically apply those positions to your view. It's your responsibility to get and apply new coordinates at a rate that will make the scrolling animation look smooth.

?

?

這個(gè)類封裝了滾動(dòng)操作,你可以根據(jù)你的手勢(shì)對(duì)界面進(jìn)行更加平滑的滾動(dòng)操作。 ?

?

To track the changing positions of the x/y coordinates, use?computeScrollOffset(). The method returns a boolean to indicate whether the scroller is finished. If it isn't, it means that a fling or programmatic pan operation is still in progress. You can use this method to find the current offsets of the x and y coordinates, for example:

?

跟蹤變化的x / y坐標(biāo)的位置,通過(guò)computeScrollOffset()方法監(jiān)聽(tīng)返回的布爾值來(lái)指示滾動(dòng)動(dòng)作是否完成。如果返回為false,說(shuō)明滾動(dòng)已經(jīng)結(jié)束。返回true,它意味著操作仍在進(jìn)行中。您可以使用

int?currX?=?mScroller.getCurrX();????//滾動(dòng)的X滾動(dòng)距離

int?currY?=?mScroller.getCurrY();? ? ?//滾動(dòng)的y滾動(dòng)距離

這個(gè)方法來(lái)找到當(dāng)前的x和y坐標(biāo)的偏移量。

?

三.構(gòu)造函數(shù)

Public Constructors
? Scroller(Context?context) Create a Scroller with the default duration and interpolator.
? Scroller(Context?context,?Interpolator?interpolator) Create a Scroller with the specified interpolator.
? Scroller(Context?context,?Interpolator?interpolator, boolean flywheel) Create a Scroller with the specified interpolator.

?Interpolator?interpolator 表示的是動(dòng)畫插入器,你可以設(shè)定相應(yīng)的效果給它。

?

Interpolator

implements?TimeInterpolator

android.view.animation.Interpolator

?

Known Indirect Subclasses

AccelerateDecelerateInterpolator,?AccelerateInterpolator,?AnticipateInterpolator,?AnticipateOvershootInterpolator,?BounceInterpolator,?CycleInterpolator,DecelerateInterpolator,?LinearInterpolator,?OvershootInterpolator

?

AccelerateDecelerateInterpolator? ? ?動(dòng)畫效果:開(kāi)始和結(jié)束都是緩慢的,通過(guò)中間時(shí)候加速

AccelerateInterpolator, ? ? ?動(dòng)畫效果:開(kāi)始緩慢,之后加速

AnticipateInterpolator, ??? ??動(dòng)畫效果:開(kāi)始后退,然后前進(jìn)

AnticipateOvershootInterpolator,? ?動(dòng)畫效果:開(kāi)始后退,之后前進(jìn)并超過(guò)終點(diǎn)位置,最終退回到終點(diǎn)

BounceInterpolator, ? ? ? ?動(dòng)畫效果:慢慢反彈到,彈性衰減到結(jié)束

CycleInterpolator, ? ? ? ? ?動(dòng)畫效果:重復(fù)循環(huán)動(dòng)畫,速度變化遵循正弦定律

DecelerateInterpolator, ? ? ? ?動(dòng)畫效果:剛開(kāi)始快速,之后減速

LinearInterpolator, ? ? ? ??動(dòng)畫效果:不斷的變化

OvershootInterpolator?? ? ? ??動(dòng)畫效果:像前超越最終點(diǎn)然后回來(lái)

?

可以通過(guò)初始化構(gòu)造方法Scroller(Context?context,?Interpolator?interpolator)給它相應(yīng)的動(dòng)畫效果。

?

Interpolator interpolator = new BounceInterpolator();

?

?

四.公共方法

?

Public Methods
void abortAnimation() ? ?停止動(dòng)畫,滾到最終的x,y位置中止動(dòng)畫
boolean computeScrollOffset() ? 當(dāng)你想要知道新的位置時(shí)候,調(diào)用該方法。返回true:動(dòng)畫沒(méi)結(jié)束
void extendDuration(int extend) ? 延長(zhǎng)滾動(dòng)動(dòng)畫的時(shí)間。extend表示延遲時(shí)間(單位為毫秒)
void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY) 在fling(快速滑動(dòng),觸摸屏幕后快意移動(dòng)松開(kāi))的手勢(shì)基礎(chǔ)上開(kāi)始滾動(dòng),滾動(dòng)距離取決于fling的初速度。
final void forceFinished(boolean finished) ? 強(qiáng)制終止?jié)L動(dòng)。
float getCurrVelocity() ? 返回當(dāng)前的速度
final int getCurrX() ? ?返回當(dāng)前滾動(dòng)的X方向的偏移量(距離原點(diǎn)X軸方向)
final int getCurrY() ??返回當(dāng)前滾動(dòng)的Y方向的偏移量(距離原點(diǎn)Y軸方向)
final int getDuration() ? 返回滾動(dòng)事件的持續(xù)時(shí)間(毫秒)
final int getFinalX() ?返回滾動(dòng)結(jié)束的X方向的偏移量(注:只針對(duì)fling 手勢(shì)有效)(距離原點(diǎn)X軸方向)
final int getFinalY()?? 返回滾動(dòng)結(jié)束的Y方向的偏移量(注:只針對(duì)fling 手勢(shì)有效)(距離原點(diǎn)Y軸方向)
final int getStartX() ? 返回滾動(dòng)起始點(diǎn)的X方向偏移量(距離原點(diǎn)X軸方向)
final int getStartY() ?返回滾動(dòng)起始點(diǎn)的Y方向偏移量.(距離原點(diǎn)Y軸方向)
final boolean isFinished() ? 返回scroller滾動(dòng)是否結(jié)束,true:滾動(dòng)結(jié)束 ? ?false:還在滾動(dòng)
void setFinalX(int newX) ?設(shè)置scroller的終止時(shí)X方向偏移量
void setFinalY(int newY) ??設(shè)置scroller的終止時(shí)Y方向偏移量
final void setFriction(float friction) The amount of friction applied to flings.
void startScroll(int startX, int startY, int dx, int dy) 提供起始點(diǎn)和滾動(dòng)距離,調(diào)用該方法進(jìn)行滾動(dòng)。(此處默認(rèn)時(shí)間為250ms)
void startScroll(int startX, int startY, int dx, int dy, int duration) 提供起始點(diǎn)和滾動(dòng)距離以及滾動(dòng)時(shí)間,調(diào)用該方法進(jìn)行滾動(dòng)。
int timePassed() ?返回自滾動(dòng)開(kāi)始經(jīng)過(guò)的時(shí)間(毫秒)

?

源碼

下面看看以上方法的源碼實(shí)現(xiàn):

知識(shí)點(diǎn)1:computeScrollOffset()方法

?

[java]?view plaincopy ?
  • /**?
  • ????*?Call?this?when?you?want?to?know?the?new?location.?If?it?returns?true,?
  • ????*?the?animation?is?not?yet?finished.?loc?will?be?altered?to?provide?the?
  • ????*?new?location.?
  • ????*/??
  • ???public?boolean?computeScrollOffset()?{??
  • ???????if?(mFinished)?{??
  • ???????????return?false;?//已經(jīng)完成了本次動(dòng)畫,直接返回為false????
  • ???????}??
  • ???????int?timePassed?=?(int)(AnimationUtils.currentAnimationTimeMillis()?-?mStartTime);??
  • ????
  • ???????if?(timePassed?<?mDuration)?{??
  • ???????????switch?(mMode)?{??
  • ???????????case?SCROLL_MODE:??
  • ???????????????float?x?=?timePassed?*?mDurationReciprocal;??
  • ????
  • ???????????????if?(mInterpolator?==?null)??
  • ???????????????????x?=?viscousFluid(x);??
  • ???????????????else??
  • ???????????????????x?=?mInterpolator.getInterpolation(x);??
  • ????
  • ???????????????mCurrX?=?mStartX?+?Math.round(x?*?mDeltaX);??
  • ???????????????mCurrY?=?mStartY?+?Math.round(x?*?mDeltaY);??
  • ???????????????break;??
  • ???????????case?FLING_MODE:??
  • ???????????????final?float?t?=?(float)?timePassed?/?mDuration;??
  • ???????????????final?int?index?=?(int)?(NB_SAMPLES?*?t);??
  • ???????????????float?distanceCoef?=?1.f;??
  • ???????????????float?velocityCoef?=?0.f;??
  • ???????????????if?(index?<?NB_SAMPLES)?{??
  • ???????????????????final?float?t_inf?=?(float)?index?/?NB_SAMPLES;??
  • ???????????????????final?float?t_sup?=?(float)?(index?+?1)?/?NB_SAMPLES;??
  • ???????????????????final?float?d_inf?=?SPLINE_POSITION[index];??
  • ???????????????????final?float?d_sup?=?SPLINE_POSITION[index?+?1];??
  • ???????????????????velocityCoef?=?(d_sup?-?d_inf)?/?(t_sup?-?t_inf);??
  • ???????????????????distanceCoef?=?d_inf?+?(t?-?t_inf)?*?velocityCoef;??
  • ???????????????}??
  • ???????????????mCurrVelocity?=?velocityCoef?*?mDistance?/?mDuration?*?1000.0f;??
  • ????????????????
  • ???????????????mCurrX?=?mStartX?+?Math.round(distanceCoef?*?(mFinalX?-?mStartX));??
  • ???????????????//?Pin?to?mMinX?<=?mCurrX?<=?mMaxX??
  • ???????????????mCurrX?=?Math.min(mCurrX,?mMaxX);??
  • ???????????????mCurrX?=?Math.max(mCurrX,?mMinX);??
  • ????????????????
  • ???????????????mCurrY?=?mStartY?+?Math.round(distanceCoef?*?(mFinalY?-?mStartY));??
  • ???????????????//?Pin?to?mMinY?<=?mCurrY?<=?mMaxY??
  • ???????????????mCurrY?=?Math.min(mCurrY,?mMaxY);??
  • ???????????????mCurrY?=?Math.max(mCurrY,?mMinY);??
  • ???????????????if?(mCurrX?==?mFinalX?&&?mCurrY?==?mFinalY)?{??
  • ???????????????????mFinished?=?true;??
  • ???????????????}??
  • ???????????????break;??
  • ???????????}??
  • ???????}??
  • ???????else?{??
  • ???????????mCurrX?=?mFinalX;??
  • ???????????mCurrY?=?mFinalY;??
  • ???????????mFinished?=?true;??
  • ???????}??
  • ???????return?true;??
  • ???}??
  • ?

    調(diào)用該方法判斷滾動(dòng)是否還在繼續(xù),mFinished屬性判斷是否滾動(dòng)完成,如果滾動(dòng)完成了,mFinished = true,computeScrollOffset()?返回false。

    ?

    知識(shí)點(diǎn)2:computeScroll()方法

    ?

    [java]?view plaincopy ?
  • /**?
  • ?*?Called?by?a?parent?to?request?that?a?child?update?its?values?for?mScrollX?
  • ?*?and?mScrollY?if?necessary.?This?will?typically?be?done?if?the?child?is?
  • ?*?animating?a?scroll?using?a?{@link?android.widget.Scroller?Scroller}?
  • ?*?object.?
  • ?*/由父視圖調(diào)用用來(lái)請(qǐng)求子視圖根據(jù)偏移值?mScrollX,mScrollY重新繪制????
  • public?void?computeScroll()?{??
  • }??
  • ?

    知道了computeScrollOffset()這個(gè)判斷是否滾動(dòng)的方法,那我們必須要有監(jiān)聽(tīng)滑屏控制,并且重繪,在Android框架中的VIEW類中就提供了computeScroll()這個(gè)方法去控制該流程。在繪制View時(shí),會(huì)在draw()過(guò)程調(diào)用該方法。因此,?再配合使用Scroller實(shí)例,我們就可以獲得當(dāng)前應(yīng)該的偏移坐標(biāo),手動(dòng)使View/ViewGroup偏移至該處。

    注:在使用Scroller這個(gè)類實(shí)現(xiàn)偏移控制,一般自定義View/ViewGroup都需要重載該方法 。

    具體實(shí)現(xiàn):

    ?

    [java]?view plaincopy ?
  • @Override??
  • ????public?void?computeScroll()?{??
  • ????????if?(mScroller.computeScrollOffset())?{??
  • ????????????scrollTo(mScroller.getCurrX(),?mScroller.getCurrY());??
  • ????????????//?更新界面??
  • ????????????postInvalidate();??
  • ????????????isMoving?=?true;??
  • ????????}?else?{??
  • ????????????isMoving?=?false;??
  • ????????}??
  • ????????super.computeScroll();??
  • ????}??
  • ?

    ?

    知識(shí)點(diǎn)3:startScroll()方法

    [java]?view plaincopy ?
  • /**?
  • ????*?Start?scrolling?by?providing?a?starting?point?and?the?distance?to?travel.?
  • ????*?
  • ????*?@param?startX??//水平方向滾動(dòng)的偏移值,以像素為單位。正值表明滾動(dòng)將向左滾動(dòng)?
  • ????*?@param?startY??//垂直方向滾動(dòng)的偏移值,以像素為單位。正值表明滾動(dòng)將向上滾動(dòng)?
  • ????*?@param?dx?//水平方向滑動(dòng)的距離,正值會(huì)使?jié)L動(dòng)向左滾動(dòng)?
  • ????*?@param?dy?//垂直方向滑動(dòng)的距離,正值會(huì)使?jié)L動(dòng)向上滾動(dòng)?
  • ????*?@param?duration?//滾動(dòng)持續(xù)時(shí)間?
  • ????*/??
  • ???public?void?startScroll(int?startX,?int?startY,?int?dx,?int?dy,?int?duration)?{??
  • ???????mMode?=?SCROLL_MODE;??
  • ???????mFinished?=?false;??
  • ???????mDuration?=?duration;??
  • ???????mStartTime?=?AnimationUtils.currentAnimationTimeMillis();??
  • ???????mStartX?=?startX;??
  • ???????mStartY?=?startY;??
  • ???????mFinalX?=?startX?+?dx;??
  • ???????mFinalY?=?startY?+?dy;??
  • ???????mDeltaX?=?dx;??
  • ???????mDeltaY?=?dy;??
  • ???????mDurationReciprocal?=?1.0f?/?(float)?mDuration;??
  • ???}??
  • 該方法以提供的起始點(diǎn)和將要滑動(dòng)的距離開(kāi)始滾動(dòng),我們可以使用該方法達(dá)到自動(dòng)滾動(dòng)的效果。在滾動(dòng)中,如果符合什么條件,可以調(diào)用該方法讓它滾動(dòng)到相對(duì)應(yīng)的地方。

    ?

    著重點(diǎn):

    在界面滾動(dòng)中,你必須搞清楚和scrollTo和scrollBy之間的區(qū)別所在:android 布局之滑動(dòng)探究 scrollTo 和 scrollBy 方法使用說(shuō)明

    ? 需要注意的是,移動(dòng)的時(shí)候向左移動(dòng)為負(fù),向下移為負(fù)。示意圖如下:

    ?

    使用思路流程:

    如果你使用Scroller,流程如下:

    1.可以在自定義的布局中,按照需求初始化Scroller構(gòu)造函數(shù)。

    2.重寫onInterceptTouchEvent(MotionEvent ev)方法,看看是否要攔截相關(guān)的點(diǎn)擊時(shí)間。

    3.重寫onTouchEvent(MotionEvent event)方法,根據(jù)觸摸屏上的動(dòng)作使用computeScroll()以及scrollTo 和 scrollBy?方法進(jìn)行根據(jù)手指對(duì)布局進(jìn)行滑動(dòng)效果。

    4.在觸摸操作結(jié)束(MotionEvent.ACTION_UP)的時(shí)候,調(diào)用startScroll(int startX, int startY, int dx, int dy, int duration)方法,進(jìn)行動(dòng)畫自動(dòng)操作,來(lái)完成整個(gè)滾動(dòng)流程。

    ?

    對(duì)于Scroller類大體的使用和介紹已經(jīng)完畢,之后會(huì)放上自己調(diào)用類實(shí)現(xiàn)的幾個(gè)漂亮的效果。

    ?

    版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。

    轉(zhuǎn)載于:https://www.cnblogs.com/Free-Thinker/p/4785014.html

    總結(jié)

    以上是生活随笔為你收集整理的Android 界面滑动实现---Scroller类 从源码和开发文档中学习(让你的布局动起来)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。