android scroller简单使用

 总体的流程:scroller存储的是移动的信息,这些信息不针对任何的视图,而是针对视图树。常用的最简单的使用方法如下:

1、调用scroller的startScroll方法触发滚动,但此时只是存储了信息,并没有表明/指定哪些视图需要滚动
2、startScroll调用后将要进行视图重绘,此时可以通过重写视图树中布局视图的相应方法实现滚动的效果。
3、当在视图树中的某个布局中重写了computeScroll方法,并在此方法中调用了scrollTo()方法,则该布局下的直接子视图(包含布局视图)将会按照scrollTo的要求进行移动;
4、 在没有重写computeScroll方法并在其内部调用scrollTo方法的布局视图下的子视图相对于其布局视图的相对位置不变;
5、移动的细节是:当mScroller.computeScrollOffset()返回值为true时进行移动,

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());
		 }
		 }
	}
}

 

猜你喜欢

转载自wangying1357.iteye.com/blog/1951645