語言表達能力有限,我們先來看下效果:
好了,如果你明白了我說的效果,那就繼續往下看吧!
思路是這樣的:
首先,我們要自定義一個HoverScrollView,繼承ScrollView,通過接口把onScrollChanged(int l, int t, int oldl, int oldt)方法裏scrollview移動的Top值暴露出來,然後在Activity根據scrollview的Top值以及需要懸浮的佈局mHoverLayoutTop距離上邊緣的size,通過兩者的比較,當Top的值大於等於size時把mHoverLayoutTop設置VISIBLE以及INVISIBLE。
這裏有必要先介紹下Left,Top,Right,Bottom這幾個值的含義:
下面是暴露出scrollview滑動時的Top值的代碼,這裏很明顯我們開個接口
開接口一般我們記住以下幾個步驟:
創建接口,聲明接口帶參數的抽象方法,聲明一個接口類型的引用來指向一個實現給接口的對象,對這個引用賦值,最後別忘記給接口傳遞的參數賦值(去調用接口的方法)。
下面是自定義HoverScrollView的代碼:
public class HoverScrollView extends ScrollView {
private OnScrollListener onScrollListener;
public interface OnScrollListener{
public void onScroll(int scrollY);
};
public HoverScrollView(Context context) {
super(context, null, 0);
// TODO Auto-generated constructor stub
}
public HoverScrollView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
// TODO Auto-generated constructor stub
}
public HoverScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public void setOnScrollListener(OnScrollListener onScrollListener){
this.onScrollListener = onScrollListener;
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
// TODO Auto-generated method stub
super.onScrollChanged(l, t, oldl, oldt);
if(onScrollListener!=null){
onScrollListener.onScroll(t);
}
}
}
然後我們來看下佈局的代碼,這裏使用FrameLayout,可以看到懸停的佈局位於FrameLayout的上層,這裏我們把懸停的佈局先gone掉,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff" >
<com.mw.yejg.andtest.view.HoverScrollView
android:id="@+id/hsv"
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:id="@+id/iv_head"
android:layout_width="match_parent"
android:layout_height="@dimen/y100"
android:background="@drawable/ic_launcher" />
<LinearLayout
android:id="@+id/layout_hover_scroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#aaaaaa"
android:orientation="horizontal" >
<Button
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button1" />
<Button
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button2" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="@dimen/y100"
android:gravity="center"
android:text="text" />
<TextView
android:layout_width="match_parent"
android:layout_height="@dimen/y100"
android:background="#dddddd"
android:gravity="center"
android:text="text" />
<TextView
android:layout_width="match_parent"
android:layout_height="@dimen/y100"
android:gravity="center"
android:text="text" />
<TextView
android:layout_width="match_parent"
android:layout_height="@dimen/y100"
android:background="#dddddd"
android:gravity="center"
android:text="text" />
<TextView
android:layout_width="match_parent"
android:layout_height="@dimen/y100"
android:gravity="center"
android:text="text" />
<TextView
android:layout_width="match_parent"
android:layout_height="@dimen/y100"
android:background="#dddddd"
android:gravity="center"
android:text="text" />
</LinearLayout>
</com.mw.yejg.andtest.view.HoverScrollView>
<LinearLayout
android:id="@+id/layout_hover_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#aaaaaa"
android:orientation="horizontal"
android:visibility="gone" >
<Button
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button1" />
<Button
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="button2" />
</LinearLayout>
</FrameLayout>
在Activity裏面我們可以通過計算懸停佈局上邊佈局的累加高度取得size,或者如果知道準確的高度可以直接通過getResources().getDimensionPixelSize(R.dimen.xxx)取得,這裏還應該知道,控件獲取高度的方法getHeight()在onCreate()方法和onResume()方法裏調用都是爲0的,這是因爲此時佈局還沒有渲染完成,我們寫個輪詢線程來獲取渲染完成後的控件高度,代碼如下:
public class TestHoverAct extends Activity implements OnScrollListener {
private HoverScrollView mHsv;
private LinearLayout mHoverLayoutTop;
private int size;
private ImageView mIvHead;
// 開個輪詢線程,循環直到對size賦上非0的值
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (msg.what == 1) {
// 頂部高度爲0時,表示佈局未完成,繼續輪詢
if (mIvHead.getHeight() == 0) {
mHandler.sendEmptyMessageDelayed(1, 10);
return;
}
size = mIvHead.getHeight();
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_test_hover);
mHsv = (HoverScrollView) findViewById(R.id.hsv);
mIvHead = (ImageView) findViewById(R.id.iv_head);
mHoverLayoutTop = (LinearLayout) findViewById(R.id.layout_hover_top);
mHsv.setOnScrollListener(this);
// 如果知道準確的高度,可以直接取得
// size = getResources().getDimensionPixelSize(R.dimen.y100);
// 10毫秒循環判斷
mHandler.sendEmptyMessageDelayed(1, 10);
}
@Override
public void onScroll(int scrollY) {
Log.e("scroll::", "size::" + size + ", scrollY::" + scrollY);
if (scrollY >= size) {
mHoverLayoutTop.setVisibility(View.VISIBLE);
} else {
mHoverLayoutTop.setVisibility(View.INVISIBLE);
}
}
}
本博客部分思路來自夏安明的博客,向他致謝!