我自定義了一個(gè)dialog,彈出后范圍為紅色區(qū)域。我設(shè)置了紅色區(qū)域點(diǎn)擊后將dialog dismiss,但是我點(diǎn)擊黃色劃線的地方dialog卻無法消失,但在黃線內(nèi)的紅色區(qū)域和黃線外的區(qū)域都可以讓dialog消失。
Dialog詳細(xì)代碼:
package com.xujiaji.happybubble;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
/**
* Created by JiajiXu on 17-12-4.
*/
public class BubbleDialog extends Dialog
{
/**
* 氣泡位置
*/
public enum Position
{
/**
* 左邊
*/
LEFT,
/**
* 上邊
*/
TOP,
/**
* 右邊
*/
RIGHT,
/**
* 下邊
*/
BOTTOM
}
private BubbleLayout mBubbleLayout;
private View mAddView;//需要添加的view
private View mClickedView;//點(diǎn)擊的View
private boolean mCalBar;//計(jì)算中是否包含狀態(tài)欄
private int mOffsetX, mOffsetY;//x和y方向的偏移
private boolean mSoftShowUp;//當(dāng)軟件盤彈出時(shí)Dialog上移
private Position mPosition = Position.TOP;//氣泡位置,默認(rèn)上位
public BubbleDialog(Context context)
{
super(context, R.style.bubble_dialog);
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (mBubbleLayout == null)
{
mBubbleLayout = new BubbleLayout(getContext());
}
if (mAddView != null)
{
mBubbleLayout.addView(mAddView);
}
setContentView(mBubbleLayout);
final Window window = getWindow();
if (window == null) return;
if (mSoftShowUp)
{
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
}
window.setLayout(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
setLook();
mBubbleLayout.post(new Runnable()
{
@Override
public void run()
{
dialogPosition();
}
});
mBubbleLayout.setOnClickEdgeListener(new BubbleLayout.OnClickEdgeListener()
{
@Override
public void edge()
{
dismiss();
}
});
}
private void setLook()
{
switch (mPosition)
{
case LEFT:
mBubbleLayout.setLook(BubbleLayout.Look.RIGHT);
break;
case TOP:
mBubbleLayout.setLook(BubbleLayout.Look.BOTTOM);
break;
case RIGHT:
mBubbleLayout.setLook(BubbleLayout.Look.LEFT);
break;
case BOTTOM:
mBubbleLayout.setLook(BubbleLayout.Look.TOP);
break;
}
mBubbleLayout.initPadding();
}
@Override
public void dismiss()
{
if (mSoftShowUp)
{
Util.hide(BubbleDialog.this);
}
super.dismiss();
}
private void dialogPosition()
{
if (mClickedView == null)
{
throw new RuntimeException("Please add the clicked view.");
}
int[] clickedViewLocation = new int[2];
mClickedView.getLocationOnScreen(clickedViewLocation);
Window window = getWindow();
if (window == null) return;
window.setGravity(Gravity.LEFT | Gravity.TOP);
WindowManager.LayoutParams params = window.getAttributes();
switch (mPosition)
{
case TOP:
case BOTTOM:
params.x = clickedViewLocation[0] + mClickedView.getWidth() / 2 - mBubbleLayout.getWidth() / 2 + mOffsetX;
if (params.x <= 0)
{
mBubbleLayout.setLookPosition(clickedViewLocation[0] + mClickedView.getWidth() / 2 - mBubbleLayout.getLookWidth() / 2);
} else if (params.x + mBubbleLayout.getWidth() > Util.getScreenWH(getContext())[0])
{
mBubbleLayout.setLookPosition(clickedViewLocation[0] - (Util.getScreenWH(getContext())[0] - mBubbleLayout.getWidth()) + mClickedView.getWidth() / 2 - mBubbleLayout.getLookWidth() / 2);
} else
{
mBubbleLayout.setLookPosition(clickedViewLocation[0] - params.x + mClickedView.getWidth() / 2 - mBubbleLayout.getLookWidth() / 2);
}
if (mPosition == Position.BOTTOM)
{
params.y = clickedViewLocation[1] - (mCalBar ? Util.getStatusHeight(getContext()) : 0) + mClickedView.getHeight() + mOffsetY;
} else
{
params.y = clickedViewLocation[1] - (mCalBar ? Util.getStatusHeight(getContext()) : 0) - mBubbleLayout.getHeight() + mOffsetY;
}
break;
case LEFT:
case RIGHT:
params.y = clickedViewLocation[1] - (mCalBar ? Util.getStatusHeight(getContext()) : 0) + mOffsetY + mClickedView.getHeight() / 2 - mBubbleLayout.getHeight() / 2;
if (params.y <= 0)
{
mBubbleLayout.setLookPosition(clickedViewLocation[1] + mClickedView.getHeight() / 2 - mBubbleLayout.getLookWidth() / 2);
} else if (params.y + mBubbleLayout.getHeight() > Util.getScreenWH(getContext())[1])
{
mBubbleLayout.setLookPosition(clickedViewLocation[1] - (Util.getScreenWH(getContext())[1] - mBubbleLayout.getHeight() + mClickedView.getHeight() / 2 - mBubbleLayout.getLookWidth() / 2));
} else
{
mBubbleLayout.setLookPosition(clickedViewLocation[1] - params.y + mClickedView.getHeight() / 2 - mBubbleLayout.getLookWidth()/ 2 - (mCalBar ? Util.getStatusHeight(getContext()) : 0));
}
if (mPosition == Position.RIGHT)
{
params.x = clickedViewLocation[0] + mClickedView.getWidth() + mOffsetX;
} else
{
params.x = clickedViewLocation[0] - mBubbleLayout.getWidth() + mOffsetX;
}
break;
}
mBubbleLayout.invalidate();
window.setAttributes(params);
}
/**
* 計(jì)算時(shí)是否包含狀態(tài)欄(如果有狀態(tài)欄目,而沒有設(shè)置為true將會出現(xiàn)上下的偏差)
*/
public <T extends BubbleDialog> T calBar(boolean cal)
{
this.mCalBar = cal;
return (T) this;
}
/**
* 設(shè)置被點(diǎn)擊的view來設(shè)置彈出dialog的位置
*/
public <T extends BubbleDialog> T setClickedView(View view)
{
this.mClickedView = view;
return (T) this;
}
/**
* 當(dāng)軟件鍵盤彈出時(shí),dialog根據(jù)條件上移
*/
public <T extends BubbleDialog> T softShowUp()
{
this.mSoftShowUp = true;
return (T) this;
}
/**
* 設(shè)置dialog內(nèi)容view
*/
public <T extends BubbleDialog> T addContentView(View view)
{
this.mAddView = view;
return (T) this;
}
public <T extends BubbleDialog> T setPosition(Position position)
{
this.mPosition = position;
return (T) this;
}
/**
* 設(shè)置x方向偏移量
*/
public <T extends BubbleDialog> T setOffsetX(int offsetX)
{
this.mOffsetX = Util.dpToPx(getContext(), offsetX);
return (T) this;
}
/**
* 設(shè)置y方向偏移量
*/
public <T extends BubbleDialog> T setOffsetY(int offsetY)
{
this.mOffsetY = Util.dpToPx(getContext(), offsetY);
return (T) this;
}
/**
* 自定義氣泡布局
*/
public <T extends BubbleDialog> T setBubbleLayout(BubbleLayout bl)
{
this.mBubbleLayout = bl;
return (T) this;
}
/**
* 背景全透明
*/
public <T extends BubbleDialog> T setTransParentBackground()
{
Window window = getWindow();
if (window == null) return (T) this;
window.setDimAmount(0);
return (T) this;
}
}找到原因了,原來是Window中的isOutOfBounds方法進(jìn)行了一個(gè)限制 。
private boolean isOutOfBounds(Context context, MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
final View decorView = getDecorView();
return (x < -slop) || (y < -slop)
|| (x > (decorView.getWidth()+slop))
|| (y > (decorView.getHeight()+slop));
}
這個(gè)方法在onTouchEvent方法中被觸發(fā),于是我重寫了onTouchEvent相關(guān)的東西,代碼如下(省略了多余代碼):
public class BubbleDialog extends Dialog
{
...
private boolean mCancelable;//是否能夠取消
...
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setCancelable(true);
...
}
...
public boolean onTouchEvent(MotionEvent event) {
Window window = getWindow();
if (window == null) return false;
final View decorView = window.getDecorView();
if (mCancelable && isShowing() && shouldCloseOnTouch(event, decorView)) {
cancel();
return true;
}
return false;
}
public boolean shouldCloseOnTouch(MotionEvent event, View decorView) {
final int x = (int) event.getX();
final int y = (int) event.getY();
return (x <= 0) || (y <= 0)
|| (x > (decorView.getWidth()))
|| (y > (decorView.getHeight()));
}
public void setCancelable(boolean flag)
{
super.setCancelable(flag);
mCancelable = flag;
}
...
}
這是我的一個(gè)氣泡對話框式Dialog開源庫,有興趣歡迎“Star”:https://github.com/xujiaji/Ha...
北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國一站式人才培養(yǎng)平臺、一站式人才輸送平臺。2014年4月3日在美國成功上市,融資1
北大課工場是北京大學(xué)校辦產(chǎn)業(yè)為響應(yīng)國家深化產(chǎn)教融合/校企合作的政策,積極推進(jìn)“中國制造2025”,實(shí)現(xiàn)中華民族偉大復(fù)興的升級產(chǎn)業(yè)鏈。利用北京大學(xué)優(yōu)質(zhì)教育資源及背
博為峰,中國職業(yè)人才培訓(xùn)領(lǐng)域的先行者
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動(dòng)互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺面向?qū)ο箝_發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國Software AG 技術(shù)顧問,美國Dachieve 系統(tǒng)架構(gòu)師,美國AngelEngineers Inc. 系統(tǒng)架構(gòu)師。