《滑动到顶部悬浮功能条》源码学习整理笔记

来源:互联网 发布:数据库中insert的用法 编辑:程序博客网 时间:2024/06/05 23:41

项目源码地址:https://git.oschina.net/steve/HoveringScroll

实现原理解析:

我这里使用了不同的颜色,将后面会讲解到的几个布局标注了出来。
这里有几个对象A布局、B布局、C布局需要事先说明一下:
A布局示意图:
这里写图片描述
B布局示意图:
这里写图片描述
C布局示意图:
这里写图片描述
1.Activity初始化时的状态,此时C布局在B布局上:
这里写图片描述
2.当向上滑动屏幕,布局B也会随着滚动布局向上滚动:
这里写图片描述
3.当向上滑动的距离超过了开始时顶部布局的高度H时,本来在B上的子布局C就会被移除,然后加到A布局上:
这里写图片描述
代码实现部分:

 // 自定义ScrollView滑动监听,获取实时的Y轴滑动距离    @Override    public void onScroll(int scrollY)    {        Log.d("guxuewu", "scrollY=>" + scrollY);        // 如果滑动的距离大于等于了顶部布局的高度H        if (scrollY >= searchLayoutTop)        {            // 并且固定布局C的父布局不是A布局            if (hoveringLayout.getParent() != search01)            {                // B布局移除布局C                search02.removeView(hoveringLayout);                // A加入布局C                search01.addView(hoveringLayout);            }        }        // 如果滑动距离小于了顶部布局的高度        else        {            // 并且固定布局C的父布局不是B布局            if (hoveringLayout.getParent() != search02)            {                // A布局移除固定布局C                search01.removeView(hoveringLayout);                // B加入固定布局C                search02.addView(hoveringLayout);            }        }    }

代码详解

HoveringScrollSampleActivity.java

