activity_main.xml

<LinearLayout 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"
android:orientation="vertical"
tools:context="com.example.scrollviewdemo.MainActivity" > <com.example.scrollviewdemo.CustomScrollView android:id="@+id/scrollview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" > <LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" > <TextView
android:layout_width="fill_parent"
android:layout_height="100dp"
android:text="AAA" >
</TextView> <TextView
android:layout_width="fill_parent"
android:layout_height="100dp"
android:text="AAA" >
</TextView> <TextView
android:layout_width="fill_parent"
android:layout_height="100dp"
android:text="AAA" >
</TextView> <TextView
android:layout_width="fill_parent"
android:layout_height="100dp"
android:text="AAA" >
</TextView> <TextView
android:layout_width="fill_parent"
android:layout_height="100dp"
android:text="AAA" >
</TextView>
<TextView
android:layout_width="fill_parent"
android:layout_height="100dp"
android:text="AAA" >
</TextView>
<TextView
android:layout_width="fill_parent"
android:layout_height="100dp"
android:text="AAA" >
</TextView>
<TextView
android:layout_width="fill_parent"
android:layout_height="100dp"
android:text="AAA" >
</TextView>
<TextView
android:layout_width="fill_parent"
android:layout_height="100dp"
android:text="AAA" >
</TextView>
</LinearLayout>
</com.example.scrollviewdemo.CustomScrollView
> </LinearLayout>

MainActivity

package com.example.scrollviewdemo;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ScrollView; public class MainActivity extends Activity {
ScrollView scrollView;
private static final int TOUCH_EVENT_ID = 1; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = (ScrollView) findViewById(R.id.scrollview); }
}

方式一

ElasticScrollView

package com.example.scrollviewdemo;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation; public class ElasticScrollView extends ScrollView {
//scrollView下的控件
private View inner; private float y; //保存状态的矩形框
private Rect normal = new Rect(); //是否要计算
private boolean isCount = false; @SuppressLint("NewApi")
public ElasticScrollView(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) {
commOnTouchEvent(ev);
}
return super.onTouchEvent(ev);
} //处理触摸事件
public void commOnTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_UP:
//是不是须要动画
if (isNeedAnimation()) {
animation();
isCount = false;
}
break;
case MotionEvent.ACTION_MOVE:
final float preY = y;
float nowY = ev.getY();
int deltaY = (int) (preY - nowY);
if (!isCount) {
deltaY = 0;
} y = nowY;
if (isNeedMove()) {
if (normal.isEmpty()) {
normal.set(inner.getLeft(), inner.getTop(),inner.getRight(), inner.getBottom());
}
inner.layout(inner.getLeft(), inner.getTop() - deltaY / 2,inner.getRight(), inner.getBottom() - deltaY / 2);
}
isCount = true;
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(); } // return left >= right || top >= bottom;
public boolean isNeedAnimation() {
return !normal.isEmpty();
} public boolean isNeedMove() {
int offset = inner.getMeasuredHeight() - getHeight();
int scrollY = getScrollY();
if (scrollY == 0 || scrollY == offset) {
return true;
}
return false;
}
}

——————————————————————————方式二——————————————————————————

CustomScrollView

package com.example.scrollviewdemo;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.ScrollView; public class CustomScrollView extends ScrollView { // y方向上当前触摸点的前一次记录位置
private int previousY = 0;
// y方向上的触摸点的起始记录位置
private int startY = 0;
// y方向上的触摸点当前记录位置
private int currentY = 0;
// y方向上两次移动间移动的相对距离
private int deltaY = 0; // 第一个子视图
private View childView; // 用于记录childView的初始位置
private Rect topRect = new Rect(); public CustomScrollView(Context context) {
super(context);
;
} public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
;
} public CustomScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
;
} @Override
protected void onFinishInflate() {
if (getChildCount() > 0) {
childView = getChildAt(0);
}
} @Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (null == childView) {
return super.dispatchTouchEvent(event);
} switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startY = (int) event.getY();
previousY = startY;
break;
case MotionEvent.ACTION_MOVE:
currentY = (int) event.getY();
deltaY = previousY - currentY;
previousY = currentY; if (0 == getScrollY()
|| childView.getMeasuredHeight() - getHeight() <= getScrollY()) {
// 记录childView的初始位置
if (topRect.isEmpty()) {
topRect.set(childView.getLeft(), childView.getTop(),
childView.getRight(), childView.getBottom());
} // 更新childView的位置
childView.layout(childView.getLeft(), childView.getTop()
- deltaY / 3, childView.getRight(),
childView.getBottom() - deltaY / 3);
}
break;
case MotionEvent.ACTION_UP:
if (!topRect.isEmpty()) {
upDownMoveAnimation();
// 子控件回到初始位置
childView.layout(topRect.left, topRect.top, topRect.right,
topRect.bottom);
} startY = 0;
currentY = 0;
topRect.setEmpty();
break;
default:
break;
} return super.dispatchTouchEvent(event);
} // 初始化上下回弹的动画效果
private void upDownMoveAnimation() {
TranslateAnimation animation = new TranslateAnimation(0.0f, 0.0f,
childView.getTop(), topRect.top);
animation.setDuration(200);
animation.setInterpolator(new AccelerateInterpolator());
childView.setAnimation(animation);
}
}
05-11 17:13