Scroll效果的幾種實(shí)現(xiàn)辦法

首先都是對(duì)view的onTouchEvent()方法進(jìn)行操作唧喉,對(duì)于
MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE,MotionEvent.ACTION_UP進(jìn)行操作

一、

首先聲明全局變量lastX,lastY保存手指按下位置忍抽;

二八孝、直接使用layout的方式

/**
 * 在View內(nèi)部可以通過getLeft(),getRight(),getTop(),getBottom()方法獲取位置
 * 在MotionEvent可以通過getX(),getY(),getRawX(),getRawY()方法獲取坐標(biāo)位置
 * 區(qū)別在于getX(),getY()是獲取相對(duì)View左上角的坐標(biāo),getRawX(),getRawY()是獲取相對(duì)屏幕左上角的坐標(biāo)
 */

//方法1鸠项、通過layout()和getX()方法產(chǎn)生scroll效果
private boolean onTouchEvent(MotionEvent ev){
    int x=(int)ev.getX();//相對(duì)于View自身的x方向位置干跛,根據(jù)移動(dòng)變化
    int y=(int)ev.getY();//相對(duì)于View自身的y方向位置
    switch(ev.getAction){
        case MotionEvent.ACTION_DOWN:
            lastX=x;//保存手指位置
            lastY=y;
            break;
        case MotionEvent.ACTION_MOVE:
            int offsetX=x-lastX;//計(jì)算手指移動(dòng)距離
            int offsetY=y-lastY;
            //重新布局
            layout(getLeft()+offsetX,getTop()+offsetY,getRight()+offsetX,getBottom()+offsetY);
            break;
    }
  return true;//消費(fèi)觸摸事件
}

//方法2、通過layout()和getRawX()方法產(chǎn)生scroll效果
private boolean onTouchEvent(MotionEvent ev){
    int rawX=(int)ev.getRawX();//相對(duì)于屏幕的x方向位置祟绊,根據(jù)移動(dòng)變化
    int rawY=(int)ev.getRawY();//相對(duì)于屏幕的y方向位置
    switch(ev.getAction){
        case MotionEvent.ACTION_DOWN:
            lastX=rawX;//保存手指位置
            lastY=rawY;
            break;
        case MotionEvent.ACTION_MOVE:
            int offsetX=rawX-lastX;//計(jì)算手指移動(dòng)距離
            int offsetY=rawY-lastY;
            //重新布局
            layout(getLeft()+offsetX,getTop()+offsetY,getRight()+offsetX,getBottom()+offsetY);
            //需要重新保存lastX楼入,lastY
            //因?yàn)橛|控點(diǎn)所在的當(dāng)前View都會(huì)跟著手指滑動(dòng)(調(diào)用了layout()),這會(huì)導(dǎo)致getRawX(等于當(dāng)前View左邊緣絕對(duì)坐標(biāo)+getX)的值持續(xù)變化嘉熊,而getX不受影響(view跟著手指一起動(dòng))。
            lastX=rawX;
            lastY=rawY;
            break;
    }
  return true;//消費(fèi)觸摸事件
}

//方法3愧薛、通過offsetLeftAndRight(int offset),offsetTopAndBottom(int offset)方法取代layout()產(chǎn)生scroll效果
修改上面的代碼
        case MotionEvent.ACTION_MOVE:
            int offsetX=x-lastX;//計(jì)算手指移動(dòng)距離
            int offsetY=y-lastY;
            //重新布局
            offsetLeftAndRight(offsetX)削罩;//同時(shí)對(duì)左右都進(jìn)行移動(dòng)
            offsetTopAndBottom(offsetY);
            break;

三、使用scrollBy()方法四濒,使用此方法需要有父布局

