Android仿IOS上拉下拉弹性效果的实例代码
作者:IT_默 发布时间:2023-08-26 06:49:18
标签:Android,仿IOS,上拉,下拉,弹性
用过iphone的朋友相信都体验过页面上拉下拉有一个弹性的效果,使用起来用户体验很好;Android并没有给我们封装这样一个效果,我们来看下在Android里如何实现这个效果。先看效果,感觉有些时候还是蛮实用的。
思路:其实原理很简单,实现一个自定义的Scrollview方法(来自网上大神),然后在布局文件中使用自定义方法Scrollview就可以了。
代码:
自定义View,继承自Scrollview。MyReboundScrollView类
package com.wj.myreboundscrollview.customview;
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;
//仿ios可上提下拉的ScrollView
public class MyReboundScrollView extends ScrollView {
private static final String TAG = "ElasticScrollView";
//移动因子, 是一个百分比, 比如手指移动了100px, 那么View就只移动50px
//目的是达到一个延迟的效果
private static final float MOVE_FACTOR = 0.5f;
//松开手指后, 界面回到正常位置需要的动画时间
private static final int ANIM_TIME = 100;
//ScrollView的子View, 也是ScrollView的唯一一个子View
private View contentView;
//手指按下时的Y值, 用于在移动时计算移动距离
//如果按下时不能上拉和下拉, 会在手指移动时更新为当前手指的Y值
private float startY;
//用于记录正常的布局位置
private Rect originalRect = new Rect();
//手指按下时记录是否可以继续下拉
private boolean canPullDown = false;
//手指按下时记录是否可以继续上拉
private boolean canPullUp = false;
//在手指滑动的过程中记录是否移动了布局
private boolean isMoved = false;
public MyReboundScrollView(Context context) {
super(context);
}
public MyReboundScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
if (getChildCount() > 0) {
contentView = getChildAt(0);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if(contentView == null) return;
//ScrollView中的唯一子控件的位置信息, 这个位置信息在整个控件的生命周期中保持不变
originalRect.set(contentView.getLeft(), contentView.getTop(), contentView
.getRight(), contentView.getBottom());
}
//在触摸事件中, 处理上拉和下拉的逻辑
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (contentView == null) {
return super.dispatchTouchEvent(ev);
}
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
//判断是否可以上拉和下拉
canPullDown = isCanPullDown();
canPullUp = isCanPullUp();
//记录按下时的Y值
startY = ev.getY();
break;
case MotionEvent.ACTION_UP:
if(!isMoved) break; //如果没有移动布局, 则跳过执行
// 开启动画
TranslateAnimation anim = new TranslateAnimation(0, 0, contentView.getTop(),
originalRect.top);
anim.setDuration(ANIM_TIME);
contentView.startAnimation(anim);
// 设置回到正常的布局位置
contentView.layout(originalRect.left, originalRect.top,
originalRect.right, originalRect.bottom);
//将标志位设回false
canPullDown = false;
canPullUp = false;
isMoved = false;
break;
case MotionEvent.ACTION_MOVE:
//在移动的过程中, 既没有滚动到可以上拉的程度, 也没有滚动到可以下拉的程度
if(!canPullDown && !canPullUp) {
startY = ev.getY();
canPullDown = isCanPullDown();
canPullUp = isCanPullUp();
break;
}
//计算手指移动的距离
float nowY = ev.getY();
int deltaY = (int) (nowY - startY);
//是否应该移动布局
boolean shouldMove =
(canPullDown && deltaY > 0) //可以下拉, 并且手指向下移动
|| (canPullUp && deltaY< 0) //可以上拉, 并且手指向上移动
|| (canPullUp && canPullDown); //既可以上拉也可以下拉(这种情况出现在ScrollView包裹的控件比ScrollView还小)
if(shouldMove){
//计算偏移量
int offset = (int)(deltaY * MOVE_FACTOR);
//随着手指的移动而移动布局
contentView.layout(originalRect.left, originalRect.top + offset,
originalRect.right, originalRect.bottom + offset);
isMoved = true; //记录移动了布局
}
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
//判断是否滚动到顶部
private boolean isCanPullDown() {
return getScrollY() == 0 ||
contentView.getHeight() < getHeight() + getScrollY();
}
//判断是否滚动到底部
private boolean isCanPullUp() {
return contentView.getHeight() <= getHeight() + getScrollY();
}
}
代码注释非常清楚。
布局文件直接使用
<com.wj.myreboundscrollview.customview.MyReboundScrollView
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"
tools:context=".MainActivity"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dip"
android:hint="Your Name"/>
<EditText
android:id="@+id/et_feedback"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dip"
android:hint="Your Feedback"
android:lines="5"/>
<Button
android:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="42dip"
android:text="Submit"
android:onClick="submit"/>
</LinearLayout>
</com.wj.myreboundscrollview.customview.MyReboundScrollView>
这里直接在外层包裹实现。注意,因为Myreboundscrollview是继承自Scrollview,因此要遵循Scrollview的使用原则,里面只能包含一个LinearLayout,所以无论里面多门复杂的布局,最后我们都要将其包含在一个LinearLayout中。
ok,功能实现,效果也演示,具体需要使用直接拿来用就可以。
来源:http://blog.csdn.net/u014733374/article/details/42739345


