您好,登錄后才能下訂單哦!
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等),可以設置偏移或無偏移
具體如下所示
//創建對象
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);
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。