Android View的scrollTo()、scrollBy() 和Scroller类总结


Android View的scrollTo()、scrollBy() 和Scroller类总结

    ViewscrollTo()scrollBy()使用介绍
    scrollTo()scrollBy()实践,自定义滑动效果
    Scroller滑动辅助类,startScroll()computeScrollOffset()使用介绍
    Scroller实践,使用示例
    总结

一、View的scrollTo()、scrollBy()
1.1 scrollTo scrollBy 使用说明

scrollTo()scrollBy()方法是View中的,因此任何的View都可以通过这两种方法进行移动。首先要明白的是,scrollTo、scrollBy滑动的是View中的内容(而且还是整体滑动),而不是View本身。我们的滑动控件如SrollView可以限定宽、高大小,以及在布局中的位置,但是滑动控件中的内容(或者里面的childView)可以是无限长、宽的,我们调用View的scrollTo、scrollBy方法,相当于是移动滑动控件中的画布Canvas,然后进行重绘,屏幕上也就显示相应的内容。

1.2 scrollTo使用介绍

调用scrollTo(100,0)表示将View中的内容移动到距离内容初始显示位置的x=100,y=0的地方,效果如下图:Android View的scrollTo()、scrollBy() 和Scroller类总结
调用scrollTo(0,100)效果如下图:Android View的scrollTo()、scrollBy() 和Scroller类总结
调用scrollTo(100,100)效果如下图:
Android View的scrollTo()、scrollBy() 和Scroller类总结

1.3 scrollBy使用介绍

调用scrollBy(0,100)表示将View中的内容移动到原内容基础上x=x + 0,y=y + 100的地方,所以scrollBy是在原来的基础上移动的,效果如下图:Android View的scrollTo()、scrollBy() 和Scroller类总结
scrollBy()的源码中其实也非常简单调用的就是scrollTo(),只不过是加上了当前的mScrollX或者 mScrollY

	public void scrollBy(int x, int y) {
scrollTo(mScrollX + x, mScrollY + y);
}

二、scrollTo和scrollBy实践,自定义滑动效果

通过上面几个图,可以清楚看到scrollTo和scrollBy的作用和滑动坐标系的关系。在实际使用中,我们一般是在onTouchEvent()方法中处理滑动事件,在MotionEvent.ACTION_MOVE时调用scrollTo(int x,int y)进行滑动,在调用scrollTo(int x,int y)前,我们先要计算出两个参数值,即水平和垂直方向需要滑动的距离,如下:

public class ScrollActivity extends AppCompatActivity {

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scroll);
}

private int mLastX;
private int mLastY;

@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
int x = (int) event.getX();
int action = event.getAction();
View decorView = getWindow().getDecorView();
switch (action) {
case MotionEvent.ACTION_DOWN:
mLastY = y;
mLastX = x;
break;
case MotionEvent.ACTION_MOVE:
int dy = mLastY - y;//本次手势滑动了多大距离
int dx = mLastX - x;
int oldScrollY = decorView.getScrollY();//先计算之前已经偏移了多少距离
int oldScrollX = decorView.getScrollX();
int scrollY = oldScrollY + dy;//本次需要偏移的距离=之前已经偏移的距离+本次手势滑动了多大距离
int scrollX = oldScrollX + dx;
decorView.scrollTo(scrollX, scrollY);
mLastY = y;
mLastX = x;
break;
}
return true;
}
}

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
android:gravity="center">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/colorAccent"
android:gravity="center"
android:padding="10dp"
android:text="scroll..."
android:textSize="24sp"
android:textStyle="bold" />

</LinearLayout>

效果图如下:
Android View的scrollTo()、scrollBy() 和Scroller类总结

三、Scroller滑动辅助类
3.1 Scroller使用说明

根据我们上面的分析,可知View的scrollTo()scrollBy()是瞬间完成的,当我们的手指在屏幕上移动时,内容会跟着手指滑动,但是当我们手指一抬起时,滑动就会停止,如果我们想要有一种惯性的滚动过程效果和回弹效果,此时就需要使用Scroller辅助类。
但是注意的是,Scroller本身不会去移动View,它只是一个移动计算辅助类,用于跟踪控件滑动的轨迹,只相当于一个滚动轨迹记录工具,最终还是通过ViewscrollToscrollBy方法完成View的移动的。
在使用Scroller类之前,先了解其重要的两个方法:

3.2 startScroll使用介绍

startScroll(),开始一个动画控制,由(startX , startY)duration时间内前进(dx,dy)个单位,即到达偏移坐标为(startX+dx , startY+dy)处。

	public void startScroll(int startX, int startY, int dx, int dy) {
startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
}

3.3 computeScrollOffset使用介绍

