1. 程式人生 > >android頁面滑動時,頂部title背景漸變的實現

android頁面滑動時,頂部title背景漸變的實現

在淘寶的商品詳情頁,我們會看到頂部的title背景顏色隨著scrollView的上下滑動而漸變,這樣的功能在我們應用中會經常用到,今天就來說一下我實現下這種功能方法,當然方法可能比較笨,看到部落格的大牛,希望能得到你們的指點。

先晒幾張效果圖:

                            

首先先解釋一下基本原理:我們的思路是重寫ScrollView,實現ScrollView的滑動監聽,在ScrollView滑動的過程中,對頂部Title做出相應的處理:

看一下title的佈局檔案:title.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/green"
    android:orientation="horizontal" >

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:background="@drawable/background_circle"
        android:padding="10dp"
        android:src="@drawable/icon_back" />

    <View
        android:layout_width="0dp"
        android:layout_height="1dp"
        android:layout_weight="1" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:background="@drawable/background_circle"
        android:padding="10dp"
        android:src="@drawable/icon_shopping_cart" />

</LinearLayout>

title佈局檔案很簡單,顯示兩張圖片,一張是返回,一張是購物車。在這裡我選擇把title作為一個獨立的佈局檔案,因為我們開發過程中,頁面的title經常會非常像,一個title可能會在多個佈局中用到,所以把title單獨作為佈局可以方便管理,也減少很多程式碼量。

下面是頁面佈局檔案:activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.gradual_change.view.MyScrollView
        android:id="@+id/scroller"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="250dp"
                android:src="@drawable/image_001" />

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:scaleType="fitXY"
                android:src="@drawable/image_002" />

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:scaleType="fitXY"
                android:src="@drawable/image_002" />
        </LinearLayout>
    </com.example.gradual_change.view.MyScrollView>

    <include layout="@layout/title" />
    
</RelativeLayout>

activity_main佈局檔案中,MyScrollView是自定義的ScrollView,主要用於ScrollView的滑動時監聽;<include layout="@layout/title" />是開始定義的title佈局檔案引入到activity_main佈局中。為了方便,我的主佈局檔案主要用了三張比較長的圖片充當內容,讀者可以根據需求修改。


下面我們看一下自定義的ScrollView是如何實現的(MyScrollView):
MyScrollView繼承了ScrollView控制元件,主要思路是為MyScrollView綁定了一個監聽,並在onTouchEvent方法中觸發監聽,當檢測到使用者手指滑動時,根據滑動距離做出相應的處理。具體請看程式碼,裡面有詳細的解釋:

public class MyScrollView extends ScrollView {
	private OnScrollListener onScrollListener;
	/** 
     * 主要是用在使用者手指離開MyScrollView,MyScrollView還在繼續滑動,我們用來儲存Y的距離,然後做比較 
     */  
    private int lastScrollY; 

    public ViewPagerScroller(Context context, AttributeSet attrs, int defStyle) {  
        super(context, attrs, defStyle);  
    }  
  
    public ViewPagerScroller(Context context) {  
        super(context);  
    }  
  
    public ViewPagerScroller(Context context, AttributeSet attrs) {  
        super(context, attrs);  
    }    
	
	/** 
     * 設定滾動介面 
     * @param onScrollListener 
     */ 
	public void setScrolListener(OnScrollListener onScrollListener){
		this.onScrollListener = onScrollListener;
	}
	
	/** 
     * 用於使用者手指離開MyScrollView的時候獲取MyScrollView滾動的Y距離,然後回撥給onScroll方法中 
     */  
    private Handler handler = new Handler() {  
    	 public void handleMessage(android.os.Message msg) {  
             int scrollY = ViewPagerScroller.this.getScrollY(); 
             if(onScrollListener != null){  
                 onScrollListener.onScroll(scrollY);  
             }
           //此時的距離和記錄下的距離不相等,在隔5毫秒給handler傳送訊息  
             if(lastScrollY != scrollY){  
                 lastScrollY = scrollY;  
                 handler.sendMessageDelayed(handler.obtainMessage(), 5);    
             }  
               
    	 }
    };
	
	/** 
     * 重寫onTouchEvent, 當用戶的手在MyScrollView上面的時候, 
     * 直接將MyScrollView滑動的Y方向距離回撥給onScroll方法中,當用戶擡起手的時候, 
     * MyScrollView可能還在滑動,所以當用戶擡起手我們隔20毫秒給handler傳送訊息,在handler處理 
     * MyScrollView滑動的距離 
     */  
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		if(onScrollListener != null){
			onScrollListener.onScroll(lastScrollY = this.getScrollY());
		}
		if(ev.getAction() == MotionEvent.ACTION_UP){
			handler.sendMessageDelayed(handler.obtainMessage(), 20); 
		}
		return super.onTouchEvent(ev);
	}

	public interface OnScrollListener{
		/** 
         * 回撥方法, 返回MyScrollView滑動的Y方向距離 
         * @param scrollY 
         *              、 
         */  
        public void onScroll(int scrollY);  
	}

}  
做好了上面的工作,我們就可以在Activity中具體應用了。如下,請看MainActivity,改類實現了自定義的MyScrollView中滑動監聽介面OnScrollListener,主要的title改變在onScroll方法中,我們通過監聽MyScrollView滑動,根據滑動y方向的距離來對title做出想用的漸變效果。

MainActivity程式碼如下:

public class MainActivity extends Activity implements OnScrollListener{

	private LinearLayout top_bg;
	private ImageView back;
	private ImageView shopping_cart;
	private MyScrollView scroller;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

	private void initView() {
		top_bg = (LinearLayout) findViewById(R.id.top_bg);
		back = (ImageView) findViewById(R.id.back);
		shopping_cart = (ImageView) findViewById(R.id.shopping_cart);
		scroller = (ViewPagerScroller) findViewById(R.id.scroller);
		top_bg.getBackground().setAlpha(0);
		scroller.setScrolListener(this);
	}

	@Override
	public void onScroll(int scrollY) {
		if(scrollY < 100){
			top_bg.getBackground().setAlpha(0);
			back.getBackground().setAlpha(255);
			shopping_cart.getBackground().setAlpha(255);
		}else if(scrollY >= 100 && scrollY < 860){
			top_bg.getBackground().setAlpha((scrollY-100)/3);
			back.getBackground().setAlpha(255 - (scrollY-100)/3);
			shopping_cart.getBackground().setAlpha(255 - (scrollY-100)/3);
		}else{
			top_bg.getBackground().setAlpha(255);
			back.getBackground().setAlpha(0);
			shopping_cart.getBackground().setAlpha(0);
		}
	}
}

其實許多類似的功能都可以通過上面的方法實現,比如:

某一控制元件逐漸向上滑動,到最頂端停止向上滑動功能的實現;

ScrollView向上滑動頂部隱藏,向下滑動頂部顯示功能的實現;

總的來數,如果需要實現隨著ScrollView的滑動,介面做出相應修改的類似功能,都可以按上面的方法實現。

需要的讀者可以根據自己的需求作出修改,希望對大家有幫助