android之Dialog对话框样式的四种实现方式


1.最好的实现方式,重写dialog样式。

   特点:1)需要自定义整个布局内容。

2)可以设置点击对话框外禁止取消窗口。

3)可以弹出输入法。

                4)点返回键可以取消。

package com.ebt.app.msettings.view;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;

import com.ebt.app.R;

/**
 * 对话框基类
 * 
 * @author Allen.li
 * 
 */
public class BaseDialog extends Dialog{
	private Context context;
	private LayoutInflater inflater;
	private ViewGroup view;
	public BaseDialog(Context context) {
//		super(context);
		super(context, R.style.dialog);
		this.context = context;
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setCanceledOnTouchOutside(false);//点击对话框外禁止取消窗口
		LayoutParams params = getWindow().getAttributes();
		params.windowAnimations = R.style.popupAnimation;
		getWindow().setGravity(Gravity.CENTER_HORIZONTAL|Gravity.CENTER_VERTICAL);
		getWindow().setAttributes(
				(android.view.WindowManager.LayoutParams) params);
		
		this.inflater = getLayoutInflater();
		view = (ViewGroup) inflater.inflate(R.layout.widget_window_msg_phone, null);
		setContentView(view);
		view.setFocusable(true);
		view.setFocusableInTouchMode(true);
		view.requestFocus();
	}
}


<?xml version="1.0" encoding="utf-8"?>

<resources>

    <style name="dialog" >
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowFrame">@null</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:colorBackgroundCacheHint">@null</item>
        <item name="android:windowBackground">@color/full_transparent</item>
        <item name="android:windowContentOverlay">@null</item><!-- 这两个属性不加上顶部会出现阴影 -->
        <item name="android:windowActionModeOverlay">true</item>
        <!-- <item name="android:backgroundDimEnabled">false</item> -->
    </style>


</resources>


BaseDialog bd = new BaseDialog(getContext());bd.show();

2.在用AlertDialog来实现。代码同dialog一样,不过输入法不弹出了。解决这个问题参看如下链接,可以弹出输入法,可以设置点击对话框外禁止取消窗口。

http://blog.csdn.net/fastthinking/article/details/38492389


3.在用activity来实现。样式设置成dialog样式。不过用Acitivity来实现简单的对话框有些不必要。


4.用PopupWindow实现,不过在有输入框的对话框时,PopupWindow不能很好的实现点击返回键退出。原因如下:


1).发现PopupWindow一个bug。

只有获取焦点才能弹出输入法,如果PopupWindow的ContentView想弹出输入法的话,必须设置PopupWindow获取焦点,即PopupWindow.setFocusable(true);

但是会导致设置禁止点击弹出窗口外失败,PopupWindow.setOutsideTouchable(false);即点击弹出窗口外会取消窗口。因为

setOutsideTouchable的设置仅仅对处于未获取焦点的且处于可触摸模式的PopupWindow起作用。setOutsideTouchable默认值是false.也就是说如果PopupWindow获取了焦点,此方法不起作用。点击PopupWindow窗口外的动作响应是取消窗口。

原文注释:

Open Declarationvoid android.widget. PopupWindow.setOutsideTouchable( boolean touchable)

Controls whether the pop-up will be informed of touch events outside of its window.This only makes sense for pop-ups that are touchable but not focusable, which means touches outside of the window will be delivered to the window behind. The default is false.

If the popup is showing, calling this method will take effect only the next time the popup is shown or through a manual call to one of theupdate() methods.

Parameters:
touchable true if the popup should receive outside touch events, false otherwise
See Also:
isOutsideTouchable()
isShowing()
update()


2).如果想设置点击PopupWindow外事件不取消PopupWindow的话,必须如下设置,

PopupWindow.setTouchable(true);//默认
PopupWindow.setFocusable(false);//取消获取焦点,这会导致无法弹出输入法
PopupWindow.setOutsideTouchable(false);


3).看PopupWindow源码知,点击PopupWindow外面区域,自动dismiss,需要调用

PopupWindow.setBackgroundDrawable(new ColorDrawable());//这个很关键

PopupWindow.setOutsideTouchable(true);


4).需要的效果之一,点击点击PopupWindow外面区域,不dismiss对话框,并且点击弹出窗口的输入组件会弹出输入法。(设置PopupWindow.setFocusable(true))

                View contentView = LayoutInflater.from(getContext()).inflate(
				R.layout.widget_window_security, null);
		// 重写onKeyListener,获取焦点的视图上捕获返回键,取消弹出窗口
		contentView.setOnKeyListener(new OnKeyListener() {
			@Override
			public boolean onKey(View v, int keyCode, KeyEvent event) {
				if (keyCode == KeyEvent.KEYCODE_BACK) {
					if (securityWindow != null) {
						securityWindow.dismiss();
					}
					return true;
				}
				return false;
			}
		});
		Button mBtnCancel = (Button)contentView.findViewById(R.id.window_btn_cancel);
		mBtnCancel.setOnClickListener(this);
		Button mBtnFinish = (Button)contentView.findViewById(R.id.window_btn_finish);
		mBtnFinish.setOnClickListener(this);
		mEditPwd = (EditText) contentView.findViewById(R.id.window_input_pwd);
                //如果还想实现返回键退出窗口效果,只能是在获取焦点的视图上捕捉返回按钮,或者是Activity捕捉返回按钮。
		mEditPwd .setOnKeyListener(new OnKeyListener() {
			@Override
			public boolean onKey(View v, int keyCode, KeyEvent event) {
				if (keyCode == KeyEvent.KEYCODE_BACK) {
					if (securityWindow != null) {
						securityWindow.dismiss();
					}
					return true;
				}
				return false;
			}
		});
		contentView.setFocusable(true); // 这个很重要
		contentView.setFocusableInTouchMode(true);
		
		securityWindow = new PopupWindow(contentView, LayoutParams.WRAP_CONTENT,
				LayoutParams.WRAP_CONTENT, true);
		
//		securityWindow.setBackgroundDrawable(new ColorDrawable());//这句不能加,加了点击空白处就取消窗口啦
		securityWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
		securityWindow
				.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
		securityWindow.setFocusable(true);//设置允许获取焦点,可以弹出输入法
		
		securityWindow.setWidth(UIHelper.dip2px(getContext(), 520));
		securityWindow.setHeight(UIHelper.dip2px(getContext(), 250));
		securityWindow.showAtLocation(this, Gravity.CENTER, 0, 0);

5).看PopupWindow源码知,PopupWindow的PopupViewContainer类是私有的,用来控制显示和处理点击事件,包括点击窗口外取消窗口,没法重写它来处理点击窗口外取消窗口事件。

你可能感兴趣的:(PopDialog)