本文参考了:《上滑停靠顶端的悬浮框》的代码,在此表示感谢。【上滑停靠顶端的悬浮框】里的实现方法是使用两个控件,滑动时,监听ScrollView的滚动Y值,从而通过对两个控件的显示隐藏来实现控件的顶部悬浮。但是实际应用场景中,有可能需要悬浮的控件里面的内容是比较多的,如果通过显示隐藏的方式来实现的话,操作控件里的内容时,需要重复定义两套变量,对控件里的内容进行修改时也是要操作再次,非常麻烦。

本文的方法是通过addView和removeView来实现的。

一、首先让ScrollView实现滚动监听:


[java] 

1. package com.willen.topFloatDemo;  
2.   
3. import android.content.Context;  
4. import android.os.Handler;  
5. import android.util.AttributeSet;  
6. import android.view.MotionEvent;  
7. import android.widget.ScrollView;  
8.   
9. /*
10.  * ScrollView并没有实现滚动监听,所以我们必须自行实现对ScrollView的监听,
11.  * 我们很自然的想到在onTouchEvent()方法中实现对滚动Y轴进行监听
12.  * ScrollView的滚动Y值进行监听
13.  */  
14. public class MyScrollView extends ScrollView {  
15. private OnScrollListener onScrollListener;    
16. /** 
17.      * 主要是用在用户手指离开MyScrollView,MyScrollView还在继续滑动,我们用来保存Y的距离,然后做比较 
18.      */    
19. private int lastScrollY;  
20.       
21. public MyScrollView(Context context) {  
22. super(context, null);  
23.     }  
24. public MyScrollView(Context context, AttributeSet attrs) {  
25. super(context, attrs, 0);  
26.     }  
27. public MyScrollView(Context context, AttributeSet attrs, int defStyle) {  
28. super(context, attrs, defStyle);  
29.     }  
30. /** 
31.      * 设置滚动接口 
32.      * @param onScrollListener 
33.      */  
34. public void setOnScrollListener(OnScrollListener onScrollListener){  
35. this.onScrollListener = onScrollListener;  
36.     }  
37. /** 
38.      * 用于用户手指离开MyScrollView的时候获取MyScrollView滚动的Y距离,然后回调给onScroll方法中 
39.      */    
40. private Handler handler = new Handler() {    
41.     
42. public void handleMessage(android.os.Message msg) {    
43. int scrollY = MyScrollView.this.getScrollY();    
44.                 
45. //此时的距离和记录下的距离不相等,在隔5毫秒给handler发送消息    
46. if(lastScrollY != scrollY){    
47.                 lastScrollY = scrollY;    
48. 5);      
49.             }    
50. if(onScrollListener != null){    
51.                 onScrollListener.onScroll(scrollY);    
52.             }    
53.                 
54.         };    
55.     
56.     };   
57. /** 
58.      * 重写onTouchEvent, 当用户的手在MyScrollView上面的时候, 
59.      * 直接将MyScrollView滑动的Y方向距离回调给onScroll方法中,当用户抬起手的时候, 
60.      * MyScrollView可能还在滑动,所以当用户抬起手我们隔5毫秒给handler发送消息,在handler处理 
61.      * MyScrollView滑动的距离 
62.      */   
63. @Override  
64. public boolean onTouchEvent(MotionEvent ev) {  
65. if(onScrollListener != null){    
66. this.getScrollY());    
67.         }    
68. switch(ev.getAction()){    
69. case MotionEvent.ACTION_UP:    
70. 20);      
71. break;    
72.         }    
73. return super.onTouchEvent(ev);  
74.     }  
75.   
76. /** 
77.      * 滚动的回调接口 
78.      */    
79. public interface OnScrollListener{    
80. /** 
81.          * 回调方法, 返回MyScrollView滑动的Y方向距离 
82.          */    
83. public void onScroll(int scrollY);    
84.     }  
85. }


二、定义简单布局


