ScrollView反弹效果的实现

发现非常多APP的界面都能够滑动,QQ。微信等等,自己琢磨了下。效果例如以下:

代码:ScrollView

package com.wsj.wsjdemo;

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;

/**
 * ScrollView反弹效果的实现
 */
public class VScrollView extends ScrollView {
	private View inner;// 孩子View
	private float y;// 点击时y坐标
	private int mLastMotionX;
	private int mLastMotionY;
	// 默认支持反弹效果
	private boolean isAllowRebound = true;
	private Rect normal = new Rect();// 矩形(这里仅仅是个形式。仅仅是用于推断是否须要动画.)

	private boolean isCount = false;// 是否開始计算

	public VScrollView(Context context) {
		super(context);
	}

	public VScrollView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public VScrollView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	/***
	 * 依据 XML 生成视图工作完毕.该函数在生成视图的最后调用,在全部子视图加入完之后. 即使子类覆盖了 onFinishInflate
	 * 方法,也应该调用父类的方法,使该方法得以运行.
	 */
	@Override
	protected void onFinishInflate() {
		if (getChildCount() > 0) {
			inner = getChildAt(0);
		}
	}

	public void setInnerView(View view) {
		this.inner = view;
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent e) {
		int x = (int) e.getRawX();
		int y = (int) e.getRawY();
		switch (e.getAction()) {
		case MotionEvent.ACTION_DOWN:
			mLastMotionX = x;
			mLastMotionY = y;
		case MotionEvent.ACTION_MOVE:
			int deltaX = x - mLastMotionX;
			int deltaY = y - mLastMotionY;
			if (Math.abs(deltaX) > 10 && Math.abs(deltaY) < 45) {
				return false;
			}
		}
		return super.onInterceptTouchEvent(e);
	}

	/***
	 * 监听touch
	 */
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		if (inner != null && getAllowRebound()) {
			commOnTouchEvent(ev);
		}
		return super.onTouchEvent(ev);
	}

	/***
	 * 触摸事件
	 *
	 * @param 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;
		/***
		 * 排除出第一次移动计算,由于第一次无法得知y坐标。 在MotionEvent.ACTION_DOWN中获取不到,
		 * 由于此时是MyScrollView的touch事件传递到到了LIstView的孩子item上面.所以从第二次计算開始.
		 * 然而我们也要进行初始化,就是第一次移动的时候让滑动距离归0. 之后记录准确了就正常运行.
		 */
		case MotionEvent.ACTION_MOVE:
			final float preY = y;// 按下时的y坐标
			float nowY = ev.getY();// 时时y坐标
			int deltaY = (int) (preY - nowY);// 滑动距离
			if (!isCount) {
				deltaY = 0; // 在这里要归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(250);
		inner.startAnimation(ta);
		// 设置回到正常的布局位置
		inner.layout(normal.left, normal.top, normal.right, normal.bottom);

		normal.setEmpty();

	}

	// 是否须要开启动画
	public boolean isNeedAnimation() {
		return !normal.isEmpty();
	}

	/***
	 * 是否须要移动布局 inner.getMeasuredHeight():获取的是控件的总高度
	 *
	 * getHeight():获取的是屏幕的高度
	 *
	 * @return
	 */
	public boolean isNeedMove() {
		int offset = inner.getMeasuredHeight() - getHeight();
		int scrollY = getScrollY();
		// 0是顶部,后面那个是底部
		if (scrollY == 0 || scrollY == offset) {
			return true;
		}
		return false;
	}

	public void scrollToTop() {
		// this.setScrollY(0);
		this.scrollTo(this.getLeft(), 0);
	}

	public void scrollToBottom() {
		// this.setScrollY(this.getHeight());
		this.scrollTo(this.getLeft(), this.getHeight());
	}

	public void setAllowRebound(boolean isAllowRebound) {
		this.isAllowRebound = isAllowRebound;
	}

	public boolean getAllowRebound() {
		return this.isAllowRebound;
	}

}

Main方法:什么都没有

package com.wsj.wsjdemo;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

}

仅仅须要在布局仅仅用自己定义ScrollView包括内容就可以:

<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" >

    <com.wsj.wsjdemo.VScrollView
        android:id="@+id/sv_mycenter"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        android:scrollbars="none" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />
        </LinearLayout>
    </com.wsj.wsjdemo.VScrollView>

</LinearLayout>

结束

时间: 2024-10-19 13:20:36

ScrollView反弹效果的实现的相关文章

ScrollView反弹效果 仿小米私密短信效果

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/28441197 现在很多APP都给ScrollView添加了反弹效果,QQ.小米私密短信等.恰好在网上看到一个类:BounceScrollView , 原创地址是:http://blog.csdn.net/h7870181/article/details/8960430 , 可惜作者没有提供一个效果图,于是我发现小米短信列表页往下拉,有反弹效果,且拉到1/3以上时,会打开私密短信

ScrollView反弹效果

1 public class BounceScrollView extends ScrollView { 2 private View inner;// 孩子View 3 4 private float y;// 点击时y坐标 5 6 private Rect normal = new Rect();// 矩形(这里只是个形式,只是用于判断是否需要动画.) 7 8 private boolean isCount = false;// 是否开始计算 9 10 public BounceScroll

Android 自定义ScrollView(具有反弹效果的ScrollView,能够兼容横向的滑动)

package com.itau.jingdong.widgets; 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 and

Android -- 仿ios上下反弹效果

1,前几天在一个app上看到了滑动反弹效果,觉得这个效果挺不错的,然后想自己来实现一下,在网上查了一下基本上都是大致的说了下思路,自己看了一下,决定把实现的思路来详细的写下来,先看一下我们实现的效果吧. 可以看出这个使我们自定义的ScrollView,通过两次判断(头部.底部)来将动态的将ScrollView里面的View向下平移,大体的思路就是这样,下面直接把代码贴出来了 ,包括实现的步骤和一些重要代码都写了注释了 package com.qianmo.myview2.view; /** *

CSS3 反弹效果

每日一更,今天是反弹效果集 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>CSS3-反弹-效果</title> 6 <style> 7 .element{ 8 color: #f35626; 9 background-image: -webkit-linear-gradient(92deg,#f35626,#f

WPF触控程序开发(三)——类似IPhone相册的反弹效果

用过IPhone的都知道,IPhone相册里,当图片放大到一定程度后,手指一放,会自动缩回,移动图片超出边框后手指一放,图片也会自动缩回,整个过程非常和谐.自然.精确,那么WPF能否做到呢,答案是肯定的. 在没有现成的控件的情况下,只有自己做,你肯定想到做动画,WPF触屏开发提供了相应的功能来获取触控点的一些变化,这些变化的最佳消费者个人认为是Matrix.我们回想下做动画一般怎么做,比如给一个button做个宽度增5的动画,我们一般是定义一个DoubleAnimation,然后定义一个Sotr

ios:ScrollView联动效果

1.简单的效果 简单的代码 2.主要用到scrollViewDidScroll代理方法   代码如下 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { float bigX = _fScrollView.bounds.size.width/_sScrollView.bounds.size.width; float littleX = _sScrollView.bounds.size.width/_fScrollView.bounds

Unity3D UGUI之ScrollView弹簧效果

unity3d版本5.3.2p4 UGUI中ScrollView包含Viewport(Content) ScrollView包含脚本.其Movement Type一共3个选项.Elastic就是弹簧效果. viewport含有Mask脚本. Content如果需要实现根据内容自适应高度就要添加Content Size Fitter脚本.脚本里面选择Preferred Size即可. 注:如果Content没有根据内容自适应高度,内容高度大于Content的高度的话 会出现ScrollView滚动

android 滚动栏下拉反弹的效果(相似微信朋友圈)

微信朋友圈上面的图片封面,QQ空间说说上面的图片封面都有下拉反弹的效果,这些都是使用滚动栏实现的.下拉,当松开时候.反弹至原来的位置.下拉时候能看到背景图片.那么这里简介一下这样的效果的实现. 本文源代码下载:点击 1.效果图 这部手机显示的分辨率有限,非常老的手机调试. 2.具有反弹效果BounceScrollView package com.org.scroll; import android.content.Context; import android.graphics.Rect; im