DialogFagmet是一个特殊的碎片经常被用作在活动中展示叠加的窗口,在其他内容之上。
经常被用作展示警告对话框,确认对话框,或者为了在同一个页面来提示信息。
DialogFragment现在是一种常见的做法,而之间使用Dialog被认为不正确。
创建一个DialogFragment的最简单方式是实现onCreateView
或者onCreateDialog
方法。前者是在整个对话的view的布局都是自定义的情况下使用的,而后者是只需要构建配置一个标准的Dialog类的情况下使用。
* 注意:所有的方法要求使用v4的包,而不是andorid.app
*
首先我们需要自定义一个Xml文件作为dialog的布局文件:fragment_edit_name.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/edit_name">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="@+id/lbl_your_name"
android:text="Your name"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/txt_your_name"
android:inputType="text"
android:imeOptions="actionDone"/>
LinearLayout>
然后开始定义碎片本身:
public class EditNameDialogFragment extends DialogFragment {
private EditText mEditText;
public EditNameDialogFragment() {
//要求空的构造方法
//不要加参数
//使用newInstance获得实例
}
public static EditNameDialogFragment newInstance(String title) {
EditNameDialogFragment frag = new EditNameDialogFragment();
Bundle args = new Bundle();
args.putString("title", title);
frag.setArguments(args);
return frag;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_edit_name, container);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//从biew中加载控件
mEditText = (EditText) view.findViewById(R.id.txt_your_name);
//从bundle中获取参数设置title
//getArguments获得碎片实例化时的参数,返回一个bundle参数
String title = getArguments().getString("title", "Enter name");
getDialog().setTitle(title);
//自动展示软键盘并且要求焦点
mEditText.requestFocus();
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}
}
在主活动中展示:
private void showEditDialog() {
FragmentManager fm = getSupportFragmentManager();
EditNameDialogFragment editNameDialogFragment = EditNameDialogFragment.newInstance("Some Title");
editNameDialogFragment.show(fm, "fragment_edit_name");
}
让我们看看怎么通过简单的自定义可用的Dialog对象构建一个dialog,
public class MyAlertDialogFragment extends DialogFragment {
public MyAlertDialogFragment() {
}
public static MyAlertDialogFragment newInstance(String title) {
MyAlertDialogFragment frag = new MyAlertDialogFragment();
Bundle args = new Bundle();
args.putString("title", title);
frag.setArguments(args);
return frag;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String title = getArguments().getString("title");
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setTitle(title);
alertDialogBuilder.setMessage("Are you sure");
alertDialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
return alertDialogBuilder.create();
}
}
对于所有碎片来说可以使用创建自定义监听器的方法向活动传递数据,需要:
- 定义一个包含传递数据给活动的方法的接口
- 建立一个view事件调用自定义的监听器通过方法传递数据
- 通过定义事件的触发条件在活动中实现接口
public class EditNameDialogFragment extends DialogFragment implements TextView.OnEditorActionListener {
private EditText mEditText;
//定义一个接口包含传递数据的方法
public interface EditNameDialogListener {
void onFinishEditDialog(String inputText);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_edit_name, container);
mEditText = (EditText) v.findViewById(R.id.txt_your_name);
//当done键摁下后建立一个回调
mEditText.setOnEditorActionListener(this);
return v;
}
//无论何时输入区域有动作时调用
//当前情况是done键触发
//要求软件盘
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (EditorInfo.IME_ACTION_DONE == actionId) {
//通过实现监听器来讲输入的文本返回
EditNameDialogListener listener = (EditNameDialogListener) getActivity();
listener.onFinishEditDialog(mEditText.getText().toString());
//关闭dialog
dismiss();
return true;
}
return false;
}
在主活动中重写在接口中定义的方法:
public class MainActivity extends AppCompatActivity implements EditNameDialogFragment.EditNameDialogListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showEditDialog();
}
private void showEditDialog() {
FragmentManager fm = getSupportFragmentManager();
//创建实例
EditNameDialogFragment editNameDialogFragment = EditNameDialogFragment.newInstance("Some Title");
editNameDialogFragment.show(fm, "fragment_edit_name");
}
@Override
public void onFinishEditDialog(String inputText) {
Toast.makeText(this, "hi"+ inputText, Toast.LENGTH_SHORT).show();
}
}
。。。
这要求我们改变相关的主要属性styels.xml
例如dialogTheme
和alertDialogTheme
如下所示res/values/styles.xml
:
-- In res/values/colors.xml -->
name="dark_blue">#180065
name="light_blue">#334ee9ff
name="medium_green">#3d853e
name="light_green">#3c2ae668
-- In res/values/styles.xml -->
-- Define your custom dialog theme here extending from base -->
-- Define your custom alert theme here extending from base -->
我们可以使用android:windowTitleStyle
来定义:
我们可以简单的从DialogFragment移除通过重写onCreateDialog
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
// request a window without the title
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
return dialog;
}
使用第三方库:
https://github.com/afollestad/material-dialogs
https://github.com/fengdai/AlertDialogPro/
https://github.com/drakeet/MaterialDialog