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):相對某個(gè)控件的位置(正左下方),無偏移
showAsDropDown(View anchor, int xoff, int yoff):相對某個(gè)控件的位置,有偏移
showAtLocation(View parent, int gravity, int x, int y):相對于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以設(shè)置偏移或無偏移
具體如下所示
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長期合作伙伴,公司提供的服務(wù)項(xiàng)目有:國際域名空間、虛擬主機(jī)、營銷軟件、網(wǎng)站建設(shè)、惠陽網(wǎng)站維護(hù)、網(wǎng)站推廣。
//創(chuàng)建對象
PopupWindow popupWindow = new PopupWindow(this);
View inflate = LayoutInflater.from(this).inflate(R.layout.view_pop_custom, null);
//設(shè)置view布局
popupWindow.setContentView(inflate);
popupWindow.setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);
popupWindow.setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
//設(shè)置動(dòng)畫的方法
popupWindow.setAnimationStyle(R.style.BottomDialog);
//設(shè)置PopUpWindow的焦點(diǎn),設(shè)置為true之后,PopupWindow內(nèi)容區(qū)域,才可以響應(yīng)點(diǎn)擊事件
popupWindow.setTouchable(true);
//設(shè)置背景透明
popupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000));
//點(diǎn)擊空白處的時(shí)候讓PopupWindow消失
popupWindow.setOutsideTouchable(true);
// true時(shí),點(diǎn)擊返回鍵先消失 PopupWindow
// 但是設(shè)置為true時(shí)setOutsideTouchable,setTouchable方法就失效了(點(diǎn)擊外部不消失,內(nèi)容區(qū)域也不響應(yīng)事件)
// false時(shí)PopupWindow不處理返回鍵,默認(rèn)是false
popupWindow.setFocusable(false);
//設(shè)置dismiss事件
popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
}
});
boolean showing = popupWindow.isShowing();
if (!showing){
//show,并且可以設(shè)置位置
popupWindow.showAsDropDown(mTv1);
}
先看問題代碼,下面這個(gè)不會(huì)出現(xiàn)彈窗,思考:為什么?
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的話,則進(jìn)行contentView賦值,如果mWindowManager為null,則取獲取mWindowManager,這個(gè)很重要。最后便是根據(jù)SDK版本而不是在構(gòu)造函數(shù)中設(shè)置附加InDecor的默認(rèn)設(shè)置,因?yàn)闃?gòu)造函數(shù)中可能沒有上下文對象。我們只想在這里設(shè)置默認(rèn),如果應(yīng)用程序尚未設(shè)置附加InDecor。
public void setContentView(View contentView) {
//判斷是否show,如果已經(jīng)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);
}
//在這里根據(jù)SDK版本而不是在構(gòu)造函數(shù)中設(shè)置附加InDecor的默認(rèn)設(shè)置,因?yàn)闃?gòu)造函數(shù)中可能沒有上下文對象。我們只想在這里設(shè)置默認(rèn),如果應(yīng)用程序尚未設(shè)置附加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);
}
//主要看這個(gè)方法
//注意啦:關(guān)于更多內(nèi)容,可以參考我的博客大匯總:https://github.com/yangchong211/YCBlogs
public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {
if (isShowing() || mContentView == null) {
return;
}
TransitionManager.endTransitions(mDecorView);
//下面單獨(dú)講
//https://github.com/yangchong211/YCBlogs
attachToAnchor(anchor, xoff, yoff, gravity);
mIsShowing = true;
mIsDropdown = true;
//通過createPopupLayoutParams方法創(chuàng)建和初始化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)源碼
關(guān)于四種引用的深入介紹可以參考我的這邊文章: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時(shí),背景是否變暗
.enableBackgroundDark(true)
//控制亮度
.setBgDarkAlpha(0.7f)
.setOutsideTouchable(true)
.setAnimationStyle(R.style.popWindowStyle)
.setOnDissmissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
//對話框銷毀時(shí)
}
})
.create()
.showAsDropDown(tv6,0,10);
本文名稱:PopupWindow源碼分析
當(dāng)前網(wǎng)址:http://www.rwnh.cn/article38/jipcsp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃、網(wǎng)站設(shè)計(jì)公司、虛擬主機(jī)、移動(dòng)網(wǎng)站建設(shè)、云服務(wù)器、標(biāo)簽優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)