用于滚动视图实现定头效果

2018-06-05  本文已影响0人  國軍哥哥

用于支持定头的工具类

首先定义一个具体的接口,用于规范具体的操作,以方便扩展,具体代码如下:

package com.sun.view.vieweffect;

/**
 * 渐变效果
 * Created by sun on 2016/4/27.
 */
public interface GradientEffect {
    /**
     * 初始化数据
     */
    void onInitData();

    /**
     * 获取渐变吸收
     *
     * @return
     */
    void generateRatio();

    /**
     * 渐变回调监听
     *
     * @param l
     */
    void setOnGradientEffectListener(OnGradientEffectListener l);

    interface OnGradientEffectListener {
        /**
         * 渐变回调
         *
         * @param ratio 渐变系数(最小为0最大为1)
         */
        void onGrade(float ratio);
    }

    void stop();
}

这是具体的功能实现,需要扩展的同学可以参考扩展,具体代码如下:

package com.sun.view.vieweffect;

import android.os.Build;
import android.view.View;
import android.view.ViewTreeObserver;

import com.sun.util.LogUtil;

/**
 * 可用于实现Title渐变效果或者吸顶效果
 * <p/>
 * 初始时,滑动视图必须在悬浮视图的下方
 * Created by sun on 2016/4/27.
 */
public class GradientEffectImpl implements GradientEffect {
    private final String TAG = getClass().getSimpleName();
    /*渐变效果监听器*/
    private OnGradientEffectListener mOnGradientEffectListener;
    /*悬浮视图*/
    private View hoverView;
    /*滑动视图*/
    private View sliderView;
    /*悬浮视图初始Y坐标*/
    private int initialHoverViewY = -1;
    /*滑动视图初始Y坐标*/
    private int initialSliderViewY = -1;
    /*悬浮视图高度*/
    private int hoverViewHeight = -1;
    /*滑动视图高度*/
    private int sliderViewHeight = -1;
    /*初始差值,如果hoverView或sliderView高度改变,随之改变*/
    private float initialDValue = -1;
    /*渐变系数*/
    private float mRatio = -1;
    /*是否完成初始化*/
    private boolean isInitial = false;

