Android群英传——Scroll
来源:互联网 发布:qq数据导入工具在哪 编辑:程序博客网 时间:2024/06/05 02:38
这篇博客的是对Android群英传,和网上的一些学习资料以及官方文档中关于Scroller的总结。主要针对scrollBy和scorllTo的区别以及Scroller类进行总结。
Scroll
使用scrollTo和scrollBy向下移动时,需要传入负数值:
scrollTo(-30,-30);scrollBy(-30,-30);
这篇文章从源码角度告诉我们为什么传入负数,向下移动
从源码角度,坐标系是不变的,由于源码中的这段代码tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY)设置一个view需要绘制的脏矩形,mScrollX和mScrollY都是作为参数的减数(负负得正,负正得负),当scrollTo()的传入参数为负的时候,view就向坐标轴正方向滚动;当为正的时候,view就向坐标轴负方向滚动。
我们也可以简单理解为坐标系的方向这样的:
scrollBy和ScrollTo的区别
scrollBy是相对于目前的位置移动指定距离
scrollTo是移动到指定的位置
效果如图,点击scrollTo后会跳到指定的位置,继续点击是没有效果的。然而点击scrollBy会相对于当前位置,每次点击都移动一段指定距离。当scrollBy移动一段距离后,再点击scrollTo,它会跳会原来指定的位置。
这里使用的是 Linearlayout来调用scrollTo和scrollBy。如果直接使用view调用时,移动的只是view里面的内容,也就是Button中的text。我们也可以使用((View)getParent)来获得父类。
public class MainActivity extends AppCompatActivity { Button btn_scrollBy; Button btn_scrollTo; LinearLayout layout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_scrollBy = (Button) findViewById(R.id.btn_scrollBy); btn_scrollTo = (Button) findViewById(R.id.btn_scrollTo); layout = (LinearLayout) findViewById(R.id.linearlayout); btn_scrollBy.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { View viewGroup = (View) v.getParent(); layout.scrollBy(-30,-30); } }); btn_scrollTo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { layout.scrollTo(-30,-30); } }); }}
我们发现使用scrollTo,和scrollBy移动时,都是瞬间移动,视觉感受不是很好,这时我们就可以调用Scroller类来实现平滑移动的效果。
Scroller
使用Scroller实现时需要遵循以下几个步骤:
创建Scroller的实例
重写computeScroll()方法,并在其内部完成平滑滚动的逻辑
调用startScroll()方法来初始化滚动数据并刷新界面
创建scroller实例
Scroller mScroller = new Scroller(context);
computeScroll是Scroller的核心算法,系统在绘制View的时候会在draw()方法中调用该方法。这个方法实际上是调用scrollTo方法。通过不断的瞬间移动一个很小的距离,来实现整体上的平滑移动的效果。
其中我们使用scroller.computeScrollOffsert()方法来进行判断,这个方法是判断移动是否结束,如果未结束会返回true,结束返回false。
mScroller.getCurrX();//在scroll中当前x的偏移量mScroller.getCurrY();//在scroll中当前y的偏移量
@Override public void computeScroll() { super.computeScroll(); //判断Scroller是否执行完毕 if (mScroller.computeScrollOffset()) { //根据当前x,y的偏移量移动 ((View) getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); // invalidate()->draw()->computeScroll() invalidate(); } }
简单介绍下startScroll()方法,一个是有duration,另一个是无duration
void startScroll (int startX, //开始时x的位置 int startY, //开始时y的位置 int dx, //x的偏移量 int dy, //y的偏移量 int duration)//滚动的持续时间void startScroll (int startX, int startY, int dx, int dy)
效果图,这个是没有设置duration的效果图
设置duration为2000ms的效果图,可以看到滑动更加的平滑
这个简单的例子,是将startScroll设置在MotionEvent.ACTION_UP时,让view回到原来的位置上。
关键代码:
使用startScroll时要调用invalidate()方法进行刷新
//当手指离开时 case MotionEvent.ACTION_UP: View viewGroup = (View) getParent(); mScroller.startScroll(viewGroup.getScrollX(), viewGroup.getScrollY(), -viewGroup.getScrollX(),//偏移量,回到初始位置 -viewGroup.getScrollY()); invalidate();//刷新 break;
完整代码:
public class DragView extends View { private int lastX; private int lastY; private Scroller mScroller; public DragView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); mScroller = new Scroller(context); } @Override public void computeScroll() { super.computeScroll(); //判断Scroller是否执行完毕 if (mScroller.computeScrollOffset()) { ((View) getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); // invalidate()->draw()->computeScroll() invalidate(); } } @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = (int) event.getX();//记录下按下时的坐标 lastY = (int) event.getY(); break; case MotionEvent.ACTION_MOVE: int offsetX = x - lastX;//计算当前坐标和按下时坐标的差值,即偏移量 int offsetY = y - lastY; //实现跟着手指移动 ((View) getParent()).scrollBy(-offsetX, -offsetY); break; //当手指离开时 case MotionEvent.ACTION_UP: View viewGroup = (View) getParent(); mScroller.startScroll(viewGroup.getScrollX(), viewGroup.getScrollY(), -viewGroup.getScrollX(),//偏移量,回到初始位置 -viewGroup.getScrollY()); invalidate();//刷新 break; } return true; }}
布局代码:
<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:id="@+id/linearlayout" tools:context=".MainActivity"> <example.com.myapplication2.DragView android:background="@color/colorAccent" android:layout_width="100dp" android:layout_height="100dp" /></LinearLayout>
MainActivity:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}
- Android群英传——Scroll
- Android Scroll——Androi群英传
- Android群英传学习笔记——Android Scroll 分析
- Android群英传笔记——第五章:Android Scroll分析
- Android群英传笔记——第五章:Android Scroll分析
- Android群英传学习——第五章、Android Scroll分析
- android 群英传笔记----Android scroll
- Scroll 滚动 《Android 群英传》笔记
- Android群英传知识点回顾——第五章:Android Scroll分析
- Android群英传之Android Scroll分析
- 《Android群英传》读书笔记5.Android Scroll分析
- Android群英传第五章Scroll分析读书笔记
- Andriod群英传-Android Scroll 分析学习笔记
- Scroll滑动分析-《Android群英传》第五章
- Android群英传——目录
- 《Android群英传》——读书笔记
- ListView2——Android群英传
- 绘图——Android群英传
- [Cordova/Phonegap] 利用 MagicaVoxel 、Wikitude 和 PhoneGap 在手机上实现AR增强现实
- 【C#】操作SQLite数据库出现database is locked解决办法
- windows下redis安装测试
- Redis持久化机制
- 随想心得
- Android群英传——Scroll
- 当好务实的项目经理(实用项目管理经验)
- 内部排序八大算法原理及JAVA实现
- DDMS中File Explorer无法查看data/data文件解决办法
- Android Studio中Gradle使用详解
- 使用CocoaPods 安装第三方库
- chrome问题记录
- ~CRC校验~
- Android中获取应用程序(包)的信息之PackageManager的使用