android Scroller簡單用法記錄
阿新 • • 發佈:2019-02-06
總體的流程:scroller儲存的是移動的資訊,這些資訊不針對任何的檢視,或者可以說是針對檢視樹。常用的最簡單的使用方法如下:
1、呼叫scroller的startScroll方法觸發滾動,但此時只是儲存了資訊,並沒有表明/指定哪些檢視需要滾動
2、startScroll呼叫後將要進行檢視重繪,此時可以通過重寫檢視樹中佈局檢視的相應方法實現滾動的效果。
3、當在檢視樹中的某個佈局中重寫了computeScroll方法,並在此方法中呼叫了scrollTo()方法,則該佈局下的直接子檢視(包含佈局檢視)將會按照scrollTo的要求進行移動;
4、 在沒有重寫computeScroll方法並在其內部呼叫scrollTo方法的佈局檢視下的子檢視相對於其佈局檢視的相對位置不變;
5、移動的細節是:當mScroller.computeScrollOffset()返回值為true時進行移動,
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()); } } } }