    private ViewTreeObserver.OnGlobalLayoutListener mHoverListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            LogUtil.i(TAG, "----hoverView------onGlobalLayout----->--");
            int tempHoverViewHeight = hoverView.getHeight();
            if (tempHoverViewHeight == hoverViewHeight) return;
            if (tempHoverViewHeight > 0 && initialHoverViewY == -1) {
                initialHoverViewY = getScreenY(hoverView);
            }
            hoverViewHeight = tempHoverViewHeight;
            tryInitDValue();
        }
    };

    private  ViewTreeObserver.OnGlobalLayoutListener mSliderListener =   new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            LogUtil.i(TAG, "----sliderView------onGlobalLayout----->--");
            int tempSliderViewHeight = sliderView.getHeight();
            if (tempSliderViewHeight == sliderViewHeight) return;
            if (tempSliderViewHeight > 0 && initialSliderViewY == -1) {
                initialSliderViewY = getScreenY(sliderView);
            }
            sliderViewHeight = tempSliderViewHeight;
            tryInitDValue();
        }
    };

    private ViewTreeObserver.OnPreDrawListener mOnDrawListener = new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            LogUtil.i(TAG, "----sliderView------onPreDraw----->--");
            generateRatio();
            return true;
        }
    };

    /**
     * 初始时,sliderView必须在hoverView的下方
     *
     * @param hoverView  悬浮视图
     * @param sliderView 滑动视图
     */
    public GradientEffectImpl(View hoverView, View sliderView) {
        this.hoverView = hoverView;
        this.sliderView = sliderView;
    }

    /**
     * 建议在滑动视图容器的onAttachedToWindow方法中调用,用于初始化数据
     */
    @Override
    public void onInitData() {
        if (isInitial) return;
        isInitial = true;
        hoverView.getViewTreeObserver().addOnGlobalLayoutListener(mHoverListener);
        sliderView.getViewTreeObserver().addOnGlobalLayoutListener(mSliderListener);
        sliderView.getViewTreeObserver().addOnPreDrawListener(mOnDrawListener);
    }

    @Override
    public void generateRatio() {
        LogUtil.i(TAG, "-----generateRatio----->----0-----");
        float ratio;
        if (sliderView.isShown()) {
            float tempDValue = getCurrentDValue();
            if (tempDValue < 0) {//滑动视图基线在悬浮视图的上方
                ratio = 1;
                LogUtil.i(TAG, "-----generateRatio----->----1-----");
            } else if (tempDValue > initialDValue) {//滑动视图基线在悬浮视图基线的下方,并且滑动视图越过原位置,继续被向下拉动
                ratio = 0;
                LogUtil.i(TAG, "-----generateRatio----->----2-----");
            } else {//滑动视图基线在悬浮视图基线的下方,并且被向上拉动
                float offset = initialDValue - tempDValue;
                ratio = offset / initialDValue;
                LogUtil.i(TAG, "-----generateRatio----->----3-----");
            }
        } else {//滑动视图被移除出当前window
            ratio = 1;
            LogUtil.i(TAG, "-----generateRatio----->----4-----");
        }

        if (mOnGradientEffectListener != null && mRatio != ratio) {
            mRatio = ratio;
            mOnGradientEffectListener.onGrade(ratio);
        }
    }

    @Override
    public void setOnGradientEffectListener(OnGradientEffectListener l) {
        mOnGradientEffectListener = l;
    }

    /**
     * 尝试去计算初始差值
     */
    private void tryInitDValue() {
        if (hoverViewHeight == -1 || sliderViewHeight == -1 || initialHoverViewY == -1 || initialSliderViewY == -1)
            return;
        initialDValue = getDValue(hoverViewHeight, initialHoverViewY, sliderViewHeight, initialSliderViewY);
    }

    /**
     * 获取当前差值
     *
     * @return 当前差值
     */
    private int getCurrentDValue() {
        int tempHoverViewY = getScreenY(hoverView);
        int tempSliderViewY = getScreenY(sliderView);
        return getDValue(hoverViewHeight, tempHoverViewY, sliderViewHeight, tempSliderViewY);
    }

    /**
     * 计算差值
     *
     * @param hoverViewHeight  悬浮视图的高度
     * @param hoverViewY       悬浮视图的y坐标
     * @param sliderViewHeight 滑动视图的高度
     * @param sliderViewY      滑动视图的y坐标
     * @return 差值
     */
    private int getDValue(int hoverViewHeight, int hoverViewY, int sliderViewHeight, int sliderViewY) {
        int sliderViewBottom = sliderViewHeight + sliderViewY;//滑动视图当前基线
        int hoverViewBottom = hoverViewHeight + hoverViewY;//悬浮视图当前基线
        return sliderViewBottom - hoverViewBottom;
    }

    /**
     * 获取当前view在屏幕中的y坐标
     *
     * @param view 当前视图
     * @return y坐标
     */
    private int getScreenY(View view) {
        int[] location = new int[2];
        view.getLocationOnScreen(location);
        return location[1];
    }

    @Override
    public void stop(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            hoverView.getViewTreeObserver().removeOnGlobalLayoutListener(mHoverListener);
            sliderView.getViewTreeObserver().removeOnGlobalLayoutListener(mSliderListener);
            sliderView.getViewTreeObserver().removeOnPreDrawListener(mOnDrawListener);
        }else{
            hoverView.getViewTreeObserver().removeGlobalOnLayoutListener(mHoverListener);
            hoverView.getViewTreeObserver().removeGlobalOnLayoutListener(mSliderListener);
            mOnDrawListener = null;
        }
    }
}


具体的使用示例如下:

private void setNavGradient() {
        mGradientEffect = new GradientEffectImpl(vNavBar, mHeaderImage);
        mGradientEffect.setOnGradientEffectListener(new GradientEffect.OnGradientEffectListener() {
            @Override
            public void onGrade(float ratio) {
                //设置导航条背景透明度
                int alpha = (int) (ratio * 255);

                vNavBar.getBackground().setAlpha(alpha);
                vTipLine.getBackground().setAlpha(alpha);
                if (ratio > 0) {//导航条完全不透明
                    mHeaderBackBtn.setImageDrawable(getResources().getDrawable(R.drawable.top_btn_icon_back_selector));
                    mHeaderShareBtn.setImageDrawable(getResources().getDrawable(R.drawable.top_btn_icon_share_selector));
                    if (mO.equals("0")) {
                        mHeaderSortBtn.setImageResource(R.drawable.btn_time_down_selector);
                    } else {
                        mHeaderSortBtn.setImageResource(R.drawable.btn_time_up_selector);
                    }
                } else {
                    mHeaderBackBtn.setImageDrawable(getResources().getDrawable(R.drawable.top_btn_icon_back_white_selector));
                    mHeaderShareBtn.setImageDrawable(getResources().getDrawable(R.drawable.top_btn_icon_share_white_selector));
                    if (mO.equals("0")) {
                        mHeaderSortBtn.setImageResource(R.drawable.btn_time_down_white);
                    } else {
                        mHeaderSortBtn.setImageResource(R.drawable.btn_time_up_white);
                    }
                }
            }
        });
        mGradientEffect.onInitData();
    }

释放资源:

        if (mGradientEffect != null) {//释放渐变效果监听
            mGradientEffect.stop();
        }
上一篇 下一篇

猜你喜欢

热点阅读