AlertDialog源码解析之一

首先我们先了解关于AlertDialog之间的继承关系
AlertDialog extends Dialog implements DialogInterface

public class Dialog implements DialogInterfaceWindow.Callback,
KeyEvent.CallbackOnCreateContextMenuListenerWindow.OnWindowDismissedCallback、

其次了解其中相关的theme的属性:

 
  
static int resolveDialogTheme(Context context, int themeResId) {

if (themeResId == THEME_TRADITIONAL) {
return R.style.Theme_Dialog_Alert;
} else if (themeResId == THEME_HOLO_DARK) {
return R.style.Theme_Holo_Dialog_Alert;
} else if (themeResId == THEME_HOLO_LIGHT) {
return R.style.Theme_Holo_Light_Dialog_Alert;
} else if (themeResId == THEME_DEVICE_DEFAULT_DARK) {
return R.style.Theme_DeviceDefault_Dialog_Alert;
} else if (themeResId == THEME_DEVICE_DEFAULT_LIGHT) {
return R.style.Theme_DeviceDefault_Light_Dialog_Alert;
} else if (themeResId >= 0x01000000) { // start of real resource IDs.
return themeResId;
} else {
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.alertDialogTheme, outValue, true);
return outValue.resourceId;
}
}
针对于AlertDialog属性中,如果没有去特殊的定义DialogTheme。它回去系统的themeResId。如果不是自定义的那么久对照系统中已经有的theme,然后再找到其中的dialog的样式。如果是自定义的就返回这个dialog的theme。所以这边可以看出Dialog的其中的属性和activity其中的属性并没有什么关联的地方,也就是如果在Dialog外层去定义属性比如textColor在Dialog中是不生效的。
下面是Dialog的初始化代码:
Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
if (createContextThemeWrapper) {
if (themeResId == 0) {
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
themeResId = outValue.resourceId;
}
mContext = new ContextThemeWrapper(context, themeResId);
} else {
mContext = context;
}

mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

final Window w = new PhoneWindow(mContext);
mWindow = w;
w.setCallback(this);
w.setOnWindowDismissedCallback(this);
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);

mListenersHandler = new ListenersHandler(this);
}
这边是直接对Windows进行操作,可以看出来Dialog其实就是那个Activity上面在创建一个Windows.

AlertDialog(Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0,
createContextThemeWrapper);

mWindow.alwaysReadCloseOnTouchAttr();
mAlert = new AlertController(getContext(), this, getWindow());
}

AlertController.java就是对AlertDialog.java的操作类。
public AlertController(Context context, DialogInterface di, Window window) {
mContext = context;
mDialogInterface = di;
mWindow = window;
mHandler = new ButtonHandler(di);

final TypedArray a = context.obtainStyledAttributes(null,
R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);

mAlertDialogLayout = a.getResourceId(
R.styleable.AlertDialog_layout, R.layout.alert_dialog);
mButtonPanelSideLayout = a.getResourceId(
R.styleable.AlertDialog_buttonPanelSideLayout, 0);
mListLayout = a.getResourceId(
R.styleable.AlertDialog_listLayout, R.layout.select_dialog);

mMultiChoiceItemLayout = a.getResourceId(
R.styleable.AlertDialog_multiChoiceItemLayout,
R.layout.select_dialog_multichoice);
mSingleChoiceItemLayout = a.getResourceId(
R.styleable.AlertDialog_singleChoiceItemLayout,
R.layout.select_dialog_singlechoice);
mListItemLayout = a.getResourceId(
R.styleable.AlertDialog_listItemLayout,
R.layout.select_dialog_item);
//Add begin by meitu.zhanghong to init he mItemHeigh(180px) and mItemCount(6.5)
mItemHeight =context.getResources().getDimensionPixelOffset(com.meitu.R.dimen.list_preferred_item_height_small);
mItemCount = Utils.MAX_DIALOG_ITEM_MEITU;
//Add end
a.recycle();
}
所以针对AlertDialog可以解析的attr有:
1.layout
就是指可以ALertDialog Windows 设置的layout文件
mWindow.setContentView(contentView);
2. buttonPanelSideLayout
对于这个属性,我们先看一下
public void setButtonPanelLayoutHint(int layoutHint) {
mButtonPanelLayoutHint = layoutHint;
}
可以去设置对于确认按钮提示说明,貌似这个layoutHint不为0都是生效的。
private int selectContentView() {
if (mButtonPanelSideLayout == 0) {
return mAlertDialogLayout;
}
if (mButtonPanelLayoutHint == AlertDialog.LAYOUT_HINT_SIDE) {
return mButtonPanelSideLayout;
}
// TODO: use layout hint side for long messages/lists
return mAlertDialogLayout;
}
如果是存在提示说明的情况下,回去使用,mButtonPanelSideLayout 替换mAlertDialogLayout文件。
这些操作都是在AlertDialog onCreate 的时候去执行的操作。

