总结Scroller ScrollTo ScrollBy

来源:互联网 发布:现在软件行业怎么样 编辑:程序博客网 时间:2024/06/04 23:40

这两天看了两篇文章

http://blog.csdn.net/vipzjyno1/article/details/24577023讲ScrollTo和ScrollBy的用法,

http://blog.csdn.net/gemmem/article/details/7321910讲Scroller类的用法

自己总结一下,ScrollTo是移动到哪,ScrollBy是移动了多少距离,

如果传入的x和y(这里的x和y都是px,可以用dp2px转下)是一样的话,ScrollTo重复调用只能移动一次到,而ScrollBy重复调用能移动很多次,这跟这两个方法的android源码实现有关,具体看上面网址。

而ScrollTo移动的其实不是这个View移动,而是这个View里面的内容移动,甚至乎这个View可以不是ViewGroup的子类,可以是一个Button,这里是很奇怪的现象,我代码测试了下Button里面的字移动了,而这个button没移动

测试代码就是用的上面Scroller网址的代码修改了下:

public class MainActivity extends Activity {private static final String TAG = "TestScrollerActivity";LinearLayout lay1, lay2, lay0;private Scroller mScroller;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mScroller = new Scroller(this);lay1 = new MyLinearLayout(this);lay2 = new MyLinearLayout(this);lay1.setBackgroundColor(this.getResources().getColor(android.R.color.darker_gray));lay2.setBackgroundColor(this.getResources().getColor(android.R.color.white));lay0 = new ContentLinearLayout(this);lay0.setOrientation(LinearLayout.VERTICAL);LinearLayout.LayoutParams p0 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);this.setContentView(lay0, p0);LinearLayout.LayoutParams p1 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);p1.weight = 1;lay0.addView(lay1, p1);LinearLayout.LayoutParams p2 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);p2.weight = 1;lay0.addView(lay2, p2);MyButton btn1 = new MyButton(this);MyButton btn2 = new MyButton(this);btn1.setText("btn in layout1");btn2.setText("btn in layout2");btn1.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mScroller.startScroll(0, 0, -DensityUtil.dp2px(MainActivity.this, 30), -DensityUtil.dp2px(MainActivity.this, 30), 50);lay1.invalidate();}});btn2.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mScroller.startScroll(0, 0, -DensityUtil.dp2px(MainActivity.this, 100), -DensityUtil.dp2px(MainActivity.this, 100), 50);lay2.invalidate();}});lay1.addView(btn1);lay2.addView(btn2);}class MyButton extends Button {public MyButton(Context ctx) {super(ctx);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Log.d("MyButton", this.toString() + " onDraw------");}}class MyLinearLayout extends LinearLayout {public MyLinearLayout(Context ctx) {super(ctx);}@Override/** * Called by a parent to request that a child update its values for mScrollX * and mScrollY if necessary. This will typically be done if the child is * animating a scroll using a {@link android.widget.Scroller Scroller} * object. */public void computeScroll() {Log.d(TAG, this.toString() + " computeScroll-----------");if (mScroller.computeScrollOffset())// 如果mScroller没有调用startScroll,这里将会返回false。{// 因为调用computeScroll函数的是MyLinearLayout实例,// 所以调用scrollTo移动的将是该实例的孩子,也就是MyButton实例getChildAt(0).scrollTo(mScroller.getCurrX(), 0);Log.d(TAG, "getCurrX = " + mScroller.getCurrX());// 继续让系统重绘getChildAt(0).invalidate();}}}class ContentLinearLayout extends LinearLayout {public ContentLinearLayout(Context ctx) {super(ctx);}@Overrideprotected void dispatchDraw(Canvas canvas) {Log.d("ContentLinearLayout", "contentview dispatchDraw");super.dispatchDraw(canvas);}}}

首先每个按钮点击的时候都是按钮的父View手动调用invalidate,父View的invalidate会导致父View重新draw一遍,这时就会调用父类重写的computeScroll方法,这个时候我们之前设置的Scroller值就去计算有没有scroll完成computeScrollOffset(),我在判断里面使用getChildAt(0).scrollTo(mScroller.getCurrX(), 0);getChildAt(0).invalidate();(其实这里第二句可以不需要,因为scrollTo就会重画),我们这里getChildAt(0)可以肯定的是得到的是这个自定义layout里的Button对象,但是这个Button.scrollTo(mScroller.getCurrX(), 0)移动的竟然是Button里面的字,这个Button还在原地啊,是的没错,所以说ScrollTo移动的是View里面内容的位置,不管这个View是ViewGroup类的子类,还是android.weidget下面的Button,ImageView,TextView等,其实移动的都是这个View里面的内容的位置,ScrollTo并没有真正移动这个View,而只是把这个View显示在界面上的区域给扩大了,如果这个View是wrap或者固定的宽高,如果ScrollTo超过了这个View的区域,然后我给这个View提前设置了onclick事件,发现即使这个View的内容不见了(因为被ScrollTo到超出view的范围去了),但是onclick事件还能触发,也就是说这个View的左上角位置没变,但是这个View里面的内容被移动到了原先区域的外面去了。

突然想起还个没解释,就是为什么自定义的RelativeLayout里面的Button移动了,这个Button点击响应,而不是点击Button移动前的位置区域响应呢,答案很简单,还是ScrollTo改变的是view的内容位置,而并不是这个View。如何解释呢,就是这里这个自定义的RelativeLayout就是这个View,然后改变了内容就是Button,所以Button响应点击事件,而不是Button移动前的区域响应,

而像Button,ImageView这些View执行ScrollTo之后只是为了移动这个Button和ImageView,而把原本用来显示Button和ImageView的区域给扩大了,导致Button和ImageView里的内容移动,而不是这个区域移动,button的区域就是默认的android按钮背景,Imageview如果也设了背景的话也是,只是这个src图移动,背景不动,TextView也是这样。

哦了~~~这样就能解释我今天遇到的迷惑了,文字描述的不够好,见谅,代码贴太麻烦了。

0 0
原创粉丝点击