实现效果是:点击主界面的按钮,调用showDialog方法,显示的是一个登陆对话框,对话框布局在R.layout.login中。
首先是使用PopupWindow:
public class MainActivity extends Activity { private AlertDialog mDialog; private EditText editText, passwordText; private InputMethodManager imm = null; private View wholeView, view; private PopupWindow window; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(Window.FEATURE_NO_TITLE); LayoutInflater inflater = LayoutInflater.from(this); wholeView = inflater.inflate(R.layout.activity_main, null); setContentView(wholeView); } public void showDialog(View v){ WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.alpha = 0.8f; getWindow().setAttributes(lp); LayoutInflater lay = getLayoutInflater(); view = lay.inflate(R.layout.login, null); //获得view的方式 Button login = (Button)view.findViewById(R.id.login); login.setOnClickListener(new OnClickListener() { public void onClick(View v) { window.dismiss(); } }); window = new PopupWindow(view, 400, 300, true); //window.setFocusable(true); window.setBackgroundDrawable(new BitmapDrawable()); window.showAtLocation(wholeView, Gravity.CENTER, 0, 0); window.setOnDismissListener(new OnDismissListener(){ public void onDismiss() { WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.alpha = 1; getWindow().setAttributes(lp); } }); } }
实现要点:
popupWindow.setFocusable(true);这一点很重要。这样才能让popupWindow里面的布局控件获得点击的事件,否则就被它的父亲view给拦截了。
如果给 PopupWindow setFocusable(true),此时屏幕的焦点在PopupWindow上面,parent无法响应的按键事件,只会 PopupWindow
响应的按键事件。public PopupWindow (View contentView, int width, int height, boolean focusable),第四个参数我们设置为true就可以了。
PopupWindow在Focusable为false的情况下,我们使用遥控无法选中输入框,虽然鼠标点击按钮能有响应,但用鼠标点击输入
框无法出现输入法,而此时主界面可以接收按键事件。
总而言之:PopupWindow与Dialog不同之处在于PopupWindow弹出时背景Activity仍可以获取焦点(PopupWindow setFocusable(
false) 除外),设置SetFocusable(true)后,与Dialog相似,并且不能接收按键事件。
如果要使PopupWindow能响应按键事件或点击背景Activity以关闭弹出对话框 最简单的方法是使用setBackgroundDrawable()
,或者使用能创建Background的构造方法 这是因为当设置了background后会将contentView放在一个PopupViewContainer类的容器
中交给WindowManager,PopupViewContainer是PopupView的内部类,实现了对按键及Touch事件的处理。当然不设background自
己通过set对最外层contentView调用setOnKeyListener(),setOnTouchListener()也可实现。
这里当键盘出来时,原布局并没有压缩。
使用AlertDialog
public void showDialog(View v){ mDialog = new AlertDialog.Builder(this).create(); mDialog.show(); Window window = mDialog.getWindow(); window.setContentView(R.layout.login); //获得view的方式 editText = (EditText)window.findViewById(R.id.username); //AlertDialog弹出时,背景是黑色的,在此我们更改黑色幕布透明度为彻底透明 window.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); WindowManager.LayoutParams lp = window.getAttributes(); lp.dimAmount = 0.0f; mDialog.onWindowAttributesChanged(lp); mDialog.setOnKeyListener(mDialog_onKeyListener); mDialog.setCanceledOnTouchOutside(false); } private DialogInterface.OnKeyListener mDialog_onKeyListener = new DialogInterface.OnKeyListener() { public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { if (keyCode == KeyEvent.KEYCODE_BACK) {//按返回键对话框消失,透明度恢复 mDialog.dismiss(); WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.alpha = 1; getWindow().setAttributes(lp); } } return false; } };
alertDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM是指定alertDialog出现在最前,Often you will want to have a Dialog display on top of the current input method, because there is no reason for it to accept text.除了上面语句
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);可实现同样效果。
Android的对话框有两种:PopupWindow和AlertDialog。
它们的不同点在于:AlertDialog的位置固定,而PopupWindow的位置可以随意
AlertDialog是非阻塞线程的,AlertDialog弹出的时候,后台可是还可以做其他事情的哦。
而PopupWindow是阻塞线程的, 这就意味着在我们退出这个弹出框之前,程序会一直等待
PopupWindow的位置按照有无偏移分,可以分为偏移和无偏移两种;按照参照物的不同,可以分为相对于某个控件(Anchor锚)和相对于父控件。具体如下
showAsDropDown(View anchor):相对某个控件的位置(正左下方),无偏移
showAsDropDown(View anchor, int xoff, int yoff):相对某个控件的位置,有偏移
showAtLocation(View parent, int gravity, int x, int y):相对于父控件的位置(例如正中央Gravity.CENTER,
下方Gravity.BOTTOM等),可以设置偏移或无偏移