Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android學習Scroller(四)——實現拉動後回彈的布局

Android學習Scroller(四)——實現拉動後回彈的布局

編輯:關於Android編程

MainActivity如下:

package cc.testscroller2;

import android.os.Bundle;
import android.app.Activity;
/**
 * Demo描述:
 * 實現可以拉動後回彈的布局.
 * 類似於下拉刷新的.
 *
 * 參考資料:
 * 1 http://gundumw100.iteye.com/blog/1884373
 * 2 http://blog.csdn.net/gemmem/article/details/7321910
 * 3 http://ipjmc.iteye.com/blog/1615828
 * 4 http://blog.csdn.net/c_weibin/article/details/7438323
 * 5 http://www.cnblogs.com/wanqieddy/archive/2012/05/05/2484534.html
 * 6 http://blog.csdn.net/hudashi/article/details/7353075
 *   Thank you very much
 */
public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	
}


BounceableLinearLayout如下:

package cc.testscroller2;
import android.content.Context;  
import android.util.AttributeSet;  
import android.view.GestureDetector;  
import android.view.MotionEvent;  
import android.widget.LinearLayout;  
import android.widget.Scroller;  
/**
 * 總體思路:
 * 處理View的Touch事件,即重寫onTouchEvent()方法:
 * 當手指抬起時將其回到原點,其余情況交給GestureDetector處理.
 * 
 * 在GestureDetector中重點是覆寫onScroll()方法.在該方法中得到
 * Y方向滑動的距離,從而設置 mScroller.startScroll()方法,准備滑動.
 * 隨之刷新界面invalidate()從而執行方法computeScroll().
 * 在computeScroll()方法中調用 scrollTo()方法實現真正的滑動.
 * 
 * 注意事項:
 * 1 scrollTo()方法的參數:
 *   scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
 *   並且在此之後也要調用postInvalidate()進行刷新 
 * 
 * 
 * 方法說明:
 * 1 mScroller.getFinalX(Y)()
 *   The final X(Y) offset as an absolute distance from the origin.
 *   返回滾動結束位置(得到當前X(Y)距離原始位置的值).僅針對"fling"滾動有效.
 *   也就是說該方法是針對滾動結束而言的.
 *   
 *   坐標方向:
 *   X方向的距離,正數向左,負數向右
 *   Y方向的距離,正數向上,負數向下
 *   
 * 2 mScroller.getCurrX(Y)()
 *   The new X offset as an absolute distance from the origin.
 *   The new Y offset as an absolute distance from the origin.
 *   返回當前滾動 X(Y)方向的偏移
 *   也就是說該方法是針對滾動中而言的.
 *   
 *   坐標方向:
 *   X方向的距離,正數向左,負數向右
 *   Y方向的距離,正數向上,負數向下
 *   
 * 3 invalidate()與postInvalidate()的區別
 *   invalidate()在UI線程自身中使用;postInvalidate()在非UI線程中使用.
 *   這是目前網絡資料的普遍說法,還待進一步研究.
 *   
 * 4 startScroll(int startX, int startY, int dx, int dy, int duration)
 *   第一,二個參數起始位置;第三,四個滾動的偏移量;第五個參數持續時間
 *   
 *
 */
public class BounceableLinearLayout extends LinearLayout {  
    private Scroller mScroller;  
    private GestureDetector mGestureDetector;  
      
    public BounceableLinearLayout(Context context) {  
        this(context, null);  
    }  
      
    public BounceableLinearLayout(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        setClickable(true);  
        setLongClickable(true);  
        mScroller = new Scroller(context);  
        mGestureDetector = new GestureDetector(context, new GestureListenerImpl());  
    }  
  
      
    @Override  
    public void computeScroll() {  
        if (mScroller.computeScrollOffset()) {  
        	System.out.println("computeScroll()---> "+
        	                   "mScroller.getCurrX()="+mScroller.getCurrX()+","+
        			           "mScroller.getCurrY()="+mScroller.getCurrY());
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());  
            //必須執行postInvalidate()從而調用computeScroll()
            //其實,在此調用invalidate();亦可
            postInvalidate(); 
        }  
        super.computeScroll();  
    }  
      
    @Override  
    public boolean onTouchEvent(MotionEvent event) {  
        switch (event.getAction()) {  
       case MotionEvent.ACTION_UP :  
    	   //手指抬起時回到最初位置
           prepareScroll(0, 0);  
            break;  
        default:  
        	//其余情況交給GestureDetector手勢處理
            return mGestureDetector.onTouchEvent(event);  
      }  
       return super.onTouchEvent(event);  
   }  
    
  
	class GestureListenerImpl implements GestureDetector.OnGestureListener {
		@Override
		public boolean onDown(MotionEvent e) {
			return true;
		}

		@Override
		public void onShowPress(MotionEvent e) {

		}

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			return false;
		}

		//控制拉動幅度:
		//int disY=(int)((distanceY - 0.5)/2);
		//亦可直接調用:
		//smoothScrollBy(0, (int)distanceY);
		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {
			int disY = (int) ((distanceY - 0.5) / 2);
			beginScroll(0, disY);
			return false;
		}

		public void onLongPress(MotionEvent e) {

		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {
			return false;
		}

	}  
	
	  
    //滾動到目標位置 
    protected void prepareScroll(int fx, int fy) {  
        int dx = fx - mScroller.getFinalX();  
        int dy = fy - mScroller.getFinalY();  
        beginScroll(dx, dy);  
    }  
  
    
     //設置滾動的相對偏移 
    protected void beginScroll(int dx, int dy) {  
    	System.out.println("smoothScrollBy()---> dx="+dx+",dy="+dy);
    	//第一,二個參數起始位置;第三,四個滾動的偏移量
        mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy);  
        System.out.println("smoothScrollBy()---> " +
        		           "mScroller.getFinalX()="+mScroller.getFinalX()+","+
        		           "mScroller.getFinalY()="+mScroller.getFinalY());
        
        //必須執行invalidate()從而調用computeScroll()
        invalidate();
    } 
    
      
	
	
}  

 


main.xml如下:



    

        
        
    



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved