首页3--界面上拉下拉的回弹效果

public class MyScrollView extends ScrollView {

    private View childView;

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

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

    public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

//    @Override
//    protected void onLayout(boolean changed, int l, int t, int r, int b) {
//        super.onLayout(changed, l, t, r, b);
//    }

    //获取子视图
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        if (getChildCount() > 0) {
            childView = getChildAt(0);
        }
    }

    private int lastY;//上一次y轴方向操作的坐标位置
    private Rect normal = new Rect();//用于记录临界状态的左、上、右、下
    private boolean isFinishAnimation = true;//是否动画结束

    private int lastX, downX, downY;

    //拦截:实现父视图对子视图的拦截
    //是否拦截成功,取决于方法的返回值。返回值true:拦截成功。反之,拦截失败
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean isIntercept = false;
        int eventX = (int) ev.getX();
        int eventY = (int) ev.getY();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastX = downX = eventX;
                lastY = downY = eventY;
                break;
            case MotionEvent.ACTION_MOVE:
                //获取水平和垂直方向的移动距离
                int absX = Math.abs(eventX - downX);
                int absY = Math.abs(eventY - downY);

                if(absY > absX && absY >= UIUtils.dp2px(10)){
                    isIntercept = true;//执行拦截
                }

                lastX = eventX;
                lastY = eventY;
                break;
        }

        return isIntercept;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (childView == null || !isFinishAnimation) {
            return super.onTouchEvent(ev);
        }

        int eventY = (int) ev.getY();//获取当前的y轴坐标
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastY = eventY;
                break;
            case MotionEvent.ACTION_MOVE:
                int dy = eventY - lastY;//微小的移动量

                if (isNeedMove()) {
                    if (normal.isEmpty()) {
                        //记录了childView的临界状态的左、上、右、下
                        normal.set(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom());
                    }
                    //重新布局
                    childView.layout(childView.getLeft(), childView.getTop() + dy / 2, childView.getRight(), childView.getBottom() + dy / 2);
                }

                lastY = eventY;//重新赋值
                break;
            case MotionEvent.ACTION_UP:
                if (isNeedAnimation()) {
                    //使用平移动画
                    int translateY = childView.getBottom() - normal.bottom;
                    TranslateAnimation translateAnimation = new TranslateAnimation(0, 0, 0, -translateY);
                    translateAnimation.setDuration(200);
//                translateAnimation.setFillAfter(true);//停留在最终位置上
                    translateAnimation.setAnimationListener(new Animation.AnimationListener() {
                        @Override
                        public void onAnimationStart(Animation animation) {
                            isFinishAnimation = false;
                        }

                        @Override
                        public void onAnimationEnd(Animation animation) {
                            isFinishAnimation = true;
                            childView.clearAnimation();//清除动画
                            //重新布局
                            childView.layout(normal.left, normal.top, normal.right, normal.bottom);
                            //清除normal的数据
                            normal.setEmpty();
                        }

                        @Override
                        public void onAnimationRepeat(Animation animation) {
                        }
                    });
                    //启动动画
                    childView.startAnimation(translateAnimation);
                }
                break;
        }

        return super.onTouchEvent(ev);
    }

    //判断是否需要执行平移动画
    private boolean isNeedAnimation() {
        return !normal.isEmpty();
    }

    private boolean isNeedMove() {
        int childMeasuredHeight = childView.getMeasuredHeight();//获取子视图的高度
        int scrollViewMeasuredHeight = this.getMeasuredHeight();//获取布局的高度

        Log.e("TAG", "childMeasuredHeight = " + childMeasuredHeight);
        Log.e("TAG", "scrollViewMeasuredHeight = " + scrollViewMeasuredHeight);

        int dy = childMeasuredHeight - scrollViewMeasuredHeight;//dy >= 0

        int scrollY = this.getScrollY();//获取用户在y轴方向上的偏移量 (上 + 下 -)
        if (scrollY <= 0 || scrollY >= dy) {
            return true;//按照我们自定义的MyScrollView的方式处理
        }
        //其他处在临界范围内的,返回false。即表示,仍按照ScrollView的方式处理
        return false;
    }
}

  

时间: 2024-08-06 06:52:03

首页3--界面上拉下拉的回弹效果的相关文章

打造android万能上拉下拉刷新框架——XRefreshView (二)

