Android 自定义DialogFragment 以及设置宽高

         DialogFragment  的特点是具有dialog 的 效果,同时又可以拥有Fragment 的生命周期,因此我们可以像管理Fragment 一样管理DialogFragment 。在 Android  中我们已经Dialog  类了,为什么还要增加一个DialogFragment 。在使用过程中DialogFragment 有事什么样子的呢,我们通过一个demo  来介绍。

         设计一个从底部弹出的弹出框,同时 弹出框中的包汗tab页。那么我们需要在弹出框布局中加入 Viewpager+ Fragment 的设计。对于复杂的 dialog 我们可以用 DialogFragment 来做。

效果如图:

    fragment 布局文件

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <LinearLayout
            android:id="@+id/contentView"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:orientation="vertical"
            android:layout_marginLeft="10dp"
            android:layout_marginBottom="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="150dp"
            android:background="@drawable/bg_list"
            android:layout_alignParentBottom="true"

            >
            <com.ogaclejapan.smarttablayout.SmartTabLayout
                android:id="@+id/vp_tab"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:layout_gravity="center"
                android:background="@color/transparent"
                app:stl_indicatorAlwaysInCenter="false"
                app:stl_indicatorWithoutPadding="false"
                app:stl_indicatorInFront="false"
                app:stl_indicatorInterpolation="linear"
                app:stl_indicatorGravity="bottom"
                app:stl_indicatorColor="@color/colorAccent"
                app:stl_indicatorThickness="2dp"
                app:stl_indicatorWidth="auto"
                app:stl_indicatorCornerRadius="1px"
                app:stl_overlineColor="#4D000000"
                app:stl_overlineThickness="0dp"
                app:stl_underlineColor="@color/line"
                app:stl_underlineThickness="0dp"
                app:stl_dividerColor="@color/line"
                app:stl_dividerThickness="0dp"
                app:stl_defaultTabBackground="@android:color/transparent"
                app:stl_defaultTabTextAllCaps="false"
                app:stl_defaultTabTextColor="#ffffff"
                app:stl_defaultTabTextSize="12sp"
                app:stl_defaultTabTextMinWidth="0dp"
                app:stl_distributeEvenly="true"
                app:stl_clickable="true"
                app:stl_titleOffset="24dp"
                app:stl_drawDecorationAfterTab="false"
                />
            <TextView
                android:layout_width="match_parent"
                android:layout_height="1px"
                android:background="@color/line"
                />
            <android.support.v4.view.ViewPager
                android:id="@+id/vp"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                />

        </LinearLayout>


    </RelativeLayout>

fragment   Java文件



/**
 * @author by nate_fu on 2018/9/13.
 * @version vision 1.0
 * @Email: fuyonghui@zjhcsoft.com
 */
public class MyDialogFragment extends DialogFragment {
    private View view;
    private ViewPager viewPager;
    private SmartTabLayout vpTab;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CustomDialog);
    }



    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_dialog,container,false);
        initViewpage();
        return view;


    }



    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);


    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Window window = getDialog().getWindow();
        getDialog().setCanceledOnTouchOutside(true);
        window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        window.setWindowAnimations(R.style.dialogWindowAnim);
        WindowManager.LayoutParams wlp = window.getAttributes();
        wlp.dimAmount=0f;
        wlp.width = WindowManager.LayoutParams.MATCH_PARENT ;
        wlp.height =WindowManager.LayoutParams.MATCH_PARENT ;
      

        window.setAttributes(wlp);
    }

    private  void  initViewpage(){
        FragmentPagerItemAdapter adapter = new FragmentPagerItemAdapter(
                getChildFragmentManager(), FragmentPagerItems.with(getActivity())
                .add("XX",InfoFragment.class)
                .add("XX",InfoFragment.class)
                .add("XX",InfoFragment.class)
                .add("XX",InfoFragment.class)
                .add("XX",InfoFragment.class)
                .create());

        viewPager =  (ViewPager)view.findViewById(R.id.vp);
        viewPager.setAdapter(adapter);
        vpTab =(SmartTabLayout)view.findViewById(R.id.vp_tab);
        vpTab.setViewPager( viewPager);

    }



    @Override
    public void show(FragmentManager manager, String tag) {
        super.show(manager, tag);
    }

}

在MyDialogFragment 类中。我们在onCreate()方法中 执行了setStyle()方法 来设置dialog 的样式。为什么要在这里执行这个方法。我们可以从DialogFragment 的源码中找找原因

setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CustomDialog);
 @Override
    public LayoutInflater onGetLayoutInflater(Bundle savedInstanceState) {
        if (!mShowsDialog) {
            return super.onGetLayoutInflater(savedInstanceState);
        }

        mDialog = onCreateDialog(savedInstanceState);

        if (mDialog != null) {
            setupDialog(mDialog, mStyle);

            return (LayoutInflater) mDialog.getContext().getSystemService(
                    Context.LAYOUT_INFLATER_SERVICE);
        }
        return (LayoutInflater) mHost.getContext().getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
    }

在 DialogFragmet 类中有一个 onGetLayoutInflater()方法。其中 创建了Dialog 对象,同时 在setupDiaglog中设置了 style  

所以我们必须在 onGetLayoutInflater()方法前设置style  。 

  f.mContainer = container;
                            f.mView = f.performCreateView(f.performGetLayoutInflater(
                                    f.mSavedFragmentState), container, f.mSavedFragmentState);

这是在FragmentManager 类中找到的代码,可以看到  getLayoutInflater 在 CreateView  之前,所以我们不能再 onCreateView()中设置是style  而在Fragment的生命周期 中 onCreate()在 onCreateView()之前调用。

接下来我们就是要设置我们要的dialog 的宽高 了。默认创建的 dialog  会在中间位置,两边会留边。而我们习惯在 onCreateView() 中 

Window window = getDialog().getWindow();
getDialog().setCanceledOnTouchOutside(true);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.setWindowAnimations(R.style.dialogWindowAnim);
WindowManager.LayoutParams wlp = window.getAttributes();
wlp.dimAmount=0f;
wlp.width = WindowManager.LayoutParams.MATCH_PARENT ;
wlp.height =WindowManager.LayoutParams.MATCH_PARENT ;
window.setAttributes(wlp);

直接给window  设置宽高。因为在我们自定义 Dialog 是 ,new  Dialog()之后我们就是这么操作的,发现在Dialog 的时候没什么问题,可是到了这里却没有效果了,这是为什么呢。我们还是继续去源码中查看

 public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        if (!mShowsDialog) {
            return;
        }

        View view = getView();
        if (view != null) {
            if (view.getParent() != null) {
                throw new IllegalStateException(
                        "DialogFragment can not be attached to a container view");
            }
            mDialog.setContentView(view);
        }

在DialogFragment 中的 onActivityCreated  中 我们发现, mDialog.setContentView 这行代码,我们知道Android 中实现window 这个类的就是PhoneWindow 类。而 我们平时在onCreate 方法中调用的setContentView 最终调用的是 PhoneWindow 中的setContentView 方法

PhoneWindow.java 

  @Override    
public void setContentView(int layoutResID) {        
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mLayoutInflater.inflate(layoutResID, mContentParent);
        final Callback cb = getCallback();
        if (cb != null) {
            cb.onContentChanged();
        }
    }

我们看到了 其中执行了installDecor();

private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
            mDecor = generateDecor(-1);
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        } else {
            mDecor.setWindow(this);
        }
       
}

这里我们看到当mDecor为null  的时候 则调用generateDecor方法完成DecorView的初始化。

而我们在结合Dialog 类来看。 

 @Override
    public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
        if (mDecor != null) {
            mWindowManager.updateViewLayout(mDecor, params);
        }
    }

当我们 给window设置Attributes 时候会回调 onWindowAttributesChanged 方法,而 在这个方法中,如果 mDecor 为null 的话是不会update我们的参数的。所以从上面我们知道 在 DialogFragment 中,dialog 窗口 被创建是在 onActivityCreate中,在此DecorView才被实例化。而我们要设置宽高的参数,必须在 DecorView实例化之后,不然是没有效果的。

以上是我的分析,如果有其他见解欢迎留言讨论。

demo 下载地址

https://download.csdn.net/download/u010324235/10698524

https://github.com/fyhsgsgssg/DialogFragment

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个完整的例子: ```java public class CustomDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle("Title") .setMessage("Message") .setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // do something } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // do something } }); AlertDialog dialog = builder.create(); // 设置 Dialog 的 margin Window window = dialog.getWindow(); WindowManager.LayoutParams layoutParams = window.getAttributes(); layoutParams.gravity = Gravity.CENTER; layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; layoutParams.x = getResources().getDimensionPixelSize(R.dimen.dialog_margin_horizontal); layoutParams.y = getResources().getDimensionPixelSize(R.dimen.dialog_margin_vertical); window.setAttributes(layoutParams); return dialog; } } ``` 在这个例子中,我们创建了一个名为 `CustomDialogFragment` 的自定义对话框。在对话框的 `onCreateDialog` 方法中,我们创建了一个 `AlertDialog.Builder` 对象,并设置了对话框的标题、消息和按钮。然后,我们通过 `builder.create()` 方法创建了一个 `AlertDialog` 对象,并将其返回。 接着,我们获取了对话框的 `Window` 对象,并通过 `window.getAttributes()` 方法获取到对话框的布局参数,即 `WindowManager.LayoutParams` 对象。我们在这个对象中设置了对话框的位置、度、度以及 margin 值。最后,我们通过 `window.setAttributes()` 方法将这些布局参数应用到对话框中。 需要注意的是,在设置 margin 值时,我们使用了资源文件 `R.dimen.dialog_margin_horizontal` 和 `R.dimen.dialog_margin_vertical`。这两个资源文件分别定义了对话框的水平和垂直 margin 值,可以在 `res/values/dimens.xml` 文件中定义,例如: ```xml <resources> <dimen name="dialog_margin_horizontal">16dp</dimen> <dimen name="dialog_margin_vertical">16dp</dimen> </resources> ``` 这样,我们就完成了对话框的创建和 margin 值的设置

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值