Android进阶——自定义View之扩展系统Dialog

引言

今天给大家总结有关自定义对话框的相关内容,前面文章Android入门——AlertDialog和ProgressDialog总结 都在在利用系统提供的函数来实现对话框,但局限性太大,当我们想自己定义Dialog视图的时候,就不能利用系统函数了,就需要我们这里的自定义对话框了来满足产品经理的各种idea。

一、Dialog部分源码结构

学习下源码的编程风格和规范


/** * Base class for Dialogs. * Activity提供了一系列的方法用于dialog的管理:onCreateDialog(int)、onPrepareDialog(int)、showDialog(int)、dismissDialog(int)、 *当这些方法被调用之后我们就可以通过 getOwnerActivity()方法获取得到对应的Dialog依附的Activity * *设置在Dialog中隐藏软键盘 * getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); */
public class Dialog implements DialogInterface, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, Window.OnWindowDismissedCallback {

    private Activity mOwnerActivity;
    final Context mContext;
    final WindowManager mWindowManager;
    Window mWindow;
    View mDecor;
    private ActionBar mActionBar;
    protected boolean mCancelable = true;
    private String mCancelAndDismissTaken;
    private Message mCancelMessage,mDismissMessage,mShowMessage;

    private OnKeyListener mOnKeyListener;
    private boolean mCreated = false,mShowing = false,mCanceled = false;
    private final Handler mHandler = new Handler();
    private static final int DISMISS = 0x43,CANCEL = 0x44,SHOW = 0x45;
    private Handler mListenersHandler;

    private SearchEvent mSearchEvent;
    private ActionMode mActionMode;

    private int mActionModeTypeStarting = ActionMode.TYPE_PRIMARY;

    private final Runnable mDismissAction = new Runnable() {
        public void run() {
            dismissDialog();
        }
    };

    public Dialog(@NonNull Context context) {
        this(context, 0, true);
    }

    public Dialog(@NonNull Context context, @StyleRes int themeResId) {
        this(context, themeResId, true);
    }

    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);
    }

    /** * @deprecated * @hide */
    @Deprecated
    protected Dialog(@NonNull Context context, boolean cancelable, Message cancelCallback) {
        this(context);
        mCancelable = cancelable;
        mCancelMessage = cancelCallback;
    }

    protected Dialog(@NonNull Context context, boolean cancelable,
            OnCancelListener cancelListener) {
        this(context);
        mCancelable = cancelable;
        setOnCancelListener(cancelListener);
    }

    /** * Retrieve the Context this Dialog is running in. * @return Context The Context used by the Dialog. */
    @NonNull
    public final Context getContext() {
        return mContext;
    }
    /** * Sets the Activity that owns this dialog. An example use: This Dialog will * use the suggested volume control stream of the Activity. * @param activity The Activity that owns this dialog. */
    public final void setOwnerActivity(Activity activity) {
        mOwnerActivity = activity;
        getWindow().setVolumeControlStream(mOwnerActivity.getVolumeControlStream());
    }

    /** * Returns the Activity that owns this Dialog. For example, if * {@link Activity#showDialog(int)} is used to show this Dialog, that * Activity will be the owner (by default). Depending on how this dialog was * created, this may return null. * * @return The Activity that owns this Dialog. */
    public final Activity getOwnerActivity() {
        return mOwnerActivity;
    }

    public boolean isShowing() {
        return mShowing;
    }
    public void create() {
        if (!mCreated) {
            dispatchOnCreate(null);
        }
    }
    public void show() {
        if (DBG) {
            Log.d(TAG, "show");
        }

        if (mShowing) {
            if (mDecor != null) {
                if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
                    mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR);
                }
                mDecor.setVisibility(View.VISIBLE);
            }
            return;
        }

        mCanceled = false;

        if (!mCreated) {
            dispatchOnCreate(null);
        }

        onStart();
        mDecor = mWindow.getDecorView();

        if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
            final ApplicationInfo info = mContext.getApplicationInfo();
            mWindow.setDefaultIcon(info.icon);
            mWindow.setDefaultLogo(info.logo);
            mActionBar = new WindowDecorActionBar(this);
        }

        WindowManager.LayoutParams l = mWindow.getAttributes();
        if ((l.softInputMode
                & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
            WindowManager.LayoutParams nl = new WindowManager.LayoutParams();
            nl.copyFrom(l);
            nl.softInputMode |=
                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
            l = nl;
        }

        try {
            mWindowManager.addView(mDecor, l);
            mShowing = true;

            sendShowMessage();
        } finally {
        }
    }

    /** * Hide the dialog, but do not dismiss it. */
    public void hide() {
        if (mDecor != null) {
            mDecor.setVisibility(View.GONE);
        }
    }

    /** * 关闭并删除Dialog,线程安全,不能重写 */
    @Override
    public void dismiss() {
        if (Looper.myLooper() == mHandler.getLooper()) {
            dismissDialog();
        } else {
            mHandler.post(mDismissAction);
        }
    }
    void dismissDialog() {
        if (DBG) {
            Log.d(TAG, "dismissDialog");
        }
        if (mDecor == null || !mShowing) {
            return;
        }
        if (mWindow.isDestroyed()) {
            Log.e(TAG, "Tried to dismissDialog() but the Dialog's window was already destroyed!");
            return;
        }
        try {
            mWindowManager.removeViewImmediate(mDecor);
        } finally {
            if (mActionMode != null) {
                mActionMode.finish();
            }
            mDecor = null;
            mWindow.closeAllPanels();
            onStop();
            mShowing = false;
            sendDismissMessage();
        }
    }

    private void sendDismissMessage() {
        if (mDismissMessage != null) {
            Message.obtain(mDismissMessage).sendToTarget();
        }
    }

    private void sendShowMessage() {
        if (mShowMessage != null) {
            // Obtain a new message so this dialog can be re-used
            Message.obtain(mShowMessage).sendToTarget();
        }
    }

    /** *与Activity的类似,初始化Dialog,包括调用 setContentView *如果Dialog在Activity之前关闭,那么会调用onSaveInstanceState保留状态 * @param savedInstanceState If this dialog is being reinitalized after a */
    protected void onCreate(Bundle savedInstanceState) {
    }

    /** * Called when the dialog is starting. */
    protected void onStart() {
        if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(true);
    }

    /** * Called to tell you that you're stopping. */
    protected void onStop() {
        if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
    }

    private static final String DIALOG_SHOWING_TAG = "android:dialogShowing";
    private static final String DIALOG_HIERARCHY_TAG = "android:dialogHierarchy";

    public Bundle onSaveInstanceState() {
        Bundle bundle = new Bundle();
        bundle.putBoolean(DIALOG_SHOWING_TAG, mShowing);
        if (mCreated) {
            bundle.putBundle(DIALOG_HIERARCHY_TAG, mWindow.saveHierarchyState());
        }
        return bundle;
    }
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        final Bundle dialogHierarchyState = savedInstanceState.getBundle(DIALOG_HIERARCHY_TAG);
        if (dialogHierarchyState == null) {
            // dialog has never been shown, or onCreated, nothing to restore.
            return;
        }
        dispatchOnCreate(savedInstanceState);
        mWindow.restoreHierarchyState(dialogHierarchyState);
        if (savedInstanceState.getBoolean(DIALOG_SHOWING_TAG)) {
            show();
        }
    }
    public Window getWindow() {
        return mWindow;
    }
    public View getCurrentFocus() {
        return mWindow != null ? mWindow.getCurrentFocus() : null;
    }

    @Nullable
    public View findViewById(@IdRes int id) {
        return mWindow.findViewById(id);
    }

    public void setContentView(@LayoutRes int layoutResID) {
        mWindow.setContentView(layoutResID);
    }
    public void setContentView(View view) {
        mWindow.setContentView(view);
    }
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        mWindow.setContentView(view, params);
    }
    public void addContentView(View view, ViewGroup.LayoutParams params) {
        mWindow.addContentView(view, params);
    }
    public void setTitle(CharSequence title) {
        mWindow.setTitle(title);
        mWindow.getAttributes().setTitle(title);
    }
    public void setTitle(@StringRes int titleId) {
        setTitle(mContext.getText(titleId));
    }
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            event.startTracking();
            return true;
        }

        return false;
    }
    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
        return false;
    }
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
                && !event.isCanceled()) {
            onBackPressed();
            return true;
        }
        return false;
    }
    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
        return false;
    }
    public void onBackPressed() {
        if (mCancelable) {
            cancel();
        }
    }

    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
        return false;
    }
    public boolean onTouchEvent(MotionEvent event) {
        if (mCancelable && mShowing && mWindow.shouldCloseOnTouch(mContext, event)) {
            cancel();
            return true;
        }

        return false;
    }
    public boolean onTrackballEvent(MotionEvent event) {
        return false;
    }
    public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
        if (mDecor != null) {
            mWindowManager.updateViewLayout(mDecor, params);
        }
    }

    public void onContentChanged() {
    }

    public void onWindowFocusChanged(boolean hasFocus) {
    }

    public void onAttachedToWindow() {
    }

    public void onDetachedFromWindow() {
    }

    /** @hide */
    @Override
    public void onWindowDismissed() {
        dismiss();
    }

    /** * 事件传递 :用于处理各种事件,我们可以重写key events在传递到window之前 * @param event The key event. */
    public boolean dispatchKeyEvent(KeyEvent event) {
        if ((mOnKeyListener != null) && (mOnKeyListener.onKey(this, event.getKeyCode(), event))) {
            return true;
        }
        if (mWindow.superDispatchKeyEvent(event)) {
            return true;
        }
        return event.dispatch(this, mDecor != null
                ? mDecor.getKeyDispatcherState() : null, this);
    }
    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
        if (mWindow.superDispatchKeyShortcutEvent(event)) {
            return true;
        }
        return onKeyShortcut(event.getKeyCode(), event);
    }
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (mWindow.superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }

    public final boolean requestWindowFeature(int featureId) {
        return getWindow().requestFeature(featureId);
    }
    public final void setFeatureDrawableResource(int featureId, @DrawableRes int resId) {
        getWindow().setFeatureDrawableResource(featureId, resId);
    }
    public final void setFeatureDrawableUri(int featureId, Uri uri) {
        getWindow().setFeatureDrawableUri(featureId, uri);
    }
    public final void setFeatureDrawable(int featureId, Drawable drawable) {
        getWindow().setFeatureDrawable(featureId, drawable);
    }
    public final void setFeatureDrawableAlpha(int featureId, int alpha) {
        getWindow().setFeatureDrawableAlpha(featureId, alpha);
    }

    public LayoutInflater getLayoutInflater() {
        return getWindow().getLayoutInflater();
    }
    /** *各种监听器 **/
    public void setOnCancelListener(final OnCancelListener listener) {
        if (mCancelAndDismissTaken != null) {
            throw new IllegalStateException(
                    "OnCancelListener is already taken by "
                    + mCancelAndDismissTaken + " and can not be replaced.");
        }
        if (listener != null) {
            mCancelMessage = mListenersHandler.obtainMessage(CANCEL, listener);
        } else {
            mCancelMessage = null;
        }
    }
    public void setOnDismissListener(final OnDismissListener listener) {
        if (mCancelAndDismissTaken != null) {
            throw new IllegalStateException(
                    "OnDismissListener is already taken by "
                    + mCancelAndDismissTaken + " and can not be replaced.");
        }
        if (listener != null) {
            mDismissMessage = mListenersHandler.obtainMessage(DISMISS, listener);
        } else {
            mDismissMessage = null;
        }
    }
    public void setOnShowListener(OnShowListener listener) {
        if (listener != null) {
            mShowMessage = mListenersHandler.obtainMessage(SHOW, listener);
        } else {
            mShowMessage = null;
        }
    }
    /** * Sets the callback that will be called if a key is dispatched to the dialog. */
    public void setOnKeyListener(final OnKeyListener onKeyListener) {
        mOnKeyListener = onKeyListener;
    }
    private static final class ListenersHandler extends Handler {
        private WeakReference<DialogInterface> mDialog;

        public ListenersHandler(Dialog dialog) {
            mDialog = new WeakReference<DialogInterface>(dialog);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case DISMISS:
                    ((OnDismissListener) msg.obj).onDismiss(mDialog.get());
                    break;
                case CANCEL:
                    ((OnCancelListener) msg.obj).onCancel(mDialog.get());
                    break;
                case SHOW:
                    ((OnShowListener) msg.obj).onShow(mDialog.get());
                    break;
            }
        }
    }
}

