弹框在很多使用都使用到了,比如用户的提示,加载网络信息,弹出对话框,接下来去详细了解对话框。
当我们想要弹框与Activity进行交互的时候,我们应该怎么做呢?在该出使用了一个 DialogFragment, DialogFragment与Activity进行数据的交互。交互的方式就是回调接口的方式。
首先了解AlertDialog的基本用法。
android.support.v7.app.AlertDialog.Builder builder = new android.support.v7.app.AlertDialog.Builder(this);
builder.setIcon(R.mipmap.ic_launcher);//设置图标
builder.setTitle("Material Design Dialog");//设置标题
builder.setMessage("这是 android.support.v7.app.AlertDialog 中的样式"); //设置详细内容
builder.setNegativeButton("取消", null);//设置取消按钮 null为按钮的点击事件
builder.setPositiveButton("确定", null);//设置确定按钮 null为按钮的点击事件
AlertDialog loadDialog = builder.create();
loadDialog.show();//显示dialog
下图是显示的结果,其中少了图标,图标显示在标题的左边。
很多时候,需要自己设置其中的内容那么需要使用到该函数builder.setView();该函数用来加载自己设置的View.
View view = inflater.inflate(R.layout.layout_loading, null);
builder.setView(view);
这就加载了所需要的View.接下来的一个例子就是加载框。
给出加载框的布局文件loading.xml,在布局问价中有两个控件,ProgressBar与TextView,ProgressBar是显示加载圈圈的,TextView是需要设置的加载时显示的文字。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:gravity="center"
android:padding="10dp"
android:id="@+id/loading_view">
<ProgressBar
android:layout_width="80dp"
android:layout_height="80dp"
android:indeterminateTint="#B2B2B2"
android:indeterminateTintMode="src_atop"/>
<TextView
android:id="@+id/tv_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:textColor="#B2B2B2"
android:textSize="20sp"
android:typeface="serif"/>
</LinearLayout>
创建一个工具类。该工具类中创建了一个AlertDialog,创建这个工具类,是让其给一在其他的程序中使用。
public class DialogUtil {
private static DialogUtil _Instance = null;
private static AlertDialog dialog = null;
public static DialogUtil Instance() {
if (_Instance == null) {
_Instance = new DialogUtil();
}
return _Instance;
}
/**
* 显示加载对话框
* @param context
* @return
*/
public AlertDialog createLoadingDialog(Context context) {
return createLoadingDialog(context, null);
}
/**
* 显示加载对话框
* @param context
* @param msg
* @return
*/
public AlertDialog createLoadingDialog(Context context, String msg) {
AlertDialog loadingDialog = null;
if (dialog == null) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.layout_loading, null);
LinearLayout layout = (LinearLayout) view.findViewById(R.id.loading_view);
TextView mTextView = (TextView) view.findViewById(R.id.tv_loading);
if (msg != null) {
mTextView.setText(msg);
}
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setView(view);
loadingDialog = builder.create();
loadingDialog.setCanceledOnTouchOutside(false);
} else {
return dialog;
}
return loadingDialog;
}
}
对话框的加载和取消是调用两个方法,一个是Show方法,还有一个是dismiss方法。
/**
* 自定义加载对话框
*/
protected AlertDialog mLoadingDialog;
/**
* 显示加载对话框
*/
public void showLoading() {
if (mLoadingDialog == null) {
mLoadingDialog = DialogUtil.Instance().createLoadingDialog(this);
}
if (!mLoadingDialog.isShowing()) {
mLoadingDialog.show();
}
}
/**
* 取消加载对话框
*/
public void dismissLoading() {
if (mLoadingDialog.isShowing() && mLoadingDialog != null) {
mLoadingDialog.dismiss();
}
}
这就是一个加载框,使用到了AlertDialog,并且是加载布局文件,同时这个布局文件可以更换为不同的样式,根据需求来决定。如果布局文件中有三个按钮,并且三个按钮都有点击事件,那么可以这样做:
Button button = (Button)view.findViewById(R.id.show);
button.setOnclick(new OnclickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity3.this, "您点击取消按钮", Toast.LENGTH_SHORT).show();
}
})
还有几个方法需要介绍:
setMultiChoiceItems(),显示一组多选框
第一个参数为列表项的文本数组,第二个参数为列表项默认情况下的选中状态,为空则都不选中,第三个是列表项的监听器类。在使用这个方法的时候如果同时使用了setMessage方法会导致此方法无效,而只显示setMessage的内容。 如:
builder.setMultiChoiceItems(new String[]{"233333", "hahahaha"}, null, null);
![]()
![]()
setSingleChoiceItems(),显示一组单选框
第一个参数为列表项的文本数组,第二个参数为列表项默认情况下的选中状态,为空则都不选中,第三个是列表项的监听器类。
在使用这个方法的时候如果同时使用了setMessage方法会导致此方法无效,而只显示setMessage的内容。
new AlertDialog.Builder(this).setTitle("单选框").setIcon(
android.R.drawable.ic_dialog_info).setSingleChoiceItems(
new String[] { "Item1", "Item2" }, 0,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).setNegativeButton("取消", null).show();
setItems
第一个参数为列表项的文本数组,第二个参数为列表项的监听器类。在使用这个方法的时候如果同时使用了setMessage方法会导致此方法无效,而只显示setMessage的内容。 如:
builder.setItems(new String[]{"Item1", "Item2"}, null);
移动位置
有时候,我们需要设置它的位置,默认是设置为屏幕中心的。
下面的代码是移动弹框的位置的
AlertDialog alertDialog = builder.create();
alertDialog.setCanceledOnTouchOutside(false); //设置点击其他地方不让其消失
Window mWindow = alertDialog.getWindow();
WindowManager.LayoutParams lp = mWindow.getAttributes();
// 透明度的范围为:0.0f-1.0f;0.0f表示完全透明,1.0f表示完全不透明(系统默认的就是这个)。
lp.alpha = 0.35f;
//设置对话框在屏幕的底部显示,当然还有上下左右,任意位置
//mWindow.setGravity(Gravity.LEFT);
// mWindow.setGravity(Gravity.BOTTOM);
/*
*
* 这里是设置偏移量,这里的x,y并不是相对于屏幕的绝对坐标,而是相对于对话框在中心位置(默认的对话框一般显示在屏幕的中心)而言的
* */
lp.x = -20;// 设置水平偏移量
lp.y = 300;// 设置竖直偏移量
// 设置Window的属性
mWindow.setAttributes(lp);
当我们想要弹框与Activity进行交互的时候,我们应该怎么做呢?在该出使用了一个 DialogFragment, DialogFragment与Activity进行数据的交互。交互的方式就是回调接口的方式。
从dialog传递数据给Activity,可以使用“fragment interface pattern”的方式,下面通过一个改造上面的登录框来展示这种模式。
改动比较小,直接贴代码了:
package com.example.zhy_dialogfragment;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
public class LoginDialogFragment extends DialogFragment
{
private EditText mUsername;
private EditText mPassword;
public interface LoginInputListener
{
void onLoginInputComplete(String username, String password);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.fragment_login_dialog, null);
mUsername = (EditText) view.findViewById(R.id.id_txt_username);
mPassword = (EditText) view.findViewById(R.id.id_txt_password);
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(view)
// Add action buttons
.setPositiveButton("Sign in",
new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int id)
{
LoginInputListener listener = (LoginInputListener) getActivity();
listener.onLoginInputComplete(mUsername
.getText().toString(), mPassword
.getText().toString());
}
}).setNegativeButton("Cancel", null);
return builder.create();
}
}
拿到username和password的引用,在点击登录的时候,把activity强转为我们自定义的接口:LoginInputListener,然后将用户输入的数据返回。
MainActivity中需要实现我们的接口LoginInputListener,实现我们的方法,就可以实现当用户点击登陆时,获得我们的帐号密码了:
package com.example.zhy_dialogfragment;
import com.example.zhy_dialogfragment.LoginDialogFragment.LoginInputListener;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity implements LoginInputListener
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void showLoginDialog(View view)
{
LoginDialogFragment dialog = new LoginDialogFragment();
dialog.show(getFragmentManager(), "loginDialog");
}
@Override
public void onLoginInputComplete(String username, String password)
{
Toast.makeText(this, "帐号:" + username + ", 密码 :" + password,
Toast.LENGTH_SHORT).show();
}
}