6、从startScroll中描述的当前参照坐标向x、y方向位移,一边移动一边刷新,在描述的滚动的周期时间结束后移动到指定位置并结束移动。
实例效果图:
起始状态
当点击如图的第二块灰色区域时,效果如下:
如图,点击的是一个LinearLayout布局组件,根布局为垂直方向的ContentLinearLayout组件lay0,其子视图为三个LinearLayout,分别为lay1,lay2,lay3;三个按钮分别在为这三个线性布局的子视图,如图。文本组件"hello scroller"属于根视图的直接子视图,视图树如下:
当点击了上图区域时,视图树刷新,lay0的子视图lay1,lay2,lay3,t按照ContentLayout中重写的computeScroll()方法滚动,由于lay1,lay2也重写了computeScroll方法,在它们布局内的btn1,btn2由原来在父视图的左上角部分向右下方滚动了一段距离。同理,由于lay3使用的是系统预设的LinearLayout,未进行滚动的自定义,所有btn3相对于lay3的位置未发生改变。
代码如下:
package com.cn.scrollerdemo; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.LinearLayout; import android.widget.Scroller; import android.widget.TextView; public class TestScrollerActivity extends Activity { private static final String TAG = "TestScrollerActivity"; LinearLayout lay1, lay2,lay3, lay0; private Scroller mScroller; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mScroller = new Scroller(this); lay1 = new MyLinearLayout(this); lay2 = new MyLinearLayout(this); lay3=new LinearLayout(this); lay1.setBackgroundColor(this.getResources().getColor( android.R.color.darker_gray)); lay2.setBackgroundColor(this.getResources().getColor( android.R.color.white)); lay3.setBackgroundColor(this.getResources().getColor( android.R.color.darker_gray)); 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( 200, LinearLayout.LayoutParams.WRAP_CONTENT); p1.weight = 1; lay0.addView(lay1, p1); LinearLayout.LayoutParams p2 = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); p2.weight = 1; lay0.addView(lay2, p2); LinearLayout.LayoutParams p3 = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); p3.weight = 1; lay0.addView(lay3, p2); MyButton btn1 = new MyButton(this); MyButton btn2 = new MyButton(this); MyButton btn3=new MyButton(this); btn1.setId(1); btn2.setId(2); btn1.setText("btn in layout1"); btn2.setText("btn in layout2"); btn3.setText("btn in layout3,无scrollTo"); btn1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mScroller.startScroll(0, 0, -30, -30, 50); } }); btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mScroller.startScroll(20, 20, -50, -50, 50); } }); /** * 为什么当View做为lay0的子视图时,设置lay0的监听滚动时,此view没有滚动的效果, * 因为scrollerTo方法定义在MyLinearLayout中,也就是说只有MyLinearLayout下的视图才能滚动 */ lay1.addView(btn1); lay2.addView(btn2); lay3.addView(btn3); //在未实现了computeScroll()方法的布局中添加按钮 LinearLayout.LayoutParams p4 = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); p4.weight = 1; TextView t = new TextView(this); t.setText("hello scroller."); t.setLayoutParams(p4); lay0.addView(t, p4); lay0.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mScroller.startScroll(0, 0, -30, -30, 50); Log.e(TAG, "lay0--------------"); // 刷新界面 lay0.invalidate(); } }); } class MyButton extends Button { public MyButton(Context ctx) { super(ctx); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.d("MyButton", this.toString() + " onDraw------"); } } class MyLinearLayout extends LinearLayout { public MyLinearLayout(Context ctx) { super(ctx); } String flag; @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-----------:" + mScroller.computeScrollOffset() + ":" + mScroller.getCurrX()); if (mScroller.computeScrollOffset())// 如果mScroller没有调用startScroll,这里将会返回false。 { // 因为调用computeScroll函数的是MyLinearLayout实例, // 所以调用scrollTo移动的将是该实例的孩子,也就是MyButton实例............ // scrollTo(mScroller.getCurrX(), 0); scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); // scrollTo控制实际的移动,mScroller可看做一个存储滚动信息的一个结构体 Log.d(TAG, "getCurrX = " + mScroller.getCurrX()); } } } class ContentLinearLayout extends LinearLayout { public ContentLinearLayout(Context ctx) { super(ctx); } @Override protected void dispatchDraw(Canvas canvas) { Log.d("ContentLinearLayout", "contentview dispatchDraw"); super.dispatchDraw(canvas); } // 当重写后其所有直接子视图都能够移动,也就是说scrollTo只能控制其直接的子视图,不能控制它子视图是ViewGroup,这个ViewGroup的子视图 public void computeScroll(){ if (mScroller.computeScrollOffset())// // 如果mScroller没有调用startScroll,这里将会返回false。 { scrollTo(mScroller.getCurrX(),mScroller.getCurrY()); //scrollTo控制实际的移动,mScroller可看做一个存储滚动信息的一个结构体 Log.d(TAG, "getCurrX = " + mScroller.getCurrX()); } } } }