[html] 

    1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    2. xmlns:tools="http://schemas.android.com/tools"  
    3. android:id="@+id/container"  
    4. android:layout_width="match_parent"  
    5. android:layout_height="match_parent"  
    6. android:orientation="vertical" >  
    7.   
    8. <com.willen.topFloatDemo.MyScrollView  
    9. android:id="@+id/myScrollView"  
    10. android:layout_width="match_parent"  
    11. android:layout_height="match_parent" >  
    12.   
    13. <LinearLayout  
    14. android:layout_width="match_parent"  
    15. android:layout_height="wrap_content"  
    16. android:orientation="vertical" >  
    17.   
    18. <RelativeLayout  
    19. android:id="@+id/rlayout"  
    20. android:layout_width="wrap_content"  
    21. android:layout_height="wrap_content"  
    22. android:layout_gravity="center_horizontal" >  
    23.   
    24. <TextView  
    25. android:id="@+id/tv"  
    26. android:layout_width="wrap_content"  
    27. android:layout_height="wrap_content"  
    28. android:gravity="center_vertical"  
    29. android:text="顶部信息\n顶部信息\n顶部信息\n顶部信息"  
    30. android:textSize="40dp" />  
    31. </RelativeLayout>  
    32.   
    33. <LinearLayout  
    34. android:id="@+id/search02"  
    35. android:layout_width="match_parent"  
    36. android:layout_height="40dip"  
    37. android:orientation="vertical" >  
    38.   
    39. <EditText  
    40. android:id="@+id/search_edit"  
    41. android:layout_width="match_parent"  
    42. android:layout_height="40dip"  
    43. android:background="@drawable/bg_edittext"  
    44. android:hint="请输入..."  
    45. android:padding="5dip"  
    46. android:singleLine="true"  
    47. android:textColorHint="#AAAAAA"  
    48. android:textSize="15dip" />  
    49. </LinearLayout>  
    50.   
    51. <TextView  
    52. android:layout_width="match_parent"  
    53. android:layout_height="wrap_content"  
    54. android:gravity="center_horizontal"  
    55. android:text="测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容"  
    56. android:textSize="40dp" />  
    57. </LinearLayout>  
    58. </com.willen.topFloatDemo.MyScrollView>  
    59.   
    60. <LinearLayout  
    61. android:id="@+id/search01"  
    62. android:layout_width="match_parent"  
    63. android:layout_height="40dip"  
    64. android:orientation="vertical" >  
    65. </LinearLayout>  
    66.   
    67. </RelativeLayout>

    三、MainActivity


    [java]

    1. package com.willen.topFloatDemo;  
    2.   
    3. import android.app.Activity;  
    4. import android.os.Bundle;  
    5. import android.widget.EditText;  
    6. import android.widget.LinearLayout;  
    7. import android.widget.RelativeLayout;  
    8.   
    9. import com.willen.topFloatDemo.MyScrollView.OnScrollListener;  
    10.   
    11. public class MainActivity extends Activity implements OnScrollListener{  
    12. private EditText search_edit;  
    13. private MyScrollView myScrollView;  
    14. private int searchLayoutTop;  
    15.       
    16.     LinearLayout search01,search02;  
    17.     RelativeLayout rlayout;  
    18.       
    19. @Override  
    20. protected void onCreate(Bundle savedInstanceState) {  
    21. super.onCreate(savedInstanceState);  
    22.         setContentView(R.layout.activity_main);  
    23. //初始化控件  
    24.         init();  
    25.     }  
    26.   
    27. private void init() {  
    28.         search_edit = (EditText)findViewById(R.id.search_edit);  
    29.         myScrollView = (MyScrollView)findViewById(R.id.myScrollView);  
    30.         search01 = (LinearLayout)findViewById(R.id.search01);  
    31.         search02 = (LinearLayout)findViewById(R.id.search02);  
    32.         rlayout = (RelativeLayout)findViewById(R.id.rlayout);  
    33. this);    
    34.           
    35.     }  
    36.   
    37. @Override  
    38. public void onWindowFocusChanged(boolean hasFocus) {  
    39. super.onWindowFocusChanged(hasFocus);      
    40. if(hasFocus){    
    41. //获取searchLayout的顶部位置  
    42.         }  
    43.     }  
    44.   
    45. //监听滚动Y值变化,通过addView和removeView来实现悬停效果  
    46. @Override  
    47. public void onScroll(int scrollY) {  
    48. if(scrollY >= searchLayoutTop){    
    49. if (search_edit.getParent()!=search01) {  
    50.                 search02.removeView(search_edit);  
    51.                 search01.addView(search_edit);  
    52.             }  
    53. else{  
    54. if (search_edit.getParent()!=search02) {  
    55.                 search01.removeView(search_edit);  
    56.                 search02.addView(search_edit);  
    57.             }  
    58.         }  
    59.     }  
    60. }


    代码中均有注释,应该不用再多解释了。

    本文源码下载:javascript:void(0)