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

首先给大家看一下我们今天这个最终实现的效果图:

 

这个是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

以上所述是小编给大家介绍的Android开发实现带有反弹效果仿IOS反弹scrollview教程详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索ios
scrollview反弹
scrollview反弹效果、scrollview详解、nestedscrollview详解、scrollview属性详解、qt scrollarea详解,以便于您获取更多的相关知识。

时间: 2024-10-31 14:13:10

Android开发实现带有反弹效果仿IOS反弹scrollview教程详解_Android的相关文章

Android开发之基本控件和四种布局方式详解_Android

Android中的控件的使用方式和iOS中控件的使用方式基本相同,都是事件驱动.给控件添加事件也有接口回调和委托代理的方式.今天这篇博客就总结一下Android中常用的基本控件以及布局方式.说到布局方式Android和iOS还是区别挺大的,在iOS中有Frame绝对布局和AutoLayout相对布局.而在Android中的布局方式就比较丰富了,今天博客中会介绍四种常用的布局方式.先总结一下控件,然后再搞一搞基本方式,开发环境还是用的Mac下的Android Studio.开始今天的正题, 虽然A

Android开发笔记之:一分钟学会使用Logcat调试程序的详解_Android

这是个很简单的问题,但每次隔一段时间后使用起来总是会出点乱子.这里记录下Logcat的步骤:1,在Activity里申明tag变量(名字其实是随便的,如下:private static final String tag="yan";2,需要使用logcat输出信息时:Log.i(tag, "屏幕宽度:"+display.getWidth()+" 屏幕高度:"+display.getHeight());3, 双击Logcat,点击"+&q

Android开发之基本控件和四种布局方式详解

Android中的控件的使用方式和iOS中控件的使用方式基本相同,都是事件驱动.给控件添加事件也有接口回调和委托代理的方式.今天这篇博客就总结一下Android中常用的基本控件以及布局方式.说到布局方式Android和iOS还是区别挺大的,在iOS中有Frame绝对布局和AutoLayout相对布局.而在Android中的布局方式就比较丰富了,今天博客中会介绍四种常用的布局方式.先总结一下控件,然后再搞一搞基本方式,开发环境还是用的Mac下的Android Studio.开始今天的正题, 虽然A

Android开发高仿课程表的布局实例详解_Android

先说下这个demo,这是一个模仿课程表的布局文件,虽然我是个菜鸟,但我还是想留给学习的人一些例子,先看下效果   然后再来看一下我们学校的app 布局分析 先上一张划分好了的布局图 首先整个页面放在一个LinearLayout布局下面,分为上面和下面两个部分,下面一个是显示课程表的详细信息 1:这个没什么好讲的,就是直接一个LinearLayout布局,然后将控件一个TextView用来显示年份,一个View用来当作竖线,一个Spinner用来显示选择周数 2:这个是显示星期几的部件,是我自定义

Android xUtils更新到3.0后的基本使用规则详解_Android

 说实话,对于xUtils,是我最近才用到的开发框架(也是刚接触),对于其功能不得不说,简化了很多的开发步骤,可以说是非常好的开发工具,但是其最近更新到3.0也没有解决加载自定义ImageView报错的问题. xUtils简介 xUtils 包含了很多实用的android工具. xUtils 支持大文件上传,更全面的http请求协议支持(10种谓词),拥有更加灵活的ORM,更多的事件注解支持且不受混淆影响... xUitls 最低兼容android 2.2 (api level 8) 我总是喜欢

Android开发中使用WebView控件浏览网页的方法详解

本文实例讲述了Android开发中使用WebView控件浏览网页的方法.分享给大家供大家参考,具体如下: 项目中遇到数学展示问题,常规的Textview显示处理不了数学公式,利用图片生成对服务器又产生较大压力,经过查询,可以通过webview加载JS实现.IOS同样的方法也可实现,但JS渲染效率远高于安卓.对Webview做下总结. 1.WebView 在使用WebView控件时,首先需要在xml布局文件中定义一个WebView控件,定义的方法如下: <WebView android:id=&quo

Android帧动画、补间动画、属性动画用法详解_Android

在安卓开发中,经常会使用到一些动画,那么在开发中,如何使用这些动画呢? 帧动画:不是针对View做出一些形状上的变化,而是用于播放一张张的图片,例如一些开机动画,类似于电影播放,使用的是AnimationDrawable来播放帧动画 res/drawable  <?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.andro

Android AsyncTask 后监听异步加载完毕的动作详解_Android

Android 使用AsyncTask 后监听异步加载完毕的动作   AsyncTask 的使用方法网上有很多例子,使用起来也非常的方便.这里就不详细说具体的使用方法了,同学可以Google 一下,很多. 场景模拟       当我们在加载一个列表的时候,比如GridView ,这时候我们考虑到不阻塞UI的做法,一般会使用线程Thread .Timer 或者使用AsyncTask ,而这些操作都是在在后台另外开一个线程给我们找数据,具体得到的数据需要使用Handler 去更新UI,AsyncTa

Android Secret Code(输入字符弹出手机信息)详解_Android

Android Secret Code 我们很多人应该都做过这样的操作,打开拨号键盘输入*#*#4636#*#*等字符就会弹出一个界面显示手机相关的一些信息,这个功能在Android中被称为android secret code,除了这些系统预置的secret code,我们也可以实现自己的secret code,而且实现起来非常简单. 要实现自己的secret code,只需要向系统注册一个Broadcast Receiver,不需要任何权限,如下所示: <receiver android:n