Activity滑動(dòng)返回效果的實(shí)現(xiàn)
在很多的App中这刷,都會(huì)發(fā)現(xiàn)利用手指滑動(dòng)事件胚想,進(jìn)行高效且人性化的交互于微。在一個(gè)大家越來越觸摸不到屏幕左上方返回鍵的大屏幕時(shí)代蹋嵌,若執(zhí)拗的不去改變自己的設(shè)計(jì)方法,不去換一種思路葫隙,那就是自尋死路栽烂。
在詳情頁面中,我希望有兩種方式來進(jìn)行返回:
- 點(diǎn)擊左上角的返回按鈕,返回上一級(jí)
- 手指從左往右滑動(dòng)腺办,返回上一級(jí)
方法一:OnClickListener
該方法很簡單粗暴焰手,為你的返回按鈕添加監(jiān)聽事件,調(diào)用finish(),同時(shí)可以在finish之后怀喉,實(shí)現(xiàn)一些動(dòng)畫效果书妻。比如我用的:
overridePendingTransition(R.anim.push_left_in,
R.anim.push_right_out);
R.anim.push_left_in也很簡單:
<translate android:fromXDelta="100%" android:toXDelta="0"
android:duration="600" />
R.anim.push_left_out:
android:fromXDelta="0" android:toXDelta="100%"
這就能實(shí)現(xiàn)一個(gè)很簡單的滑動(dòng)滑出的動(dòng)畫。
在做這個(gè)動(dòng)畫的時(shí)候躬拢,不太理解其中屬性的含義躲履,一直出不來自己想要的結(jié)果。搜索了很多聊闯,然后自己也總結(jié)一下:
- fromXDelta 動(dòng)畫起始時(shí)X坐標(biāo)位置(左正右負(fù)工猜,下同)
- toXDelta 動(dòng)畫結(jié)束時(shí)X坐標(biāo)位置
- fromYDelta 動(dòng)畫起始時(shí)Y坐標(biāo)位置
- toYDelta 動(dòng)畫結(jié)束時(shí)Y坐標(biāo)位置
- duration 動(dòng)畫的持續(xù)時(shí)間ms
注:在沒有指定的時(shí)候,默認(rèn)是以自己為相對(duì)參照物菱蔬。屬性中+%表示和自身的百分比篷帅,+p表示以父View為參考。
方法二:onTouchEvent
大概的思路就是:監(jiān)聽手勢按下以及移動(dòng)的距離和速度拴泌,若超過合理的范圍魏身,我就認(rèn)定用戶是在返回
說起來還是很簡單,實(shí)現(xiàn)起來也不是特別的復(fù)雜蚪腐。我將其寫入在我的菜單基類里面箭昵,便于其他菜單繼承。
- 設(shè)置向右滑動(dòng)的最小速度SPEED_MIN = 200;
- 設(shè)置向右滑動(dòng)的最小距離DISTANCE_MIN = 150;
- 用兩個(gè)變量削茁,記錄手指按下時(shí)的橫坐標(biāo)xDown宙枷,和移動(dòng)時(shí)的橫坐標(biāo)xMove;
- 在onTouch中得到xMove-xDown之間的距離,并通過函數(shù)計(jì)算出當(dāng)時(shí)的速度茧跋。若都大于最小值慰丛,則判定用戶是在返回,調(diào)用finish();
- 創(chuàng)建VelocityTracker對(duì)象瘾杭,并將觸摸content界面的滑動(dòng)事件加入到VelocityTracker當(dāng)中
mVelocityTracker.addMovement(event);
- 通過getScrollVelocity()诅病,獲得手指的當(dāng)前滑動(dòng)速度(滑動(dòng)速度依靠的是每秒鐘多少像素)
private int getScrollVelocity() {
mVelocityTracker.computeCurrentVelocity(1000);
int velocity = (int) mVelocityTracker.getXVelocity();
return Math.abs(velocity);
}
- 記住在MotionEvent.ACTION_UP中回收VelocityTracker對(duì)象
我興高采烈的配置完畢,發(fā)現(xiàn)犯傻了粥烁。由于的我項(xiàng)目需要贤笆,我將我的布局寫成了ScrollView,所以首先會(huì)執(zhí)行scrollView中的onTouchEvent()讨阻,而且會(huì)返回true芥永,事件停止傳播。這就會(huì)導(dǎo)致上面寫的OnTouchEvent將不會(huì)被回調(diào)了钝吮。
解決的辦法就是自己自定義一個(gè)ScrollView
- Override onTouchEvent()方法埋涧,并讓它返回true
- 在將之前布局中的ScrollView用新的替換掉
萬事OK板辽,按下F11,噫棘催?怎么搞的劲弦,還是返回不了嘛,而且就沒有滑動(dòng)的說(因?yàn)槲以贠nTouchEvent中添加了log)醇坝。
再一次邑跪,我踏上了除蟲之旅。
仔細(xì)的分析過后發(fā)現(xiàn)呼猪,ScrollView中的高度好像不對(duì)画畅,并沒有像我想象的那樣填滿整個(gè)控件,但是我設(shè)置的屬性的的確確是fill_parent吶郑叠。查了查Google夜赵,才發(fā)現(xiàn)要想填滿整個(gè)ScrollView時(shí),fill_parent屬性是不管用的乡革。必須設(shè)置fillViewport="true"寇僧。
這樣改了改,總算完成了預(yù)定想法沸版。
想起來一個(gè)人在知乎上面說的話:“做Android開發(fā)就是嘁傀,解決了一個(gè)問題,又有無數(shù)個(gè)問題冒出來视粮∠赴欤”
對(duì)此,我深感贊同蕾殴。
Have a nice day.