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

用于支持定头的工具类

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

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();
        }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,478评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,825评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,482评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,726评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,633评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,018评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,168评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,320评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,264评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,288评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,995评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,587评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,909评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,284评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,862评论 2 339

推荐阅读更多精彩内容