自动回滚ScrollView
来源:互联网 发布:网络形容男人的词 编辑:程序博客网 时间:2024/04/29 19:25
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;
public class RollbackScrollView extends ScrollView {
private View inner; // 孩子View
private static final int DEFAULT_POSITION = -1;
private float y = DEFAULT_POSITION;// 点击时y的坐标
private Rect normal = new Rect();
// 滑动距离及坐标
private float xDistance, yDistance, xLast, yLast;
public RollbackScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 根据XML生成视图工作完成,该函数在生成视图的最后调用,在所有子视图添加完成之后, 即使子类覆盖了onFinishInflate
* 方法,也应该调用父类的方法, 使得该方法得以执行
*/
@Override
protected void onFinishInflate() {
if (getChildCount() > 0) {
inner = getChildAt(0);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (inner == null) {
return super.onTouchEvent(ev);
} else {
commOnTouchEvent(ev);
}
return super.onTouchEvent(ev);
}
public void commOnTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
y = ev.getY();
break;
case MotionEvent.ACTION_UP:
if (isNeedAnimation()) {
animation();
}
y = DEFAULT_POSITION;
break;
/**
* 排除第一次移动计算,因为第一次无法得知y左边,在MotionEvent.ACTION_DOWN中获取不到,
* 因为此时是MyScrollView的Tocuh时间传递到了ListView的孩子item上面。所以从第二次开始计算
* 然而我们也要进行初始化,就是第一次移动的时候让滑动距离归零,之后记录准确了就正常执行
*/
case MotionEvent.ACTION_MOVE:
float preY = y;
float nowY = ev.getY();
if (isDefaultPosition(y)) {
preY = nowY;
}
int deltaY = (int) (preY - nowY);
scrollBy(0, deltaY);
y = nowY;
// 当滚动到最上或者最下时就不会再滚动,这时移动布局
if (isNeedMove()) {
if (normal.isEmpty()) {
// 保存正常的布局位置
normal.set(inner.getLeft(), inner.getTop(),
inner.getRight(), inner.getBottom());
}
// 移动布局
inner.layout(inner.getLeft(), inner.getTop() - deltaY,
inner.getRight(), inner.getBottom() - deltaY);
}
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);
normal.setEmpty();
}
// 是否需要开启动画
public boolean isNeedAnimation() {
return !normal.isEmpty();
}
// 是否需要移动布局
public boolean isNeedMove() {
int offset = inner.getMeasuredHeight() - getHeight();
int scrollY = getScrollY();
if (scrollY == 0 || scrollY == offset) {
return true;
}
return false;
}
// 检查是否处于默认位置
private boolean isDefaultPosition(float position) {
return position == DEFAULT_POSITION;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
xLast = ev.getX();
yLast = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
xDistance += Math.abs(curX - xLast);
yDistance += Math.abs(curY - yLast);
xLast = curX;
yLast = curY;
if (xDistance > yDistance) {
return false;
}
}
return super.onInterceptTouchEvent(ev);
}
}
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;
public class RollbackScrollView extends ScrollView {
private View inner; // 孩子View
private static final int DEFAULT_POSITION = -1;
private float y = DEFAULT_POSITION;// 点击时y的坐标
private Rect normal = new Rect();
// 滑动距离及坐标
private float xDistance, yDistance, xLast, yLast;
public RollbackScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 根据XML生成视图工作完成,该函数在生成视图的最后调用,在所有子视图添加完成之后, 即使子类覆盖了onFinishInflate
* 方法,也应该调用父类的方法, 使得该方法得以执行
*/
@Override
protected void onFinishInflate() {
if (getChildCount() > 0) {
inner = getChildAt(0);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (inner == null) {
return super.onTouchEvent(ev);
} else {
commOnTouchEvent(ev);
}
return super.onTouchEvent(ev);
}
public void commOnTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
y = ev.getY();
break;
case MotionEvent.ACTION_UP:
if (isNeedAnimation()) {
animation();
}
y = DEFAULT_POSITION;
break;
/**
* 排除第一次移动计算,因为第一次无法得知y左边,在MotionEvent.ACTION_DOWN中获取不到,
* 因为此时是MyScrollView的Tocuh时间传递到了ListView的孩子item上面。所以从第二次开始计算
* 然而我们也要进行初始化,就是第一次移动的时候让滑动距离归零,之后记录准确了就正常执行
*/
case MotionEvent.ACTION_MOVE:
float preY = y;
float nowY = ev.getY();
if (isDefaultPosition(y)) {
preY = nowY;
}
int deltaY = (int) (preY - nowY);
scrollBy(0, deltaY);
y = nowY;
// 当滚动到最上或者最下时就不会再滚动,这时移动布局
if (isNeedMove()) {
if (normal.isEmpty()) {
// 保存正常的布局位置
normal.set(inner.getLeft(), inner.getTop(),
inner.getRight(), inner.getBottom());
}
// 移动布局
inner.layout(inner.getLeft(), inner.getTop() - deltaY,
inner.getRight(), inner.getBottom() - deltaY);
}
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);
normal.setEmpty();
}
// 是否需要开启动画
public boolean isNeedAnimation() {
return !normal.isEmpty();
}
// 是否需要移动布局
public boolean isNeedMove() {
int offset = inner.getMeasuredHeight() - getHeight();
int scrollY = getScrollY();
if (scrollY == 0 || scrollY == offset) {
return true;
}
return false;
}
// 检查是否处于默认位置
private boolean isDefaultPosition(float position) {
return position == DEFAULT_POSITION;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
xLast = ev.getX();
yLast = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
xDistance += Math.abs(curX - xLast);
yDistance += Math.abs(curY - yLast);
xLast = curX;
yLast = curY;
if (xDistance > yDistance) {
return false;
}
}
return super.onInterceptTouchEvent(ev);
}
}
0 0
- 自动回滚ScrollView
- ScrollView滚回顶部
- ScrollView滚回顶部
- 安卓ScrollView实现自动滚屏
- 让ScrollView自动滚到顶部
- Android ScrollView自动滚屏或者直接滚屏到底部
- iOS 点击状态栏回滚scrollView顶部
- ScrollView嵌套可滑动控件(RecyclerView、ListView、GraidView等),ScrollView会自动滚到底部
- 自动回滚的listview
- scrollView 滑动滚广告
- amdroid小知识之——ScrollView滚回顶部
- Spring自动回滚的事务管理配置
- junit 单元测试事务自动回滚
- Spring-test事务自动回滚
- android scrollView滚到底部
- Spring事务为什么不会自动回滚?Spring事务怎样才会自动回滚?事务自动回滚条件及手动回滚
- 用TPKeyboardAvoidingScrollView在scrollview中实现自动上滚,避免键盘遮盖住了textfield,textview等控件
- TPKeyboardAvoidingScrollView用于在scrollview中实现自动上滚,避免键盘遮盖住了textfield,textview等控件。
- 一起学Java设计模式--工厂方法模式(不在23种设计模式之内)
- oracle中INDEX BY BINARY_INTEGER 的作用
- Uva 数据
- 解决VS2013不默认支持多字符编码的问题,有代价
- 指向学生类的指针
- 自动回滚ScrollView
- 黑马程序员之java核心部分面向对象1
- oracle服务器和客户端字符集的查看和修改
- 用户、组
- VM下两个linux串口连接的问题
- IAR 8.3以后的版本编译TI BLE Stack会报类似如下的错误
- oracle--left join and 和left join where的区别
- Weblogic学习笔记-weblogic12c安装
- 我们可以转身,但是不必回头