二、扩展系统Dialog步骤

  • 定义Dialog将要显示的布局xml文件

  • 继承Dialog 并实现相关的构造方法

  • 重写相关父类的生命周期方法,比如说在onCreate里通过LayoutInflater的LayoutInflater对象的inflate方法把xml布局文件映射成为自定义的view,获取我们自定义对话框的view,然后利用setContentView

1、实现普通的自定义Dialog

定义自定义Dialog 的布局xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">

    <TextView  style="@style/TitleStyle" android:layout_width="match_parent" android:padding="5dp" android:layout_height="wrap_content" android:gravity="center" android:text="自定义的Dialog" android:drawableLeft="@mipmap/ic_red_launcher"/>
    <ProgressBar  android:layout_width="match_parent" android:layout_height="wrap_content" />
</LinearLayout>

继承Dialog并实现相关构造方法并重写onCreate:

/** * Created by cmo on 16-5-5. */
public class MyCostomDialog extends Dialog {
    Context mContext;
    public MyCostomDialog(Context context) {
        super(context);
        mContext=context;
    }
    /** *另一种形式的使用Theme * public MyCostomDialog(Context context){ super(context,R.style.myCustomdialog); mContext=context; } */
    //使用到Theme时调用
    public MyCostomDialog(Context context, int theme) {
        super(context, theme);
        mContext = context;
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LayoutInflater inflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.dialog_my_costom, null);
        this.setContentView(layout);
    }
}

styles.xml:

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
    <style name="TitleStyle">
        <item name="android:textColor">@color/colorGreen</item>
        <item name="android:textSize">@dimen/activity_title_size</item>
    </style>

    <!--
    android:windowFrame:界面对应的前景图片;
    android:background:背景图片
    android:windowIsFloating:表示浮在屏幕上的,如果在这里使用了,整个layout就会在 屏幕中心,相当于浮在屏幕上,所以这个只适用于dialog
    android:windowContentOverlay:表示标题栏的阴影部分的样式,使用图片或者颜色
    android:windowNoTitle:标题栏是否隐藏
    -->
    <style name="myCustomdialog" parent="android:Theme.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:background">@drawable/shape_dialog_bcg</item>
    </style>
</resources>
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    //调用代码显示无Theme的Dialog
    public void showDialog(View view){
        MyCostomDialog dialog = new  MyCostomDialog(MainActivity.this);
        ///MyCostomDialog dialog = new MyCostomDialog(MainActivity.this, R.style.myCustomdialog);显示自定义Theme的的Dialog
        dialog.show();
    }
}

Android进阶——自定义View之扩展系统Dialog_第1张图片

2、显示具有交互功能的Dialog

布局很简单就不贴了,既然需要交互,那肯定得注册监听,so 参考Activity上的处理肯定是在界面初始化的时候设置对应的监听


/** * Created by cmo on 16-5-5. */
public class MyCostomDialog extends Dialog {
    Context mContext;

    public MyCostomDialog(Context context) {
        super(context);
        mContext=context;
    }
    //使用到Theme时调用
    public MyCostomDialog(Context context, int theme) {
        super(context, theme);
        mContext = context;
    }
    //设置RadioGroup的监听
    private void setRadioListener(final View view){
        final RadioGroup radioGroup= (RadioGroup) view.findViewById(R.id.id_radiogroup);
        radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener(){

            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                RadioButton checkedRadio=(RadioButton)findViewById(radioGroup.getCheckedRadioButtonId());
                switch (checkedId){
                    case R.id.id_android_radiobtn:
                    case R.id.id_ios_radiobtn:
                    case R.id.id_java_radiobtn:
                         Log.d("TAG",checkedRadio.getText().toString());
                        break;
                    default:
                        break;
                }
            }
        });
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LayoutInflater inflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.dialog_my_costom, null);
        setRadioListener(layout);//设置监听
        this.setContentView(layout);
    }
}

Android进阶——自定义View之扩展系统Dialog_第2张图片
Android进阶——自定义View之扩展系统Dialog_第3张图片

3、与Activity之间的通信

3.1、通过构造函数把Activity里的数据传递至Dialog

package com.crazymo.costomstyledialog;
/** * Created by cmo on 16-5-5. */
public class MyCostomDialog extends Dialog {
    Context mContext;
    String mText;
    public MyCostomDialog(Context context) {
        super(context);
        mContext=context;
    }
    //使用到Theme时调用
    public MyCostomDialog(Context context, int theme) {
        super(context, theme);
        mContext = context;
    }
    //其中txt则是从Activity传递至DIalog的数据
    public MyCostomDialog(Context context, String txt,int theme) {
        super(context,theme);
        mContext = context;
        mText=txt;
    }

    private void setRadioListener(final View view){
        final RadioGroup radioGroup= (RadioGroup) view.findViewById(R.id.id_radiogroup);
        radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener(){

            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                RadioButton checkedRadio=(RadioButton)findViewById(radioGroup.getCheckedRadioButtonId());
                switch (checkedId){
                    case R.id.id_android_radiobtn:
                    case R.id.id_ios_radiobtn:
                    case R.id.id_java_radiobtn:
                        Log.d("TAG", checkedRadio.getText().toString());
                        break;
                    default:
                        break;
                }
            }
        });
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LayoutInflater inflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.dialog_my_costom, null);
        setRadioListener(layout);
        TextView tv = (TextView)layout.findViewById(R.id.id_dialog_title_txt);
        tv.setText(mText);//设置Activity传递来的数据
        this.setContentView(layout);
    }
}

在MainActivity里显示:

public void showDialog(View view){
        MyCostomDialog dialog = new  MyCostomDialog(MainActivity.this, "我来自Activity",R.style.myCustomdialog);
        dialog.show();
    }

3.2、通过回调方式把Dialog里的数据回传至Activity

package com.crazymo.costomstyledialog;

/** * Created by cmo on 16-5-5. */
public class MyCostomDialog extends Dialog {
    Context mContext;
    String mText;
    private  IShowPicByIndexListener mIShowPicByIndexListener;//声明一个回调接口函数变量,用于调用
    //定义一个回调接口,用于接收Activity返回的值
    public interface IShowPicByIndexListener{
        public void onShowPicIndex(int index);
    }

    public MyCostomDialog(Context context) {
        super(context);
        mContext=context;
    }
    //使用到Theme时调用
    public MyCostomDialog(Context context, int theme) {
        super(context, theme);
        mContext = context;
    }
    //把回调也传递到构造方法中
    public MyCostomDialog(Context context, String txt,int theme,IShowPicByIndexListener listener) {
        super(context,theme);
        mContext = context;
        mText=txt;
        mIShowPicByIndexListener=listener;
    }
    public MyCostomDialog(Context context, String txt,int theme) {
        super(context,theme);
        mContext = context;
        mText=txt;
    }

    private void setRadioListener(final View view){
        final RadioGroup radioGroup= (RadioGroup) view.findViewById(R.id.id_radiogroup);
        radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener(){

            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                int index=0;
                RadioButton checkedRadio=(RadioButton)findViewById(radioGroup.getCheckedRadioButtonId());
                switch (checkedId){
                    case R.id.id_android_radiobtn:
                        index=1;
                        break;
                    case R.id.id_ios_radiobtn:
                        index=2;
                        break;
                    case R.id.id_java_radiobtn:
                        index=3;
                        break;
                    default:
                        index=0;
                }
                mIShowPicByIndexListener.onShowPicIndex(index);
            }
        });
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LayoutInflater inflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.dialog_my_costom, null);
        setRadioListener(layout);
        TextView tv = (TextView)layout.findViewById(R.id.id_dialog_title_txt);
        tv.setText(mText);
        this.setContentView(layout);
    }
}
package com.crazymo.costomstyledialog;

public class MainActivity extends Activity {
    private int[] imgs={R.mipmap.ic_blue_launcher,R.mipmap.ic_red_launcher,R.mipmap.ic_toy,R.mipmap.ic_launcher};
    private RadioGroup mRadioGroup;
    private ImageView mImageView;
    private int index=0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }
    private void init(){
        getViews();
    }
    private void getViews(){
        mImageView= (ImageView) findViewById(R.id.id_pic_imgv);
    }
    public void showDialog(View view){
        MyCostomDialog dialog = new  MyCostomDialog(MainActivity.this, "我来自Activity", R.style.myCustomdialog, new MyCostomDialog.IShowPicByIndexListener() {
            @Override
            public void onShowPicIndex(int index) {
                mImageView.setImageResource(imgs[index]);
            }
        });
        dialog.show();
    }

    private void setImageViewBcg(int index){
        mImageView.setImageResource(imgs[index]);
    }
}

Android进阶——自定义View之扩展系统Dialog_第4张图片

4、自主控制自定义Dialog

4.1、动态设置Dialog的显示位置

对话框默认显示于屏幕中心位置,但是我们可以通过Window对象来动态设置Dialog的位置

public void showDialog(View view){
        MyCostomDialog dialog = new  MyCostomDialog(MainActivity.this, "我来自Activity", R.style.myCustomdialog, new MyCostomDialog.IShowPicByIndexListener() {
            @Override
            public void onShowPicIndex(int index) {
                mImageView.setImageResource(imgs[index]);
            }
        });
        Window window=dialog.getWindow();//获取Window对象
        window.setGravity(Gravity.TOP|Gravity.LEFT);//设置显示位置
        dialog.show();
    }

Android进阶——自定义View之扩展系统Dialog_第5张图片

4.2、改变对话框的透明度

改变对话框的透明度也可以通过设置Window的alpha属性。

  Window window=dialog.getWindow();//先获取Window对象
        WindowManager.LayoutParams layoutParams=window.getAttributes();//再获取属性集
        layoutParams.alpha=0.6f;//设置alpha属性
        window.setAttributes(layoutParams);

Android进阶——自定义View之扩展系统Dialog_第6张图片

4.3、自主控制对话框的关闭状态

    public void showDialog(View view){
        MyCostomDialog dialog = new  MyCostomDialog(MainActivity.this, "我来自Activity", R.style.myCustomdialog, new MyCostomDialog.IShowPicByIndexListener() {
            @Override
            public void onShowPicIndex(int index) {
                mImageView.setImageResource(imgs[index]);
            }
        });
        Window window=dialog.getWindow();
        window.setGravity(Gravity.TOP | Gravity.LEFT);
        WindowManager.LayoutParams layoutParams=window.getAttributes();
        layoutParams.alpha=0.6f;
        window.setAttributes(layoutParams);
        try {
            Field field=dialog.getClass().getSuperclass().getDeclaredField("mShowing");
            field.setAccessible(true);
            try {
                field.set(dialog,false);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        dialog.show();
    }

你可能感兴趣的:(自定义dialog,自定义view,UI组件,扩展系统UI,扩展Dialog)