public class HoveringScrollSampleActivity extends Activity implements OnScrollListener{        // 自定义的ScrollView    private HoveringScrollview hoveringScrollview;        // 顶部布局的高度    private int searchLayoutTop;        // 顶部布局    private RelativeLayout rlayout;        // 中间固定条的布局    private LinearLayout hoveringLayout;    // 不跟随ScrollView移动的父布局    private LinearLayout search01;    // 跟随ScrollView移动的父布局    // Search01的布局高度要和search02的设置一样,这样看起来就不会有替换的感觉    private LinearLayout search02;    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_samples);        initViews();    }    private void initViews()    {        hoveringLayout = (LinearLayout)findViewById(R.id.hoveringLayout);        hoveringScrollview = (HoveringScrollview)findViewById(R.id.hoveringScrollview);        search01 = (LinearLayout)findViewById(R.id.search01);        search02 = (LinearLayout)findViewById(R.id.search02);        rlayout = (RelativeLayout)findViewById(R.id.rlayout);        hoveringScrollview.setOnScrollListener(this);    }    @Override    public void onWindowFocusChanged(boolean hasFocus)    {        super.onWindowFocusChanged(hasFocus);        // 每次启动,设置顶部布局的高度        if (hasFocus)        {            searchLayoutTop = rlayout.getBottom();        }    }  // 自定义ScrollView滑动监听,获取实时的Y轴滑动距离    @Override    public void onScroll(int scrollY)    {        Log.d("guxuewu", "scrollY=>" + scrollY);        // 如果滑动的距离大于等于了顶部布局的高度H        if (scrollY >= searchLayoutTop)        {            // 并且固定布局C的父布局不是A布局            if (hoveringLayout.getParent() != search01)            {                // B布局移除布局C                search02.removeView(hoveringLayout);                // A加入布局C                search01.addView(hoveringLayout);            }        }        // 如果滑动距离小于了顶部布局的高度        else        {            // 并且固定布局C的父布局不是B布局            if (hoveringLayout.getParent() != search02)            {                // A布局移除固定布局C                search01.removeView(hoveringLayout);                // B加入固定布局C                search02.addView(hoveringLayout);            }        }    }    // 点击事件监听    public void clickListenerMe(View view)    {        if (view.getId() == R.id.btnQiaBuy)        {            Toast.makeText(this, "抢购成功", Toast.LENGTH_SHORT).show();        }    }}

HoveringScrollview.java

public class HoveringScrollview extends ScrollView{    // 滚动监听器    private OnScrollListener onScrollListener;    /**     * 主要是用在用户手指离开本view,本view还在继续滑动,我们用来保存Y的距离,然后做比较     */    private int lastScrollY;    public HoveringScrollview(Context context, AttributeSet attrs)    {        super(context, attrs);    }    /**     * 设置滚动监听接口     */    public void setOnScrollListener(OnScrollListener onScrollListener)    {        this.onScrollListener = onScrollListener;    }    /**     * 用于用户手指离开MyScrollView的时候获取MyScrollView滚动的Y距离,然后回调给onScroll方法中     */    @SuppressLint("HandlerLeak")    private Handler handler = new Handler()    {        public void handleMessage(android.os.Message msg)        {            int scrollY = HoveringScrollview.this.getScrollY();            // 此时的距离和记录下的距离不相等,在隔6毫秒给handler发送消息            if (lastScrollY != scrollY)            {                lastScrollY = scrollY;                // 相当于开启了一个无线循环的消息机制                handler.sendMessageDelayed(handler.obtainMessage(), 20);            }            if (onScrollListener != null)            {                onScrollListener.onScroll(scrollY);            }        };    };    @SuppressLint("ClickableViewAccessibility")    public boolean onTouchEvent(MotionEvent ev)    {        // 当用户的手在HoveringScrollview上面的时候,        // 直接将HoveringScrollview滑动的Y方向距离回调给onScroll方法中,        if (onScrollListener != null)        {            onScrollListener.onScroll(lastScrollY = this.getScrollY());        }        switch (ev.getAction())        {        // 当用户抬起手的时候,HoveringScrollview可能还在滑动,        // 所以当用户抬起手我们隔6毫秒给handler发送消息,        // 在handler处理 HoveringScrollview滑动的距离            case MotionEvent.ACTION_UP:                handler.sendMessageDelayed(handler.obtainMessage(), 20);                break;        }        return super.onTouchEvent(ev);    };    /**     * 滚动的回调接口     */    public interface OnScrollListener    {        /**         * 回调方法, 返回本view滑动的Y方向距离         */        public void onScroll(int scrollY);    }}

布局文件activity_samples.xml

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:paddingBottom="@dimen/activity_vertical_margin" >    <com.steve.hovering.samples.HoveringScrollview        android:id="@+id/hoveringScrollview"        android:layout_width="match_parent"        android:layout_height="match_parent" >        <!-- 套在ScrollView中的唯一父布局 -->        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="vertical" >            <RelativeLayout                android:id="@+id/rlayout"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="center_horizontal" >                <TextView                    android:id="@+id/tv"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:gravity="center_vertical"                    android:text="TOP信息占位\nTOP信息\nTOP信息\nTOP信息占位"                    android:textColor="#d19275"                    android:textSize="30sp" />            </RelativeLayout>            <!-- 跟随ScrollView移动的父布局 -->            <LinearLayout                android:id="@+id/search02"                android:layout_width="match_parent"                android:layout_height="70dp"                android:background="@android:color/holo_green_light" >                <!-- 这个悬浮条必须是固定高度 -->                <!-- android:background="#A8A8A8" -->                <LinearLayout                    android:id="@+id/hoveringLayout"                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:gravity="center_vertical"                    android:orientation="horizontal"                    android:padding="10dp" >                    <TextView                        android:layout_width="0dp"                        android:layout_height="wrap_content"                        android:layout_weight="1"                        android:gravity="center"                        android:padding="10dp"                        android:text="¥188\r\n原价:¥399"                        android:textColor="#FF7F00" />                    <Button                        android:id="@+id/btnQiaBuy"                        android:layout_width="0dp"                        android:layout_height="wrap_content"                        android:layout_weight="1"                        android:background="#FF7F00"                        android:onClick="clickListenerMe"                        android:padding="10dp"                        android:text="立即抢购"                        android:textColor="#FFFFFF" />                </LinearLayout>            </LinearLayout>            <TextView                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:gravity="center_horizontal"                android:text="1测试内容\n2测试内容\n3测试内容\n4测试内容\n5测试内容\n6测试内容\n7测试内容\n8测试内容\n9测试内容\n10测试内容\n11测试内容\n12测试内容\n13测试内容\n14测试内容\n15测试内容\n16测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n测试内容\n27测试内容"                android:textSize="40sp" />        </LinearLayout>    </com.steve.hovering.samples.HoveringScrollview>    <!-- 固定不动的用来装固定布局的父布局 -->    <LinearLayout        android:id="@+id/search01"        android:layout_width="match_parent"        android:layout_height="70dp"        android:background="@android:color/darker_gray"        android:orientation="vertical" >    </LinearLayout></RelativeLayout>

最终效果

这里写图片描述

学习心得

学习大神的代码总能收益颇多,之前也一直想研究这个效果怎么做出来,无意在论坛看到这个源码分享,便迫不及待拿来细细研究。
研究后发现自己原来好多实现想法想复杂了,原来这么简单其实就可以实现这个效果。
所以我们还是得敢于尝试,尝试用最简单的方法去实现想要的效果。

1 0
原创粉丝点击