效果如图,Gif压缩得厉害,效果失真,凑合看:
我所谓的淡入淡出过渡自然是指一下几点:
1. 窗体从底部弹出以及收回过程有移动动画;
2. 伴随窗体的弹出和收起,背景也应有个由明到暗和由暗到明的动画,否则会显得生硬。
附加功能:
1. 点击窗体外,弹窗收回;
2. 弹窗打开时,点击返回键,弹窗收回。
项目地址:https://github.com/sheaye/SlidePopupWindow
部分代码:
SlidePopupWindow
:
public abstract class SlidePopupWindow extends PopupWindow {
private final Context mContext;
private FrameLayout mContainer;
// 透明遮罩,接收窗体外部的点击事件用
private FrameLayout mMaskLayout;
public SlidePopupWindow(Context context) {
super(context);
mContext = context;
setAnimationStyle(R.style.pop_anim);
// 收起时渐进恢复背景,从半透明-
setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss() {
ValueAnimator animator = ValueAnimator.ofFloat(0.5f, 1f).setDuration(500);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
setBackgroundAlpha((Float) animation.getAnimatedValue());
}
});
animator.start();
}
});
mContainer = (FrameLayout) LayoutInflater.from(context).inflate(R.layout.window_slide_popup, null);
// 添加窗体
View contentView = onCreateView(context, mContainer);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
layoutParams.gravity = Gravity.BOTTOM;
contentView.setLayoutParams(layoutParams);
mContainer.addView(contentView, layoutParams);
setContentView(mContainer);
// 宽度必须设置MATCH_PARENT,否则不显示
setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
// 高度MATCH_PARENT,contentView铺满全屏,点击内容区域外时即点击透明遮罩mMaskLayout
setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
// 设置popupWindow背景透明,否则PopupWindow整体是灰色背景
setBackgroundDrawable(null);
// 点击返回时收起弹窗
setBackCancel();
mMaskLayout = mContainer.findViewById(R.id.mask_layout);
// 点击窗体外部的透明遮罩时收起弹窗
mMaskLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
}
public abstract View onCreateView(Context context, ViewGroup container);
/**
* 点返回键时收起弹窗
*/
private void setBackCancel() {
// 返回键窗体消失必须设置
setFocusable(true);
setOutsideTouchable(true);
// 设置contentView能够监听事件,设置点击返回键窗体消失有必要
mContainer.setFocusable(true);
mContainer.setFocusableInTouchMode(true);
// 设置点击返回键窗体消失
mContainer.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
dismiss();
return true;
}
return false;
}
});
}
/**
* 显示弹窗,过程中伴随背景逐渐变暗。
* 不要改变MaskLayout的背景色,否则会是灰色背景的框框整体向上升起的效果。
*/
public void show(View parent) {
showAtLocation(parent, Gravity.BOTTOM, 0, 0);
ValueAnimator animator = ValueAnimator.ofFloat(1, 0.5f).setDuration(500);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
setBackgroundAlpha((Float) animation.getAnimatedValue());
}
});
animator.start();
}
/**
* 设置PopupWindow下面的内容的透明度
*/
private void setBackgroundAlpha(float bgAlpha) {
WindowManager.LayoutParams lp = ((Activity) mContext).getWindow().getAttributes();
lp.alpha = bgAlpha;
((Activity) mContext).getWindow().setAttributes(lp);
}
}
使用时继承SlidePopupWindow
,例如:
public class SharePopupWindow extends SlidePopupWindow implements View.OnClickListener {
private final Context mContext;
Button mSendToFriends;
Button mShareInTimeline;
TextView mCancelShare;
public SharePopupWindow(Context context) {
super(context);
mContext = context;
}
@Override
public View onCreateView(Context context, ViewGroup container) {
View contentView = LayoutInflater.from(context).inflate(R.layout.window_share, container, false);
mSendToFriends = contentView.findViewById(R.id.send_to_friends);
mShareInTimeline = contentView.findViewById(R.id.share_in_timeline);
mCancelShare = contentView.findViewById(R.id.cancel_share);
mSendToFriends.setOnClickListener(this);
mShareInTimeline.setOnClickListener(this);
mCancelShare.setOnClickListener(this);
return contentView;
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.cancel_share) {// 取消
dismiss();
return;
}
switch (v.getId()) {
case R.id.send_to_friends:// 发送给朋友
Toast.makeText(mContext,"发送给朋友", Toast.LENGTH_SHORT).show();
break;
case R.id.share_in_timeline:// 分享到朋友圈
Toast.makeText(mContext,"分享到朋友圈", Toast.LENGTH_SHORT).show();
break;
}
dismiss();
}
}
然后就可以愉快地“Show”啦:
new SharePopupWindow(this).show(getWindow().getDecorView().findViewById(android.R.id.content));
更多代码参见上述项目地址。