computeScrollOffset(),滑动过程中,根据当前已经消逝的时间计算当前偏移的坐标点,保存在mCurrXmCurrY值中。

	public boolean computeScrollOffset() {
if (mFinished) {
return false;
}
int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
if (timePassed < mDuration) {
...
}
else {
mCurrX = mFinalX;
mCurrY = mFinalY;
mFinished = true;
}
return true;
}

3.4 Scroller使用总结

Scroller类中最重要的两个方法就是startScroll()computeScrollOffset(),但是Scroller类只是一个滑动计算辅助类,它的 startScroll()computeScrollOffset()方法中也只是对一些轨迹参数进行设置和计算,真正需要进行滑动还是得通过ViewscrollTo()scrollBy()方法 。为此,View中提供了computeScroll()方法来控制这个滑动流程。computeScroll()方法会在绘制子视图的时候进行调用。其源码如下:是一个空方法。

public void computeScroll() {}

因此Scroller类的基本使用流程可以总结如下:

    首先通过Scroller类的startScroll()开始一个滑动动画控制,里面进行了一些轨迹参数的设置和计算;
    在调用startScroll()的后面调用invalidate();引起视图的重绘操作,从而触发ViewGroup中的computeScroll()被调用;
    computeScroll()方法中,先调用Scroller类中的computeScrollOffset()方法,里面根据当前消耗时间进行轨迹坐标的计算,然后取得计算出的当前滑动的偏移坐标,调用ViewscrollTo()方法进行滑动控制,最后也需要调用invalidate();进行重绘。
    如下的一个简单代码示例:

3.5 Scroller使用示例

public class ScrollLinearLayout extends LinearLayout {

public ScrollLinearLayout(Context context) {
super(context);
init();
}

public ScrollLinearLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}

public ScrollLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

private int mLastX;
private int mLastY;
private Scroller mScroller;

private void init() {
mScroller = new Scroller(getContext());
}

@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
int x = (int) event.getX();
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
mLastY = y;
mLastX = x;
break;
case MotionEvent.ACTION_MOVE:
int dy = mLastY - y;//本次手势滑动了多大距离
int dx = mLastX - x;
mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy, 0);//第一步
invalidate();
mLastY = y;
mLastX = x;
break;
default:
}
return true;
}

@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()) {//第二步
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());//第三步
invalidate();
}
}
}

public class ScrollActivity extends AppCompatActivity {

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scroll);
}

}

<?xml version="1.0" encoding="utf-8"?>
<com.example.mtest.ScrollLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
android:gravity="center">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/colorAccent"
android:gravity="center"
android:padding="10dp"
android:text="scroll..."
android:textSize="24sp"
android:textStyle="bold" />

</com.example.mtest.ScrollLinearLayout>

Android View的scrollTo()、scrollBy() 和Scroller类总结

四、总结

Scroller类能够帮助我们实现高级的滑动功能,如手指抬起后的惯性滑动功能。使用流程为,首先通过Scroller类的startScroll()+invalidate()触发ViewcomputeScroll(),在computeScroll()中让Scroller类去计算最新的坐标信息,拿到最新的坐标偏移信息后还是要调用ViewscrollTo来实现滑动。可以看到,使用Scroller的整个流程比较简单,关键的是控制滑动的一些逻辑计算。
Android后面推出了OverScroller类,OverScroller在整体功能上和Scroller类似,使用也相同。OverScroller类可以完全代替Scroller,相比ScrollerOverScroller主要是增加了对滑动到边界的一些控制,如增加一些回弹效果等,功能更加强大。

本文参考:
Android Scroller详解
Android源码角度分析View的scrollBy()和scrollTo()的参数正负问题
ListView滑动删除实现之二——scrollTo、scrollBy详解

原创:https://www.panoramacn.com
源码网提供WordPress源码,帝国CMS源码discuz源码,微信小程序,小说源码,杰奇源码,thinkphp源码,ecshop模板源码,微擎模板源码,dede源码,织梦源码等。

专业搭建小说网站,小说程序,杰奇系列,微信小说系列,app系列小说

Android View的scrollTo()、scrollBy() 和Scroller类总结

免责声明,若由于商用引起版权纠纷,一切责任均由使用者承担。

您必须遵守我们的协议,如果您下载了该资源行为将被视为对《免责声明》全部内容的认可-> 联系客服 投诉资源
www.panoramacn.com资源全部来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。 敬请谅解! 侵权删帖/违法举报/投稿等事物联系邮箱:2640602276@qq.com
未经允许不得转载:书荒源码源码网每日更新网站源码模板! » Android View的scrollTo()、scrollBy() 和Scroller类总结
关注我们小说电影免费看
关注我们,获取更多的全网素材资源,有趣有料!
120000+人已关注
分享到:
赞(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

您的打赏就是我分享的动力!

支付宝扫一扫打赏

微信扫一扫打赏