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); } }
时间: 2024-11-07 04:35:48