在淘寶的商品詳情頁,我們會看到頂部的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的滑動,界面做出相應修改的類似功能,都可以按上面的方法實現。
需要的讀者可以根據自己的需求作出修改,希望對大家有幫助