用于滚动视图实现定头效果
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();
}