在各电商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