先看看效果圖:java
由於沒有具體內容,也沒有簡書的圖片資源,因此稍微簡陋了點.
可是依然不妨礙咱們的效果展現~android
OK,接下來慣例,經過閱讀本文你能學習到:git
這個效果,難度不大,會ViewDragHelper的同窗應該10分鐘就能寫出來了吧~
若是不會也不要緊~github
1.1 由於看到左邊黃色的View是被遮住的,而另一個View的寬度是MatchParent的,因此FrameLayout是不錯的選擇.
順便增長一個回調,通知activity去finishide
1
2
3
4
5
6
7
|
public
void
setCallback(Callback mCallback){
this
.mCallback = mCallback;
}
private
Callback mCallback;
public
interface
Callback{
void
onShouldFinish();
}
|
1.2 Xml佈局,很是簡單:佈局
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<
yifeiyuan.practice.practicedemos.drager.SwipeBackFrameLayout
android:id
=
"@+id/swipe_back"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
tools:context
=
"yifeiyuan.practice.practicedemos.drager.SwipeBackActivity"
>
<
TextView
android:layout_width
=
"40dp"
android:layout_height
=
"match_parent"
android:text
=
"@string/hello_world"
android:gravity
=
"center"
android:background
=
"#ffff00"
/>
<
View
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:background
=
"#ff00ff"
/>
</
yifeiyuan.practice.practicedemos.drager.SwipeBackFrameLayout
>
|
1.3 實例化一個ViewDragHelper學習
1
2
3
4
5
6
7
8
9
|
//1f表明靈敏度
mDragHelper = ViewDragHelper.create(
this
, 1f,
new
ViewDragHelper.Callback() {
@Override
public
boolean
tryCaptureView(View child,
int
pointerId) {
return
false
;
}
}
//由於咱們是從左向右滑動 因此設置EDGE_LEFT
mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
|
1.4 在SwipeBackFrameLayout裏實例化xml裏的子View動畫
1
2
3
4
5
6
7
8
9
|
private
View mDividerView;
private
View mContentView;
@Override
protected
void
onFinishInflate() {
super
.onFinishInflate();
mDividerView = getChildAt(
0
);
mDividerView.setAlpha(0f);
mContentView = getChildAt(
1
);
}
|
1.5 讓ViewDragHelper處理touch事件this
1
2
3
4
5
6
7
8
9
10
|
@Override
public
boolean
onInterceptTouchEvent(MotionEvent ev) {
return
mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public
boolean
onTouchEvent(MotionEvent event) {
mDragHelper.processTouchEvent(event);
return
true
;
}
|
1.6重寫ViewDragHelper的一些處理方法spa
已附上詳細註釋
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
@Override
public
void
onEdgeTouched(
int
edgeFlags,
int
pointerId) {
super
.onEdgeTouched(edgeFlags, pointerId);
//觸摸到左邊界的時候 咱們capture住mContentView
mDragHelper.captureChildView(mContentView, pointerId);
}
@Override
public
int
getViewHorizontalDragRange(View child) {
return
1
;
}
@Override
public
void
onViewPositionChanged(View changedView,
int
left,
int
top,
int
dx,
int
dy) {
super
.onViewPositionChanged(changedView, left, top, dx, dy);
Log.d(TAG,
"onViewPositionChanged() called with left = ["
+ left +
"], top = ["
+ top +
"], dx = ["
+ dx +
"], dy = ["
+ dy +
"]"
);
//0.0 - 1.0
//Notice 這邊能夠給個接口回調出去,就能夠作各類炫酷的效果了
float
alpha = (
float
) (left*
1.0
/mDividerWidth);
mDividerView.setAlpha(alpha);
}
@Override
public
int
clampViewPositionHorizontal(View child,
int
left,
int
dx) {
// Log.d(TAG, "clampViewPositionHorizontal() called with dx = [" + dx + "]");
// 計算left 咱們的目標範圍是0-dividerwidth的寬度
mLastdx = dx;
int
newLeft = Math.min(mDividerWidth, Math.max(left,
0
));
return
newLeft;
}
@Override
public
void
onViewReleased(View releasedChild,
float
xvel,
float
yvel) {
//>0表明用戶想關閉
if
(mLastdx>
0
){
// 還不到關閉條件,咱們讓view滑動過去,再關閉
if
(mDividerWidth != releasedChild.getLeft()) {
mDragHelper.settleCapturedViewAt(mDividerWidth,releasedChild.getTop();
invalidate();
}
else
{
if
(mCallback !=
null
) {
mCallback.onShouldFinish();
}
}
}
else
{
//用戶不想關閉 ,則滑動到最左邊
if
(mDividerWidth !=
0
) {
mDragHelper.settleCapturedViewAt(
0
, releasedChild.getTop());
invalidate();
}
}
}
@Override
public
void
onViewDragStateChanged(
int
state) {
super
.onViewDragStateChanged(state);
//滑動中止,而且到達了滑動的判斷條件 則回調關閉
if
(mDragHelper.getViewDragState()==ViewDragHelper.STATE_IDLE&&mCallback !=
null
&&mDividerWidth==mContentView.getLeft()&&mLastdx>
0
) {
mCallback.onShouldFinish();
}
}
});
|
1.7 增長對view滑動事件處理,對於以上mDividerWidth咱們在onLayout裏獲取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
private
int
mDividerWidth;
@Override
protected
void
onLayout(
boolean
changed,
int
left,
int
top,
int
right,
int
bottom) {
super
.onLayout(changed, left, top, right, bottom);
mDividerWidth = mDividerView.getWidth();
}
//Notice view 剛初始化的時候就會被調用一次
@Override
public
void
computeScroll() {
super
.computeScroll();
// Log.d(TAG, "computeScroll() called with " + "");
if
(mDragHelper.continueSettling(
true
)) {
invalidate();
}
}
|
咱們寫完自定義view後還須要自定義一下activity的退出動畫~
2.1 在anim目錄下,建立兩個動畫xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//no_anim
<
alpha
android:duration
=
"300"
android:fromAlpha
=
"1.0"
android:toAlpha
=
"1.0"
>
</
alpha
>
//out_to_right
<
translate
android:duration
=
"300"
android:fromXDelta
=
"0%"
android:toXDelta
=
"100%"
>
</
translate
>
|
2.2 在activity裏設置callback監聽,並運用動畫
1
2
3
4
5
6
7
|
mSwipeBack.setCallback(
new
SwipeBackFrameLayout.Callback() {
@Override
public
void
onShouldFinish() {
finish();
overridePendingTransition(R.anim.no_anim, R.anim.out_to_right);
}
});
|
好了!!~代碼量很是少!~就是這麼簡單~
吐槽一下,簡書對代碼塊的支持太差了,代碼複製過來全是亂的!!
同窗們仍是去看源碼吧:
源碼在個人Github上