private boolean onTouchEvent(MotionEvent ev){
    int x=(int)ev.getX();//相對(duì)于View自身的x方向位置喳资,根據(jù)移動(dòng)變化
    int y=(int)ev.getY();//相對(duì)于View自身的y方向位置
    switch(ev.getAction){
        case MotionEvent.ACTION_DOWN:
            lastX=x;//保存手指位置
            lastY=y;
            break;
        case MotionEvent.ACTION_MOVE:
            int offsetX=x-lastX;//計(jì)算手指移動(dòng)距離
            int offsetY=y-lastY;
            //重新布局,必須使用父布局的scrollBy()方法
            ((View)getParent()).scrollBy(-offsetX,-offsetY);//注意這里必須加“-”,往正方向移動(dòng)搞疗,必須是負(fù)值
            break;
    }
  return true;//消費(fèi)觸摸事件
}```

####四幢炸、使用Scroller類,內(nèi)部其實(shí)是通過scrollTo()方法
- 初始化Scroller
在構(gòu)造方法中進(jìn)行

scroller=new Scroller(context);

- 重寫computeScroll()方法,這是核心缰揪,必須要有

@Override
public void computeScroll() {
super.computeScroll();
//判斷Scroller是否執(zhí)行完畢
if(scroller.computeScrollOffset()){
((View)getParent()).scrollTo(scroller.getCurrX(),scroller.getCurrY());//通過getCurrX()和getCurrY()獲得當(dāng)前滑動(dòng)坐標(biāo)
//通過重繪不斷調(diào)用computeScroll
invalidate();
}
}
computeScroll()不會(huì)自動(dòng)調(diào)用赞厕,只能通過invalidate()-->draw()-->computeScroll()來循環(huán)獲得scrollX和scrollY```

  • startScroll
    有兩個(gè)重載方法
scroller.startScroll(int startX,int startY,int dX,int dY);
scroller.startScroll(int startX,int startY,int dX,int dY,int duration);```
前四個(gè)參數(shù)為起始坐標(biāo)和偏移量,duration則為持續(xù)時(shí)間
在獲取坐標(biāo)時(shí)镀虐,通常用父布局的getScrollX()和getScrollY()來獲取父視圖中content的滑動(dòng)到的點(diǎn)

在這里添加ACTION_UP事件绽慈,演示:
代碼如下

public class DragView extends ImageView {
private Scroller scroller;
private int lastX,lastY;
public DragView(Context context) {
super(context);
}

public DragView(Context context, AttributeSet attrs) {
    super(context, attrs);
    scroller=new Scroller(context);
}

public DragView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
    int x= (int) event.getX();
    int y= (int) event.getY();
    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN:
            lastX=x;
            lastY=y;
            break;
        case MotionEvent.ACTION_MOVE:
            int offsetX=x-lastX;
            int offsetY=y-lastY;
            ((View)getParent()).scrollBy(-offsetX,-offsetY);
            break;
        case MotionEvent.ACTION_UP:
            View viewGroup= (View) getParent();
            scroller.startScroll(viewGroup.getScrollX(),
                                          viewGroup.getScrollY(),
                                          -viewGroup.getScrollX(),
                                          -viewGroup.getScrollY(),1000);//返回原來的位置
            //通過重繪不斷調(diào)用computeScroll
            invalidate();
    }
    return true;
}
@Override
public void computeScroll() {
    super.computeScroll();
    //判斷Scroller是否執(zhí)行完畢
    if(scroller.computeScrollOffset()){
        ((View)getParent()).scrollTo(scroller.getCurrX(),scroller.getCurrY());
        //通過重繪不斷調(diào)用computeScroll
        invalidate();
    }
}

}```
效果圖如下

scroller.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末啃炸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖封救,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異旭贬,居然都是意外死亡奋刽,警方通過查閱死者的電腦和手機(jī)方妖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門镐牺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事参袱。” “怎么了企垦?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長荧降。 經(jīng)常有香客問我接箫,道長,這世上最難降的妖魔是什么废累? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蹲坷。我一直安慰自己,他們只是感情好题山,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著洲劣,像睡著了一般备蚓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上囱稽,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天郊尝,我揣著相機(jī)與錄音,去河邊找鬼战惊。 笑死流昏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的吞获。 我是一名探鬼主播况凉,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼各拷!你這毒婦竟也來了刁绒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤烤黍,失蹤者是張志新(化名)和其女友劉穎知市,沒想到半個(gè)月后傻盟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嫂丙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年娘赴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跟啤。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诽表,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出隅肥,到底是詐尸還是另有隱情竿奏,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布武福,位于F島的核電站议双,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏捉片。R本人自食惡果不足惜平痰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伍纫。 院中可真熱鬧宗雇,春花似錦、人聲如沸莹规。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽良漱。三九已至舞虱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間母市,已是汗流浹背矾兜。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留患久,地道東北人椅寺。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像蒋失,于是被迫代替她去往敵國和親返帕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容