content: package tv.baokan.baokanandroid.widget;
  
  import android.annotation.SuppressLint;
  import android.widget.ScrollView;
  import android.content.Context;
  import android.graphics.Rect;
  import android.util.AttributeSet;
  import android.view.MotionEvent;
  import android.view.View;
  import android.view.animation.TranslateAnimation;
  
  /**
   * 可以拖动的ScrollView 仿iOS UIScrollView
   */
  public class DragScrollView extends ScrollView {
  
      private static final int size = 4;
      private View inner;
      private float y;
      private Rect normal = new Rect();
  
      public DragScrollView(Context context) {
          super(context);
      }
  
      public DragScrollView(Context context, AttributeSet attrs) {
          super(context, attrs);
      }
  
      @Override
      protected void onFinishInflate() {
          if (getChildCount() > 0) {
              inner = getChildAt(0);
          }
      }
  
      @SuppressLint("ClickableViewAccessibility")
      @Override
      public boolean onTouchEvent(MotionEvent ev) {
          if (inner == null) {
              return super.onTouchEvent(ev);
          } else {
              commOnTouchEvent(ev);
          }
          return super.onTouchEvent(ev);
      }
  
      public void commOnTouchEvent(MotionEvent ev) {
          int action = ev.getAction();
          switch (action) {
              case MotionEvent.ACTION_DOWN:
                  y = ev.getY();
                  break;
              case MotionEvent.ACTION_UP:
                  if (isNeedAnimation()) {
                      // Log.v("mlguitar", "will up and animation");
                      animation();
                  }
                  break;
              case MotionEvent.ACTION_MOVE:
                  final float preY = y;
                  float nowY = ev.getY();
                  /**
                   * size=4 表示 拖动的距离为屏幕的高度的1/4
                   */
                  int deltaY = (int) (preY - nowY) / size;
                  // 滚动
                  // scrollBy(0, deltaY);
  
                  y = nowY;
                  if (isNeedMove()) {
                      if (normal.isEmpty()) {
                          normal.set(inner.getLeft(), inner.getTop(),
                                  inner.getRight(), inner.getBottom());
                          return;
                      }
                      int yy = inner.getTop() - deltaY;
  
                      // 移动布局
                      inner.layout(inner.getLeft(), yy, inner.getRight(),
                              inner.getBottom() - deltaY);
                  }
                  break;
              default:
                  break;
          }
      }
  
      public void animation() {
          TranslateAnimation ta = new TranslateAnimation(0, 0, inner.getTop(),
                  normal.top);
          ta.setDuration(200);
          inner.startAnimation(ta);
          inner.layout(normal.left, normal.top, normal.right, normal.bottom);
          normal.setEmpty();
      }
  
      public boolean isNeedAnimation() {
          return !normal.isEmpty();
      }
  
      public boolean isNeedMove() {
          int offset = inner.getMeasuredHeight() - getHeight();
          int scrollY = getScrollY();
          return scrollY == 0 || scrollY == offset;
      }
  
  }