先看看效果图: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上