扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
public PopupWindow (Context context)
public PopupWindow(View contentView)
public PopupWindow(int width, int height)
public PopupWindow(View contentView, int width, int height)
public PopupWindow(View contentView, int width, int height, boolean focusable)
showAsDropDown(View anchor):相对某个控件的位置(正左下方),无偏移
showAsDropDown(View anchor, int xoff, int yoff):相对某个控件的位置,有偏移
showAtLocation(View parent, int gravity, int x, int y):相对于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移
具体如下所示
顺昌网站制作公司哪家好,找成都创新互联公司!从网页设计、网站建设、微信开发、APP开发、响应式网站建设等网站项目制作,到程序开发,运营维护。成都创新互联公司自2013年创立以来到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选成都创新互联公司。//创建对象
PopupWindow popupWindow = new PopupWindow(this);
View inflate = LayoutInflater.from(this).inflate(R.layout.view_pop_custom, null);
//设置view布局
popupWindow.setContentView(inflate);
popupWindow.setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);
popupWindow.setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
//设置动画的方法
popupWindow.setAnimationStyle(R.style.BottomDialog);
//设置PopUpWindow的焦点,设置为true之后,PopupWindow内容区域,才可以响应点击事件
popupWindow.setTouchable(true);
//设置背景透明
popupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000));
//点击空白处的时候让PopupWindow消失
popupWindow.setOutsideTouchable(true);
// true时,点击返回键先消失 PopupWindow
// 但是设置为true时setOutsideTouchable,setTouchable方法就失效了(点击外部不消失,内容区域也不响应事件)
// false时PopupWindow不处理返回键,默认是false
popupWindow.setFocusable(false);
//设置dismiss事件
popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
}
});
boolean showing = popupWindow.isShowing();
if (!showing){
//show,并且可以设置位置
popupWindow.showAsDropDown(mTv1);
}
先看问题代码,下面这个不会出现弹窗,思考:为什么?
PopupWindow popupWindow = new PopupWindow(this);
View inflate = LayoutInflater.from(this).inflate(R.layout.view_pop_custom, null);
popupWindow.setContentView(inflate);
popupWindow.setAnimationStyle(R.style.BottomDialog);
popupWindow.showAsDropDown(mTv1);
首先先来看看源码
可以看出,先判断是否show,如果没有showing的话,则进行contentView赋值,如果mWindowManager为null,则取获取mWindowManager,这个很重要。最后便是根据SDK版本而不是在构造函数中设置附加InDecor的默认设置,因为构造函数中可能没有上下文对象。我们只想在这里设置默认,如果应用程序尚未设置附加InDecor。
public void setContentView(View contentView) {
//判断是否show,如果已经show,则返回
if (isShowing()) {
return;
}
//赋值
mContentView = contentView;
if (mContext == null && mContentView != null) {
mContext = mContentView.getContext();
}
if (mWindowManager == null && mContentView != null) {
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
}
//在这里根据SDK版本而不是在构造函数中设置附加InDecor的默认设置,因为构造函数中可能没有上下文对象。我们只想在这里设置默认,如果应用程序尚未设置附加InDecor。
if (mContext != null && !mAttachedInDecorSet) {
setAttachedInDecor(mContext.getApplicationInfo().targetSdkVersion
>= Build.VERSION_CODES.LOLLIPOP_MR1);
}
}
public void setAttachedInDecor(boolean enabled) {
mAttachedInDecor = enabled;
mAttachedInDecorSet = true;
}
先来看一下showAsDropDown(View anchor)部分代码
public void showAsDropDown(View anchor) {
showAsDropDown(anchor, 0, 0);
}
//主要看这个方法
//注意啦:关于更多内容,可以参考我的博客大汇总:https://github.com/yangchong211/YCBlogs
public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {
if (isShowing() || mContentView == null) {
return;
}
TransitionManager.endTransitions(mDecorView);
//下面单独讲
//https://github.com/yangchong211/YCBlogs
attachToAnchor(anchor, xoff, yoff, gravity);
mIsShowing = true;
mIsDropdown = true;
//通过createPopupLayoutParams方法创建和初始化LayoutParams
final WindowManager.LayoutParams p = createPopupLayoutParams(anchor.getWindowToken());
preparePopup(p);
final boolean aboveAnchor = findDropDownPosition(anchor, p, xoff, yoff,
p.width, p.height, gravity);
updateAboveAnchor(aboveAnchor);
p.accessibilityIdOfAnchor = (anchor != null) ? anchor.getAccessibilityViewId() : -1;
invokePopup(p);
}
接着来看看attachToAnchor(anchor, xoff, yoff, gravity)源码
关于四种引用的深入介绍可以参考我的这边文章:01.四种引用比较与源码分析
private void attachToAnchor(View anchor, int xoff, int yoff, int gravity) {
detachFromAnchor();
final ViewTreeObserver vto = anchor.getViewTreeObserver();
if (vto != null) {
vto.addOnScrollChangedListener(mOnScrollChangedListener);
}
final View anchorRoot = anchor.getRootView();
anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
mAnchor = new WeakReference<>(anchor);
mAnchorRoot = new WeakReference<>(anchorRoot);
mIsAnchorRootAttached = anchorRoot.isAttachedToWindow();
mAnchorXoff = xoff;
mAnchorYoff = yoff;
mAnchoredGravity = gravity;
}
接着看看dismissImmediate(View decorView, ViewGroup contentHolder, View contentView)源码
第三步,讲mDecorView,mBackgroundView置为null
private void dismissImmediate(View decorView, ViewGroup contentHolder, View contentView) {
// If this method gets called and the decor view doesn't have a parent,
// then it was either never added or was already removed. That should
// never happen, but it's worth checking to avoid potential crashes.
if (decorView.getParent() != null) {
mWindowManager.removeViewImmediate(decorView);
}
if (contentHolder != null) {
contentHolder.removeView(contentView);
}
// This needs to stay until after all transitions have ended since we
// need the reference to cancel transitions in preparePopup().
mDecorView = null;
mBackgroundView = null;
mIsTransitioningToDismiss = false;
}
通过createDecorView(View contentView)方法可以知道,是PopupDecorView直接new出来的布局对象decorView,外面包裹了一层PopupDecorView,这里的PopupDecorView也是我们自定义的FrameLayout的子类,然后看一下里面的代码:
private class PopupDecorView extends FrameLayout {
private TransitionListenerAdapter mPendingExitListener;
public PopupDecorView(Context context) {
super(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
if ((event.getAction() == MotionEvent.ACTION_DOWN)
&& ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) {
dismiss();
return true;
} else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
dismiss();
return true;
} else {
return super.onTouchEvent(event);
}
}
}
new CustomPopupWindow.PopupWindowBuilder(this)
//.setView(R.layout.pop_layout)
.setView(contentView)
.setFocusable(true)
//弹出popWindow时,背景是否变暗
.enableBackgroundDark(true)
//控制亮度
.setBgDarkAlpha(0.7f)
.setOutsideTouchable(true)
.setAnimationStyle(R.style.popWindowStyle)
.setOnDissmissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
//对话框销毁时
}
})
.create()
.showAsDropDown(tv6,0,10);
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流