前:在看设计图的时候,设计师说需要一个弹出层在指定位置,渐出,背景带阴影层,第一个想到的是 popWindow ,但是pop 并没有阴影层,直接是一层覆盖在上面。仔细一想带阴影也是可以,但是渐渐出现的动画如何和背景阴影协同展示,是个问题。所以查阅了一些资料,以及填了一些坑。完成了最终的效果。效果如下:
在不同android系统上面展示的效果是不一样的,这是适配的一个坑。
在7.0 以下的手机,pop 设置 MATCH_PARENT,是完全没有问题的,在7.0以上的手机 会发现 pop 直接顶到父布局的顶端了。完全没有在指定位置的下面。
//这个属性 在 6.0和7.0以上处理不同,6.0 就直接在下面,不管pop 大小,7.0pop太大,就会找父类view
下面是我的处理方法:动态的设置pop 的高宽
private void initView(QuoInfoObject.QuoInfo quoInfo) {
setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
if (Build.VERSION.SDK_INT < 24) {
setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
} else {
float density = mContext.getResources().getDisplayMetrics().density;
Log.d("QuotationDescWindow","density="+density);
int height;
if(density == 2.5){
height = ScreenUtils.getScreenHeight(mContext) - ScreenUtils.dip2px(mContext, 110) + topScrollDis;
}else {
height = ScreenUtils.getScreenHeight(mContext) - ScreenUtils.dip2px(mContext, 143) + topScrollDis;
}
setHeight(height);
}
.....
..
setOutsideTouchable(true);
setFocusable(true);
}
height = ScreenUtils.getScreenHeight(mContext) - ScreenUtils.dip2px(mContext, 110) + topScrollDis;ScreenUtils.dip2px(mContext, 110) 固定位置距离顶部的距离
topScrollDis 这个是顶部滚动的距离,动态控制的。
这里处理采用属性动画,补间动画不能满足要求。
//显示
public void showPopupWindow(View parent, int xOff, int yOff) {
if (!this.isShowing()) {
showAsDropDown(parent, xOff, yOff);
//执行进入动画,这里主要是执行列表下滑,背景变半透明
AnimUtils.createAnimation(true, contentView, rootView, null);
} else {
dismissPopup();
}
}
AnimUtils.createAnimation:就是简单的一个属性动画的展示,相关代码如下
/**
* @param isIn 动画类型,进入或消失
* @param rootView 根布局,主要用来设置半透明背景
* @param target 要移动的view
* @param animInterface 动画执行完毕后的回调
*/
public static void createAnimation(final boolean isIn, final View rootView, final View target,
final AnimInterface animInterface) {
final int toYDelta = ScreenUtils.getViewHeight(target);//测量布局高度
ValueAnimator valueAnimator = ValueAnimator.ofFloat(isIn ? -toYDelta : 0, isIn ? 0 : -toYDelta);
valueAnimator.setDuration(isIn ? ANIMATION_IN_TIME : ANIMATION_OUT_TIME);
valueAnimator.setRepeatCount(0);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentValue = (Float) animation.getAnimatedValue();
target.setY(currentValue);
rootView.setAlpha(1 - Math.abs(currentValue) / animation.getDuration());
}
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
if (animInterface != null) {
animInterface.animStar();
}
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
if (animInterface != null) {
animInterface.animEnd();
}
}
});
valueAnimator.start();
}
这个cover 是填充布局下面的留白和方便点击空白处 关闭
4-1:
public class QuotationDescWindow extends PopupWindow {
private Context mContext;
private View contentView;//弹出框的根布局,可以监听其点击事件,达到点击阴影消失弹框的效果
private LinearLayout rootView;
private TextView contentTv;
private CircularStatisticsView ringView;
private TextView upConts,downConts,fairConts,enterMonety,enterFont;
private TextView weekRadio,monthRadio,seasonRadio,yearRadio;
private int topScrollDis;
private boolean isAnimalRunning = false;
public QuotationDescWindow(Context context, int scrollDis, QuoInfoObject.QuoInfo quoInfo) {
super(context);
mContext = context;
topScrollDis = scrollDis;
initView(quoInfo);
}
private void initView(QuoInfoObject.QuoInfo quoInfo) {
setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
if (Build.VERSION.SDK_INT < 24) {
setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
} else {
//45+78 + 20 = 143
float density = mContext.getResources().getDisplayMetrics().density;
Log.d("QuotationDescWindow","density="+density);
int height;
if(density == 2.5){
height = ScreenUtils.getScreenHeight(mContext) - ScreenUtils.dip2px(mContext, 110) + topScrollDis;
}else {
height = ScreenUtils.getScreenHeight(mContext) - ScreenUtils.dip2px(mContext, 143) + topScrollDis;
}
Log.d("QuotationDescWindow","height="+height);
setHeight(height);
}
//这里的xml 就是第三点贴出来的
contentView = LayoutInflater.from(mContext).inflate(R.layout.pop_quo_desc_layout, null);
setContentView(contentView);//设置布局
setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
//相关控件的获取和数据的处理就不贴了
....
....
setOutsideTouchable(true);
setFocusable(true);
contentView.findViewById(R.id.pop_desc_cover).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
}
});
}
//显示
public void showPopupWindow(View parent, int xOff, int yOff) {
if (!this.isShowing()) {
//这个属性 在 6.0和7.0以上处理不同,6.0 就直接在下面,不管pop 大小,7.0pop太大,就会找父类view
//https://blog.csdn.net/xx23x/article/details/53557731
// int[] positon = new int[2];
// parent.getLocationOnScreen(positon);
// showAsDropDown(parent,positon[0] + xOff,positon[1] +yOff);
showAsDropDown(parent, xOff, yOff);
//执行进入动画,这里主要是执行列表下滑,背景变半透明
AnimUtils.createAnimation(true, contentView, rootView, null);
} else {
dismissPopup();
}
}
//消失
public void dismissPopup() {
super.dismiss();// 调用super.dismiss(),如果直接dismiss()会一直会调用下面的dismiss()
}
@Override
public void dismiss() {
if (isAnimalRunning) { //防止重复点击,动画多次执行
return;
}
//执行退出动画,列表上滑退出,同时背景变透明
AnimUtils.createAnimation(false, contentView, rootView, new AnimUtils.AnimInterface() {
@Override
public void animStar() {
isAnimalRunning = true;
}
@Override
public void animEnd() {
isAnimalRunning = false;
dismissPopup();//动画执行完毕后消失
}
});
}
}
4-2:
相关调用
private void showPopView() {
if (quoInfoData == null) {
return;
}
QuotationDescWindow quotationDescWindow = new QuotationDescWindow(QuotationDetailActivity.this, topScrollDis, quoInfoData);
quotationDescWindow.showPopupWindow(subTopView, 0, 0);
quotationDescWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
setDescEnterIcon(false);
}
});
}