打造Android万能上拉下拉刷新框架--XRefreshView(一) 打造Android万能上拉下拉刷新框架--XRefreshView(三) 一.前言 自从上次发表了打造android万能上拉下拉刷新框架--XRefreshView (一)之后,期间的大半个月一直都非常忙.可是我每天晚上下班以后都有在更新和维护XRefreshView,也依据一些朋友的意见攻克了一些问题,这次之所以写这篇文章.是由于XRefreshView已经到了一个功能相对可靠和稳定的一个阶段.以下我会介绍下Xrefre

ListView实现上拉下拉刷新加载功能

第一步.首先在你项目中创建一个包存放支持下拉刷新和上拉加载的类: 第二步.需要把两个动画导入进来,实现180度旋转与360度旋转: 第三步.需要把支持的下拉与上拉显示的隐藏加载布局给导入进来 第四步.需要添加strings.xml与colors.xml文件的内容添加到项目里面: strings.xml <string name="pull_to_refresh">下拉刷新</string> <string name="release_to_ref

打造Android万能上拉下拉刷新框架--XRefreshView(三)

转载请注明出处:http://blog.csdn.net/footballclub/ 打造Android万能上拉下拉刷新框架–XRefreshView(一) 打造Android万能上拉下拉刷新框架–XRefreshView(二) XRefreshView更新说明 这段时间一直有朋友给我反馈,让我帮忙解决问题,我汇总了下,有以下几种: 1. 处理listview滑动删除与XRefreshView的冲突 2. 处理viewpager和XRefreshView的冲突 3. listview滑动到底部自

iOS 上拉下拉刷新

1 把李明杰的MJRfresh文件夹拖到工程中 2 然后引入头文件 3 在.m 文件中设置两个变量 4 在viewDidLoad里调用两个方法 5 实现需要调用的两个方法 iOS 上拉下拉刷新,布布扣,bubuko.com

iOS不得姐项目--精华模块上拉下拉的注意事项,日期显示,重构子控制器,计算cell的高度(只计算一次),图片帖子的显示

一.上拉下拉注意事项 使用MJRefresh中的上拉控件自动设置透明 当请求下页数据通过page的时候,注意的是上拉加载更多数据失败的问题,下拉加载数据失败了,页数应该还原.或者是请求成功的时候再将页数修改 二.帖子中的日期显示问题(操作日期的两个类的使用) 期望达到的效果:如图 <1>NSDate -- 需要通过NSDateFormatter(日期格式类)将日期转换成相同的格式,才能相互运算,计算出来的时间间隔是以秒数来呈现的. <2>NSCalendar(日历类) -- 通过当

练习使用XRecyclerView,可上拉下拉刷新。

1 package com.lixu.testxrecyclerview; 2 import android.support.v7.app.AppCompatActivity; 3 import android.os.Bundle; 4 import android.support.v7.widget.StaggeredGridLayoutManager; 5 import android.view.LayoutInflater; 6 import android.view.View; 7 im

打造android万能上拉下拉刷新框架——XRefreshView (一)

一.写在开头的话 之所以写这个东西是因为项目中有用到,需要给stickylistheaders加个刷新,其实就是个framelayout里面有个listview的自定义view布局,但是一些知名的刷新框架我试了下都不支持,pulltoRefresh和XListView都是自己实现了一个可刷新的view,然后让我们来直接使用这个可刷新的view,从而达到可以上拉下拉刷新的目的.我这个需求需要的是一个我告诉他什么时候需要刷新他就能帮我刷新的框架,也就是说不管什么view,只要能告诉框架自己什么时候需

上拉下拉-不刷新特效

上拉下拉-不刷新特效 上拉刷新数据.下拉刷新数据.上拉不刷新数据.下拉不刷新数据 下载地址:http://www.devstore.cn/code/info/1022.html 运行截图:     版权声明:本文为博主原创文章,未经博主允许不得转载.

jq 筛选选择器,方法,隐式迭代 元素显示隐藏 淡入淡出 上拉下拉 动画 类名操作以及样式

jQuery 地址:https://jquery.com/ 历史版本:http://code.jquery.com/ 1.x:兼容 IE678 低版本浏览器 2.x:不兼容 IE678 低版本浏览器 3.x:不兼容 IE678 低版本浏览器,官方主要维护版本 入口函数 // 一下两种入口函数 相当于原生中的 DOMContentLoaded $(function () { /* DOM加载完成的入口*/ }) $(document).ready(function(){ /* DOM加载完成的入口