public void installContent() {
/* We use a custom title so never request a window title */
mWindow.requestFeature(Window.FEATURE_NO_TITLE);
int contentView = selectContentView();
mWindow.setContentView(contentView);
setupView();
setupDecor();
}
关注:setupView()
private void setupView() {             P.mCancelable = false;
......//取到不同的控件
setupContent(contentPanel);//对于alert_dialog.xml文件中 scrollview listview 的不同处理方式
setupButtons(buttonPanel);//对于三个Button,在系统中定义了三个button的样式分别是
    //int BIT_BUTTON_POSITIVE = 1; 确认按钮
//int BIT_BUTTON_NEGATIVE = 2;//取消按钮
//int BIT_BUTTON_NEUTRAL = 4;中间的按钮 可以通过重写这三个样式在style.xml文件中去改变button的样式

setupTitle(topPanel);// 对于自定义title,有icon的title,只有textview title的不同处理方式。
......
// Only display the text spacer if we don't have buttons.
if (!hasButtonPanel) {
if (contentPanel != null) {
final View spacer = contentPanel.findViewById(R.id.textSpacerNoButtons);
if (spacer != null) {
spacer.setVisibility(View.VISIBLE);
}
}
mWindow.setCloseOnTouchOutsideIfNotSet(true);//点击空白区域是否消失的初始化,针对AlertDialog的一个属性 P.mCancelable = false;
}
    ......
final TypedArray a = mContext.obtainStyledAttributes(
null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);
setBackground(a, topPanel, contentPanel, customPanel, buttonPanel,
hasTopPanel, hasCustomPanel, hasButtonPanel);
a.recycle();
// Add begin by meitu.liujr for:MEIOS3
if(com.meitu.mobile.theme.Utils.isMeituUI(mContext)){
WindowManager.LayoutParams lp = mWindow.getAttributes();
if(mListView !=null){
if(mTitleView!=null){
mTitleView.setTextColor(mContext.getResources().getColor(com.meitu.internal.R.color.primary_text_default_material_light));
mTitleView.setTextSize(TypedValue.COMPLEX_UNIT_PX,mContext.getResources().getDimensionPixelSize(com.meitu.internal.R.dimen.text_size_large_material));
}
// has not buttons
if(TextUtils.isEmpty(mButtonNegativeText) && TextUtils.isEmpty(mButtonPositiveText) && TextUtils.isEmpty(mButtonNeutralText)){
//if( !hasButtonPanel){
lp.gravity = Gravity.BOTTOM;
lp.windowAnimations = android.R.style.Animation_InputMethod;
// has title
if(mCustomTitleView !=null || !TextUtils.isEmpty(mTitle)){
// if(hasTopPanel){
mWindow.setBackgroundDrawableResource(com.meitu.internal.R.drawable.dialog_background_meitu_title);
}else{
mWindow.setBackgroundDrawableResource(com.meitu.internal.R.drawable.menu_hardkey_panel_meitu_light);
}
}else{
lp.gravity = Gravity.CENTER;
lp.windowAnimations = android.R.style.Animation_Dialog;
mWindow.setBackgroundDrawableResource(com.meitu.internal.R.drawable.dialog_background_meitu);
}
}else{

if(mTitleView!=null){
mTitleView.setTextColor(mContext.getResources().getColor(com.meitu.internal.R.color.dialog_title_text_color));
mTitleView.setTextSize(TypedValue.COMPLEX_UNIT_PX,mContext.getResources().getDimensionPixelSize(com.meitu.internal.R.dimen.text_size_subhead_material));
}

lp.gravity = Gravity.CENTER;
lp.windowAnimations = android.R.style.Animation_Dialog;
mWindow.setBackgroundDrawableResource(com.meitu.internal.R.drawable.dialog_background_meitu);

}
mWindow.setAttributes(lp);
}
// Add end
}
3.listLayout
设置listview的layout文件

4.multiCHoiceItemLayout
设置多选列表的layout文件
5.singleChoiceItemLayout
设置单选列表的layout文件
6.listItemLayout
对于listItem的layout文件
这些是在AlertController.java里面需要去解析的theme属性。下面回去看其中的layout文件,layout文件中也会有一些属性需要去解析。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值