activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.harvic.smoothscrollview.MainActivity" > <com.harvic.smoothscrollview.CustomScrollView android:layout_width="fill_parent" android:layout_height="match_parent"> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:scaleType="fitCenter" android:src="@drawable/ic_launcher"/> </com.harvic.smoothscrollview.CustomScrollView> </RelativeLayout>
package com.harvic.smoothscrollview; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
package com.harvic.smoothscrollview; 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; import android.widget.ScrollView; public class CustomScrollView extends ScrollView { // 图片控件视图 private View mRootView; // 用来保存手指的当前位置坐标值 private int mpreY = 0; // 初始化图片视图的矩形区域坐标位置 private Rect mNormalRect; public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } /** * onFinishInflate()函数,明显是在布局解析结束后会调用的函数。 */ @Override protected void onFinishInflate() { mRootView = getChildAt(0); super.onFinishInflate(); } /** * 在onTouchEvent()中根据手指的移动距离,通过layout()函数将布局跟随移动即可 */ @Override public boolean onTouchEvent(MotionEvent event) { // 获取手指当前的位置y轴坐标 float curY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { if (mRootView != null) { // 进行布局位置--获取图片初始化的矩形区域 mNormalRect = new Rect(mRootView.getLeft(), mRootView.getTop(), mRootView.getRight(), mRootView.getBottom()); } } break; case MotionEvent.ACTION_MOVE: { // 获取手指移动的距离--乘以0.25是凸显阻尼效果 int delta = (int) ((curY - mpreY) * 0.25); if (delta > 0) { // 根据手指滑动的距离,进行重新布局那个图片View控件!!!!!!!!!!!! mRootView.layout(mRootView.getLeft(), mRootView.getTop() + delta, mRootView.getRight(), mRootView.getBottom() + delta); } } break; case MotionEvent.ACTION_UP: { // 获取手指松开的那一刻的图片的顶部距离 int curTop = mRootView.getTop(); // 回归到初始化的那个矩形位置即可 mRootView.layout(mNormalRect.left, mNormalRect.top, mNormalRect.right, mNormalRect.bottom); TranslateAnimation animation = new TranslateAnimation(0, 0, curTop - mNormalRect.top, 0); // 下面这样子也可以 // mRootView.layout(mRootView.getLeft(), mNormalRect.top, // mRootView.getRight(), mNormalRect.bottom); // TranslateAnimation animation = new TranslateAnimation(0, 0, // curTop // - mNormalRect.top, 0); animation.setDuration(200); mRootView.startAnimation(animation); } break; } // 保存每次手指移动的最新位置 mpreY = (int) curY; return super.onTouchEvent(event); } }
************************************************或者修改自定义ScrollView类,下边的方式也可以******************************
package com.example.pullscrollview; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.animation.TranslateAnimation; import android.widget.ScrollView; public class CustomScrollView extends ScrollView { // 图片控件视图 private View mRootView; // 用来保存手指的当前位置坐标值 private int mpreY = 0; // 初始化图片视图的矩形区域坐标位置 private Rect mNormalRect; public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } /** * onFinishInflate()函数,明显是在布局解析结束后会调用的函数。 */ @Override protected void onFinishInflate() { mRootView = getChildAt(0); super.onFinishInflate(); } /** * 在onTouchEvent()中根据手指的移动距离,通过layout()函数将布局跟随移动即可 */ @Override public boolean onTouchEvent(MotionEvent event) { // 获取手指当前的位置y轴坐标 switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { mpreY = (int) event.getY(); if (mRootView != null) { // 进行布局位置--获取图片初始化的矩形区域 mNormalRect = new Rect(mRootView.getLeft(), mRootView.getTop(), mRootView.getRight(), mRootView.getBottom()); } } break; case MotionEvent.ACTION_MOVE: { float curY = event.getY(); // 获取手指移动的距离--乘以0.25是凸显阻尼效果 int delta = (int) (curY - mpreY); if (delta > 0) { // 根据手指滑动的距离,进行重新布局那个图片View控件!!!!!!!!!!!! mRootView.layout(mRootView.getLeft(), mNormalRect.top + delta, mRootView.getRight(), mNormalRect.bottom + delta); } } break; case MotionEvent.ACTION_UP: { // 获取手指松开的那一刻的图片的顶部距离 int curTop = mRootView.getTop(); // 回归到初始化的那个矩形位置即可 mRootView.layout(mNormalRect.left, mNormalRect.top, mNormalRect.right, mNormalRect.bottom); TranslateAnimation animation = new TranslateAnimation(0, 0, curTop - mNormalRect.top, 0); // 下面这样子也可以 // mRootView.layout(mRootView.getLeft(), mNormalRect.top, // mRootView.getRight(), mNormalRect.bottom); // TranslateAnimation animation = new TranslateAnimation(0, 0, // curTop // - mNormalRect.top, 0); animation.setDuration(200); mRootView.startAnimation(animation); } break; } // 保存每次手指移动的最新位置 return super.onTouchEvent(event); } }