一步一步教你150行代碼實現簡書滑動返回效果

先看看效果圖:java

 

由於沒有具體內容,也沒有簡書的圖片資源,因此稍微簡陋了點.
可是依然不妨礙咱們的效果展現~android

OK,接下來慣例,經過閱讀本文你能學習到:git

  1. ViewDragHelper的使用(若是你想學習自定義View,那麼ViewDragHelper你絕對不能錯過)
  2. 好像也沒有什麼了….

這個效果,難度不大,會ViewDragHelper的同窗應該10分鐘就能寫出來了吧~
若是不會也不要緊~github

1. 咱們自定義一個SwipeBackFrameLayout繼承自FrameLayout

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
      xmlns:android = "http://schemas.android.com/apk/res/android"
      xmlns:tools = "http://schemas.android.com/tools"
      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.定義activity的finish動畫

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"
      xmlns:android = "http://schemas.android.com/apk/res/android"
      android:fromAlpha = "1.0"
      android:toAlpha = "1.0" >
</ alpha >
 
//out_to_right
< translate
      xmlns:android = "http://schemas.android.com/apk/res/android"
      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

原文:http://www.jianshu.com/p/59be4551c418

相關文章
相關標籤/搜索