猜你喜欢
- Android 使用log4j前言: 如果要直接在android工程中使用log4j,是有点问题的,会报如下的错: 1
- 本文实例讲述了Android实现打开各种文件的intent方法。分享给大家供大家参考,具体如下:import android.app.Act
- Java InputStream的任意拷贝有时候,当我们需要多次使用到同一个InputStream的时候如何实现InputStream的拷贝
- 本文实例为大家分享了Java身份证号码校验工具类的具体代码,供大家参考,具体内容如下import java.text.ParseExcept
- 1、什么是线程及线程池线程是操作系统进行时序调度的基本单元。线程池可以理解为一个存在线程的池子,就是一个容器,这个容器只能存在线程。这个容器
- 前言异步调用几乎是处理高并发,解决性能问题常用的手段,如何开启异步调用?SpringBoot中提供了非常简单的方式,就是一个注解@Async
- QTableWidget 是 Qt 中的表格组件类。在窗体上放置一个 QTableWidget 组件后,可以在 Property Edito
- 本文实例讲述了Android编程之防止反编译的实现方法。分享给大家供大家参考,具体如下:1. 判断程序是否运行在模拟器上boolean is
- 如果JDBC连接是在自动提交模式下,它在默认情况下,那么每个SQL语句都是在其完成时提交到数据库。这可能是对简单的应用程序,但有三个原因,你
- stopWatch是org.springframework.util包下的一个工具类,使用它可直观的输出代码执行耗时,以及执行时间百分比,瞬
- 本文实例讲述了C#实现合并多个word文档的方法,是非常具有实用价值的技巧。分享给大家供大家参考。具体实现方法如下:using System
- 功能目标使用Treeview控件实现点左边的节点,在右边显示相关的页面知识点Treeview命名空间:System.Windows.Form
- 一、前言开发中经常要处理用户一些文字的提交,所以涉及到了敏感词过滤的功能,参考资料中DFA有穷状态机算法的实现,创建有向图。完成了对敏感词、
- 本文实例讲述了Android实现完整游戏循环的方法。分享给大家供大家参考。具体如下:1. DroidzActivity.java:packa
- 目录1.文件读写1.1打开文件1.2关闭文件1.3读取文件1.4写入文件1.5读写二进制I/O文件1.6获取文件的大小1.7文本简单加密、解
- 本文实例为大家分享了Androidstudio调用摄像头拍照并保存照片的具体代码,供大家参考,具体内容如下首先在manifest.xmlns
- 开发环境win10Android Studio效果用于多级菜单展示,或选择。如 每个省,市,县;如 树木的病虫害;关键代码 @overrid
- 动态数组ArrayList类在System.Collecions的命名空间下,所以使用时要加入System.Collecions命名空间,而
- 基本流foreach 实现了外部迭代,它是建立于集合的基础上;stream 流实现的是内部迭代中间操作与终端操作对任意集合使用 stream
- 简介关于IDEA的介绍,引用自百度百科:IDEA全称 IntelliJ IDEA,是java编程语言开发的集成环境。IntelliJ在业界被