购买栏悬浮效果实现

在各电商APP的商品详情页中,我们经常会看到这种效果。

默认情况下,购买栏显示在商品图片下方:


当页面向上滑动,购买栏滑动到屏幕顶部时,会一直固定在屏幕顶部:

今天我们来实现这种显示效果。

实现思路:
首先,页面能够滚动,需要ScrollView的支持。在ScrollView内部,包含一个垂直方向的LinearLayout,商品图片和购买栏呈垂直线性排列,这些都比较容易想到。难点在于如何把页面中的购买栏固定住,而页面还可以继续滚动。那么我们就变换一下思维,如果从一开始,在屏幕的顶部就一直存在着一个一模一样的购买栏,只不过是隐藏状态,当商品图片下边的购买栏滑动到屏幕顶部时,我们将屏幕顶部已有的购买栏显示出来就好啦。

思路图:


基于上述思路,我们就有了下面的布局代码:

好了,下面开始用代码实现逻辑了。
我们首先要获取到商品图片区域的高度,然后监听ScrollView在垂直方向的滚动距离,当滚动距离大于商品图片的高度时,就将屏幕顶部的购买栏显示出来,否则将其隐藏。

监听滚动,很容易会想到setOnScrollChangeListener(OnScrollChangeListener l)方法。不过,很遗憾的是,ScrollView只有在api level 23以上,才提供了该方法。那么,在低版本中,我们如何监听ScrollView的滚动呢?

我们发现,在ScrollView中,有如下方法。

/**
  * This is called in response to an internal scroll in this view (i.e., the
  * view scrolled its own contents). This is typically as a result of
  * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
  * called.
  *
  * @param l Current horizontal scroll origin.
  * @param t Current vertical scroll origin.
  * @param oldl Previous horizontal scroll origin.
  * @param oldt Previous vertical scroll origin.
  */
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
  // ...
}
而且,该方法是protected的,那么我们可以自定义一个View,继承自ScrollView,然后重写onScrollChanged()方法,将参数t(垂直方向的滚动距离)回调出去为我们所用。

实现如下。
package net.csdn.blog.ruancoder;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;

public class ScrollChangedView extends ScrollView {
    private OnScrollChangedListener mListener;

    public void setOnScrollChangedListener(OnScrollChangedListener listener) {
        this.mListener = listener;
    }

    public ScrollChangedView(Context context) {
        super(context);
    }

    public ScrollChangedView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ScrollChangedView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mListener != null) {
            // 将ScrollView垂直方向滚动的距离回调出去
            mListener.onScrollChanged(t);
        }
    }

    public interface OnScrollChangedListener {
        void onScrollChanged(int scrollY);
    }
}

然后在Activity中,监听ScrollChangedView.OnScrollChangedListener,根据scrollY的大小来控制顶部购买栏的显示或隐藏,就可以实现上述效果。
package net.csdn.blog.ruancoder;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewTreeObserver;

public class MainActivity extends Activity implements ScrollChangedView.OnScrollChangedListener {
    private View mFixedBuyBar;// 顶部固定的购买栏
    private int mTopViewHeight;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final View topView = findViewById(R.id.top_view);
        mFixedBuyBar = findViewById(R.id.fixed_buy_button_bar);
        mFixedBuyBar.setVisibility(View.GONE);

        final ScrollChangedView scrollView = (ScrollChangedView) findViewById(R.id.scrollview);
        scrollView.setOnScrollChangedListener(this);

        scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                // 获取顶部视图的高度
                mTopViewHeight = topView.getHeight();
                scrollView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        });
    }

    @Override
    public void onScrollChanged(int scrollY) {
        if (scrollY > mTopViewHeight) {// 滚动超出顶部视图的高度,此时显示顶部固定的购买栏
            mFixedBuyBar.setVisibility(View.VISIBLE);
        } else {// 否则,隐藏顶部固定的购买栏
            mFixedBuyBar.setVisibility(View.GONE);
        }
    }
}

最后附上完整工程代码下载链接:
http://download.csdn.net/detail/ruancoder/9594054

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值