文档章节

【Android】Android开发实现带有反弹效果,仿IOS反弹scrollview详解教程

程序员小冰
 程序员小冰
发布于 2016/10/27 21:45
字数 1156
阅读 35
收藏 0

作者:程序员小冰,GitHub主页:https://github.com/QQ986945193
新浪微博:http://weibo.com/mcxiaobing
首先给大家看一下我们今天这个最终实现的效果图:
这里写图片描述
这个是ios中的反弹效果。当然我们安卓中如果想要实现这种效果,
感觉不会那么生硬,滚动到底部或者顶部的时候。当然
使用scrollview是无法实现的。所以我们需要新建一个view继承ScrollView

package davidbouncescrollview.qq986945193.com.davidbouncescrollview;

import android.annotation.SuppressLint;
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;

/** * @author :程序员小冰 * @新浪微博 :http://weibo.com/mcxiaobing * @GitHub:https://github.com/QQ986945193 * @CSDN博客: http://blog.csdn.net/qq_21376985 * @交流Qq :986945193 * 类名:带有反弹效果的scrollview */
public class BounceScrollView extends ScrollView {
    private View inner;// 孩子View

    private float y;// 点击时y坐标

    private Rect normal = new Rect();// 矩形(这里只是个形式,只是用于判断是否需要动画.)

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

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

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

    /*** * 监听touch */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (inner != null) {
            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. 之后记录准确了就正常执行. * https://github.com/QQ986945193 */
            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());
                    }
// Log.e("jj", "矩形:" + 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);

// Log.e("jj", "回归:" + normal.left + "," + normal.top + "," + normal.right
// + "," + normal.bottom);

        normal.setEmpty();

    }

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

    /*** * 是否需要移动布局 inner.getMeasuredHeight():获取的是控件的总高度 * <p/> * getHeight():获取的是屏幕的高度 * <p/> * https://github.com/QQ986945193 * * @return */
    public boolean isNeedMove() {
        int offset = inner.getMeasuredHeight() - getHeight();
        int scrollY = getScrollY();
// Log.e("jj", "scrolly=" + scrollY);
        // 0是顶部,后面那个是底部
        if (scrollY == 0 || scrollY == offset) {
            return true;
        }
        return false;
    }
}

然后他的用法就是和ScrollView用法一样了。比如直接在布局中引用:

<?xml version="1.0" encoding="utf-8"?>
<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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="davidbouncescrollview.qq986945193.com.davidbouncescrollview.MainActivity">

    <davidbouncescrollview.qq986945193.com.davidbouncescrollview.BounceScrollView  android:layout_width="match_parent" android:layout_height="match_parent">

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

            <View  android:layout_width="match_parent" android:layout_height="1dp" android:background="@android:color/black" />

            <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="大家好,我是程序员小冰" />

            <View  android:layout_width="match_parent" android:layout_height="1dp" android:background="@android:color/black" />

            <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="大家好,我是程序员小冰" />

            <View  android:layout_width="match_parent" android:layout_height="1dp" android:background="@android:color/black" />

            <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="大家好,我是程序员小冰" />

            <View  android:layout_width="match_parent" android:layout_height="1dp" android:background="@android:color/black" />

            <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="大家好,我是程序员小冰" />

            <View  android:layout_width="match_parent" android:layout_height="1dp" android:background="@android:color/black" />

            <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="大家好,我是程序员小冰" />

            <View  android:layout_width="match_parent" android:layout_height="1dp" android:background="@android:color/black" />

            <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="大家好,我是程序员小冰" />

            <View  android:layout_width="match_parent" android:layout_height="1dp" android:background="@android:color/black" />

            <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="大家好,我是程序员小冰" />

            <View  android:layout_width="match_parent" android:layout_height="1dp" android:background="@android:color/black" />

            <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="大家好,我是程序员小冰" />
        </LinearLayout>

    </davidbouncescrollview.qq986945193.com.davidbouncescrollview.BounceScrollView>

</LinearLayout>

最后直接运行即可看到上面的效果。
(AndroidStudio版)github下载地址:
https://github.com/QQ986945193/DavidBounceScrollView
(AndroidStudio版)CSDN免积分下载地址:
http://download.csdn.net/detail/qq_21376985/9624856
(AndroidStudio版)git开源中国下载地址:
http://git.oschina.net/MCXIAOBING/DavidBounceScrollView

本文转载自:http://blog.csdn.net/qq_21376985/article/details/52468306

程序员小冰

程序员小冰

粉丝 14
博文 162
码字总数 147
作品 4
深圳
程序员
私信 提问
Android开发优秀博文收录

Android 完美实现图片圆角和圆形(对实现进行分析) 2.Android之Loader理解 3.Android Loader详解一:概述 4. Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅 5. And...

JayPark不作死
2014/09/29
0
0
【React Native开发】React Native控件之WebView组件详解以及实例使用(22)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jiangqq781931404/article/details/50676379 import React, {AppRegistry,Component,StyleSheet,Text,View,We......

江清清
2016/02/16
0
0
驰骋工作流引擎-CCMobile与安卓、IOS集成过程中的问题与解决方案

CCMobile与安卓、IOS集成过程中的问题与解决方案 前言: CCMobile(2019版本)是CCFlow&JFlow 的一款移动端审批的产品。系统基于mui框架开发,是一款可以兼容Android与IOS的移动端工作流审批...

孟娟
今天
0
0
【React Native开发】React Native控件之RefreshControl组件详解(21)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jiangqq781931404/article/details/50672747 const React =require('react-native');const {AppRegistry,Scro......

江清清
2016/02/16
0
0
fir.im Weekly - iOS 开发中的 Git 流程

本期 fir.im Weekly 收集了微博上的热转资源,包含 Android、iOS 开发工具、源码等好用的轮子,还有一些 APP 设计的 Tips,希望对你有用。 精仿知乎日报 iOS 端 @我偏笑_NSNirvana花了将近一...

风起云飞fir_im
2015/11/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

vmstat命令详解

https://www.cnblogs.com/ggjucheng/archive/2012/01/05/2312625.html

流光韶逝
35分钟前
1
0
如何理解算法时间复杂度的表示

先从O(1) 来说,理论上哈希表就是O(1)。因为哈希表是通过哈希函数来映射的,所以拿到一个关键 字,用哈希函数转换一下,就可以直接从表中取出对应的值。和现存数据有多少毫无关系,故而每次执...

yky20190625
51分钟前
5
0
分布式架构 实现分布式锁的常见方式

一、我们为什么需要分布式锁? 在单机时代,虽然不需要分布式锁,但也面临过类似的问题,只不过在单机的情况下,如果有多个线程要同时访问某个共享资源的时候,我们可以采用线程间加锁的机制...

太猪-YJ
今天
8
0
GitLab Docker 安装记录

安装环境 环境Centos7.4 64 1.拉取镜像文件 docker pull gitlab/gitlab-ce:latest 2.docker 安装 git.zddts.com 为访问域名或换成可以访问的IP docker run -d --hostname git.***.com -p ......

侠者圣
今天
0
0
EfficientNet: 再论 CNN 的网络规模

由于这里公式无法正常显示,所有内容以图片内容上传,如有需要,可提供 pdf 版。

爱吃草莓的皮卡丘
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部