一步一步教你150行代码实现简书滑动返回效果
source link: http://www.androidchina.net/3263.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
今天带大家实现简书的滑动返回效果.
先看看效果图:
因为没有具体内容,也没有简书的图片资源,所以稍微简陋了点.
但是依然不妨碍我们的效果展示~
OK,接下来惯例,通过阅读本文你能学习到:
- ViewDragHelper的使用(如果你想学习自定义View,那么ViewDragHelper你绝对不能错过)
- 好像也没有什么了….
这个效果,难度不大,会ViewDragHelper的同学应该10分钟就能写出来了吧~
如果不会也没关系~
1. 我们自定义一个SwipeBackFrameLayout继承自FrameLayout
1.1 因为看到左边黄色的View是被遮住的,而另外一个View的宽度是MatchParent的,所以FrameLayout是不错的选择.
顺便增加一个回调,通知activity去finish
public
void
setCallback(Callback mCallback){
this
.mCallback = mCallback;
}
private
Callback mCallback;
public
interface
Callback{
void
onShouldFinish();
}
1.2 Xml布局,非常简单:
<
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
//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
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事件
@Override
public
boolean
onInterceptTouchEvent(MotionEvent ev) {
return
mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public
boolean
onTouchEvent(MotionEvent event) {
mDragHelper.processTouchEvent(event);
return
true
;
}
1.6重写ViewDragHelper的一些处理方法
已附上详细注释
@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里获取
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.定义activity的finish动画
2.1 在anim目录下,创建两个动画xml:
//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监听,并运用动画
mSwipeBack.setCallback(
new
SwipeBackFrameLayout.Callback() {
@Override
public
void
onShouldFinish() {
finish();
overridePendingTransition(R.anim.no_anim, R.anim.out_to_right);
}
});
好了!!~代码量非常少!~就是这么简单~
吐槽一下,简书对代码块的支持太差了,代码复制过来全是乱的!!
同学们还是去看源码吧:
源码在我的Github上
原文:http://www.jianshu.com/p/59be4551c418
转载请注明:Android开发中文站 » 一步一步教你150行代码实现简书滑动返回效果
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK