support.v4.app.DialogFragment使用问题总结

因app需求问题,需要实现如图这种dialog

看到这里,你可能会说如此easy的事情,还说什么! 那么继续往下看!

场景1:

import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;

public class AlertDialogFragmentActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_alert_dialog_fragment);

        findViewById(R.id.show).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showDialog();
            }
        });
    }

    public static class MyAlertDialogFragment extends DialogFragment {
        public static MyAlertDialogFragment newInstance(int title) {
            MyAlertDialogFragment frag = new MyAlertDialogFragment();
            Bundle args = new Bundle();
            args.putInt("title", title);
            frag.setArguments(args);
            return frag;
        }

        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            int title = getArguments().getInt("title");
            // AlertDialog 的内容区
            View contentView = LayoutInflater.from(getActivity()).inflate(R.layout.basic_dialog_fragment, null);
            return new AlertDialog.Builder(getActivity())
                    .setIcon(R.drawable.ic_about)
                    .setTitle(title)
                    .setView(contentView)
                    .setPositiveButton("ok", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    })
                    .setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    })
                    .create();
        }

    }
    void showDialog() {
        DialogFragment newFragment = MyAlertDialogFragment.newInstance(R.string.two_buttons_title);
        newFragment.show(getSupportFragmentManager(), "dialog");
    }
}

实际效果图成了这样

title区的内容不是纵横向居中的,button区完全走样右对齐了,如上图所示,只有绿色内容区是自定义内容,(title和button样式都是Android内置)

这是什么原因造成的?

这是因为当前这个AlertDialogFragmentActivity的theme属性的原因,它继承自AppCompatActivity要求使用 Theme.AppCompat.xxx 系列theme

代码中(AppCompatActivity,DialogFragment,AlertDialog)都是support library中的类,这些的类是配套使用的,你不能在Activity中直接使用support library中的DialogFragment和AlertDialog

尝试在AndroidManifest.xml中将AppCompatActivity的android:theme属性改成"@android:style/Theme.Holo"等,后续得到一个以下异常

Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

Theme.AppCompat.xxx 系列theme可以用于非support library包中的类,反过来Theme.Holo.xxx 或者 Theme.Light.xxx 等系列则无法用于support library包中的类

尝试修改 MyAlertDialogFragment的onCreateDialog 中的AlertDialog.Builder()代码

new AlertDialog.Builder(getActivity(),android.R.style.Theme_Holo_Dialog)

得到的效果图如下,反而更差

场景2:

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;

public class AlertDialogFragmentActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_alert_dialog_fragment);

        findViewById(R.id.show).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showDialog();
            }
        });
    }

    public static class MyAlertDialogFragment extends DialogFragment {
        public static MyAlertDialogFragment newInstance(int title) {
            MyAlertDialogFragment frag = new MyAlertDialogFragment();
            Bundle args = new Bundle();
            args.putInt("title", title);
            frag.setArguments(args);
            return frag;
        }

        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            int title = getArguments().getInt("title");
            // AlertDialog 的内容区
            View contentView = LayoutInflater.from(getActivity()).inflate(R.layout.basic_dialog_fragment, null);
            return new AlertDialog.Builder(getActivity())
                    .setIcon(R.drawable.ic_about)
                    .setTitle(title)
                    .setView(contentView)
                    .setPositiveButton("ok", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    })
                    .setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    })
                    .create();
        }

    }
    void showDialog() {
        DialogFragment newFragment = MyAlertDialogFragment.newInstance(R.string.two_buttons_title);
        newFragment.show(getFragmentManager(), "dialog");
    }
}

得到的效果图基本理想:

场景2中没有使用support library中类,而且Theme.AppCompat.xxx系列theme可以兼容低版本API,但是你的App的最小API也要11以上。

鉴于以上原因,最好自定义Dialog的内容区(在你自定义时,模仿将title和button都定义到你的布局中),然后不设置Dialog的title,button属性,只调用AlertDialog.Builder#setView(view),或者Dialog#setContentView(View view)

时间: 2024-12-08 08:32:32

support.v4.app.DialogFragment使用问题总结的相关文章

[转]android.support.v4.app.Fragment和android.app.Fragment区别

1.最低支持版本不同 android.app.Fragment 兼容的最低版本是android:minSdkVersion="11" 即3.0版 android.support.v4.app.Fragment 兼容的最低版本是android:minSdkVersion="4" 即1.6版 2.需要导jar包 fragment android.support.v4.app.Fragment 需要引入包android-support-v4.jar 3.在Activity

Attempt to write to field 'android.support.v4.app.FragmentManagerImpl android.support.v4.app.Fragment.mFragmentManager' on a null object reference

E/AndroidRuntime﹕ FATAL EXCEPTION: mainProcess: org.example.magnusluca.drawertestapp, PID: 3624java.lang.NullPointerException: Attempt to write to field 'android.support.v4.app.FragmentManagerImpl android.support.v4.app.Fragment.mFragmentManager' on

Android Studio不识别support.v4.app.FragmentTabHost的问题。

用Android Studio实现底部标签页功能,同样的代码在Eclipse里面是没有问题的,现在在AS里面预览的时候总是报错:Exception raised during rendering: No tab known for tag null XML源码如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.andr

安卓开发错误:The type android.support.v4.app.TaskStackBuilder$SupportParentable cannot be resolved.

今天在使用低版本下的ActionBar,在继承ActionBarActivity时报了"The type Android.support.v4.app.TaskStackBuilder$SupportParentable cannot be resolved. It is indirectly referenced from required .class files"错误,网上查了很久终于解决了. 问题根源:因为在复制项目的jar包时,把Eclipse下自带的android-supp

java.lang.ClassCastException:fragment cannot be cast to android.support.v4.app.Fragment

已启动APP后台就报了这个错误! java.lang.ClassCastException:fragment cannot be cast to android.support.v4.app.Fragment Java.lang.classcastexception:片段不能被转换为android.support.v4.app.fragment 原因是因为在使用继承Fragment的时候 导错包了:import android.support.v4.Fragment; 正确的包:import a

android.support.v4.app.Fragment 和 android.app.Fragment区别

今天在公司遇到一个android.app.Fragment 和android.support.v4.app.Fragment 的问题. (1)android.app.Fragment:兼容的最低版本是android:minSdkVersion="11"因此你的应用不能兼容3.0以下的应用. 可以使用<fragment>标签的,这点很重要,如果是用android.support.v4.app.Fragment的话,是不能是用<fragment>标签的,会抛出and

cannot be cast to android.support.v4.app.Fragment

android.app.Fragment as stated in the imports. Change the import to android.support.v4.app.Fragment

android.app.FragmentManager 与 android.support.v4.app.FragmentManager带来的若干Error

Fragment是activity的界面中的一部分或一种行为.你能够把多个Fragment们组合到一个activity中来创建一个多面界面而且你能够在多个activity中重用一个Fragment.你能够把Fragment觉得模块化的一段activity,它具有自己的生命周期,接收它自己的事件.并能够在activity执行时被加入或删除. 一个好的帖子:http://my.oschina.net/u/270164/blog/85347. 使用Fragment的包为android.app.Frag

app:transformClassesWithJarMergingForDebug uplicate entry: android/support/v4/app/BackStackState$1.class

.Execution failed for task ':app:transformClassesWithJarMergingForDebug'.> com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: android/support/v4/app/BackStackState$1.class 原因:在所添加的jar包或aar包中也引用了support-V4