您的位置:首页 > 移动开发 > Android开发

android 对话框(Dialog)使用(2)

2017-06-07 15:40 483 查看
参考:

android 对话框(Dialog)使用http://blog.csdn.net/u012005313/article/details/58153917

之前总结了基本的关于
dialog
的使用,经过一段时间的学习,对
dialog
的使用又有了一些新的体会。下面加入一些新的操作,同时完善之前的内容。

主要内容

自定义对话框 - 登录界面的实现

设置
activity
为对话框样式


material-dialogs
- 开源对话框库使用


DatePickerDialog
TimePickerDialog
使用


WheelView
- 开源滚轮控件使用


DialogFragment
使用


ProgressDialog
使用


show
hide
dismiss
使用


代码链接

自定义对话框 - 登录界面的实现

dialog
可实现自定义界面,比如登录对话框

首先设置登录界面 -
dialog_login.xml
:用户名和密码输入框,以及清除按钮和登录按钮

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

<TableLayout
android:id="@+id/dl_table"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="1"
android:visibility="visible"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">

<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:layout_width="60dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="用户" />

<EditText
android:id="@+id/et_user"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</TableRow>

<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:layout_width="60dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="密码" />

<EditText
android:id="@+id/et_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword" />

</TableRow>

</TableLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<Button
android:id="@+id/btn_clear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/btn_clear" />

<Button
android:id="@+id/btn_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/btn_login" />

</LinearLayout>

</LinearLayout>


将该界面加载生成
View
对象:

View view = View.inflate(this, R.layout.dialog_login, null);


Note:
View.inflate
详细内容

/**
* Inflate a view from an XML resource.  This convenience method wraps the {@link
* LayoutInflater} class, which provides a full range of options for view inflation.
*
* @param context The Context object for your activity or application.
* @param resource The resource ID to inflate
* @param root A view group that will be the parent.  Used to properly inflate the
* layout_* parameters.
* @see LayoutInflater
*/
public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
LayoutInflater factory = LayoutInflater.from(context);
return factory.inflate(resource, root);
}


生成
dialog
对象,将自定义视图加载进去:

AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setView(view);


显示该登录对话框:

builder.show();


Note:调用
builder.show
等同于先创建
AlertDialog
,再进行显示

/**
* Creates an {@link AlertDialog} with the arguments supplied to this
* builder and immediately displays the dialog.
* <p>
* Calling this method is functionally identical to:
* <pre>
*     AlertDialog dialog = builder.create();
*     dialog.show();
* </pre>
*/
public AlertDialog show() {
final AlertDialog dialog = create();
dialog.show();
return dialog;
}




这样就完成了登录对话框的创建,如果想要进一步获取用户输入的信息,点击按钮可以进行操作,增加如下代码:

final EditText etUser = (EditText) view.findViewById(R.id.et_user);
final EditText etPassword = (EditText) view.findViewById(R.id.et_password);

Button btnClear = (Button) view.findViewById(R.id.btn_clear);
btnClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
etUser.setText(null);
etPassword.setText(null);
}
});

Button btnLogin = (Button) view.findViewById(R.id.btn_login);
btnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String user = etUser.getText().toString();
String password = etPassword.getText().toString();

Log.e(TAG, "onClick: user = " + user + " password = " + password);
Toast.makeText(getApplicationContext(), "user = " + user + " password = " + password, Toast.LENGTH_SHORT).show();
}
});


Note:如果想要符合
MD
规范,可以使用
AlertDialog
自带的按钮,还可以使用自带的标题栏


设置
activity
为对话框样式

继续上面的登录界面,现在已经实现了登录对话框,此时并不需要
activity
背景界面,可以设置
activity
主题为
dialog
,消去空白的的登录界面。设置方式 - 修改
AndroidManifest.xml
中对应
activity
,设置主题为
dialog
样式:

<activity
android:name=".custom.CustomActivity"
android:theme="@style/Theme.AppCompat.Light.Dialog.Alert"></activity>




但是还得解决登录框取消后,仍会出现背景的问题



可以使用
DialogInterface.OnKeyListener
接口:

/**
* Interface definition for a callback to be invoked when a key event is
* dispatched to this dialog. The callback will be invoked before the key
* event is given to the dialog.
*/
interface OnKeyListener {
/**
* Called when a key is dispatched to a dialog. This allows listeners to
* get a chance to respond before the dialog.
*
* @param dialog The dialog the key has been dispatched to.
* @param keyCode The code for the physical key that was pressed
* @param event The KeyEvent object containing full information about
*            the event.
* @return True if the listener has consumed the event, false otherwise.
*/
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event);
}


具体思路:
dialog
注册此接口,出现点击操作时,判断是否是返回键。若是,则关闭整个
activity


AlertDialog alertDialog = builder.create();

DialogInterface.OnKeyListener onKeyListener = new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
finish();

return true;
}
return false;
}
};

alertDialog.setOnKeyListener(onKeyListener);


同时还要设置点击屏幕对话框外的区域不结束
dialog


alertDialog.setCancelable(false);


完整代码如下:

View view = View.inflate(this, R.layout.dialog_login, null);
AlertDialog.Builder builder = new AlertDialog.Builder(this) .setView(view);
final EditText etUser = (EditText) view.findViewById(R.id.et_user); final EditText etPassword = (EditText) view.findViewById(R.id.et_password); Button btnClear = (Button) view.findViewById(R.id.btn_clear); btnClear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { etUser.setText(null); etPassword.setText(null); } }); Button btnLogin = (Button) view.findViewById(R.id.btn_login); btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String user = etUser.getText().toString(); String password = etPassword.getText().toString(); Log.e(TAG, "onClick: user = " + user + " password = " + password); Toast.makeText(getApplicationContext(), "user = " + user + " password = " + password, Toast.LENGTH_SHORT).show(); } });
AlertDialog alertDialog = builder.create(); DialogInterface.OnKeyListener onKeyListener = new DialogInterface.OnKeyListener() { @Override public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { finish(); return true; } return false; } }; alertDialog.setOnKeyListener(onKeyListener);
alertDialog.setCancelable(false);
alertDialog.show();


参考:

AlertDialog点击按钮后对话框不消失的处理方法

此时,不管是否有输入,点击按钮后对话框自动消失,可通过设置按钮点击事件实现手动决定对话框是否消失。

实现方法:在对话框初始化阶段,设置按钮点击事件为
null
;显示对话框后,设置按钮点击事件,即可手动决定是否
dismiss
对话框

修改后代码如下:

View view = View.inflate(this, R.layout.dialog_login, null);
final EditText etUser = (EditText) view.findViewById(R.id.et_user);
final EditText etPassword = (EditText) view.findViewById(R.id.et_password);

AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setTitle(getResources().getString(R.string.app_name))
.setView(view)
.setPositiveButton(getResources().getString(R.string.btn_login), null)
.setNegativeButton(getResources().getString(R.string.btn_clear), null);

AlertDialog alertDialog = builder.create(); DialogInterface.OnKeyListener onKeyListener = new DialogInterface.OnKeyListener() { @Override public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { finish(); return true; } return false; } }; alertDialog.setOnKeyListener(onKeyListener);
alertDialog.setCancelable(false);
alertDialog.show();

alertDialog.getButton(Dialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String user = etUser.getText().toString();
String password = etPassword.getText().toString();

Log.e(TAG, "onClick: user = " + user + " password = " + password);
Toast.makeText(getApplicationContext(), "user = " + user + " password = " + password, Toast.LENGTH_SHORT).show();
}
});

alertDialog.getButton(Dialog.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
etUser.setText(null);
etPassword.setText(null);
}
});




material-dialogs
- 开源对话框库使用

一个开源的,符合
MD
设计规范的对话框

github:material-dialogs

使用方式和
dialog
类似

DatePickerDialog
TimePickerDialog
使用

android
内置了日期选择对话框和时间选择对话框组件

DatePickerDialog
使用

获取当前年,月,日:

Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);


创建
DatePickerDialog
并显示:

DatePickerDialog datePickerDialog = new DatePickerDialog(this, this, year, month, day);

datePickerDialog.show();


另外,需要设置回调接口
DatePickerDialog.OnDateSetListener


完整代码如下:

public class DatePickerActivity extends AppCompatActivity implements DatePickerDialog.OnDateSetListener {
private static final String TAG = DatePickerActivity.class.getSimpleName();

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

Calendar calendar = Calendar.getInstance(); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH); int day = calendar.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(this, this, year, month, day); datePickerDialog.show();}

@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
Log.e(TAG, "onDateSet: year = " + year + " month = " + month + " day = " + dayOfMonth);
}
}




TimePickerDialog
使用

获取当前时间:

Calendar calendar = Calendar.getInstance();

int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);


创建
TimePickerDialog
并显示:

TimePickerDialog timePickerDialog = new TimePickerDialog(this, this, hour, minute, true);

timePickerDialog.show();


另外,需要设置回调接口
TimePickerDialog.OnDateSetListener


完整代码如下:

public class TimePickerActivity extends AppCompatActivity
implements TimePickerDialog.OnTimeSetListener {
private static final String TAG = TimePickerDialog.class.getSimpleName();

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

Calendar calendar = Calendar.getInstance(); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE);
TimePickerDialog timePickerDialog = new TimePickerDialog(this, this, hour, minute, true); timePickerDialog.show();}

@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Log.e(TAG, "onTimeSet: h = " + hourOfDay + " m = " + minute);
}
}




WheelView
- 开源滚轮控件使用

android
没有滚轮控件,不过网上已经有了很多的开源滚轮控件,参考了其中两个

参考

android-wheel

venshine/WheelView

有时间详细学习一下

DialogFragment
使用

android
推荐使用
DialogFragment
用作对话框的容器,这样可保证能够正确处理生命周期事件,同时有利于复用

实现最简单的对话框使用

首先,扩展
DialogFragment
中的
onCreateDilog
方法,创建
AlertDialog
对象并返回:

public class MyDialogFragment extends DialogFragment {

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
//        return super.onCreateDialog(savedInstanceState);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setTitle("MyDialogFragment")
.setMessage("DialogFragment")
.setPositiveButton("OK", null)
.setNegativeButton("Cancel", null);

return builder.create();
}
}


其次,在
Activity
中创建
MyDialogFragment
实例,并调用
show
方法即可显示对话框:

MyDialogFragment myDialogFragment = new MyDialogFragment();
myDialogFragment.show(getSupportFragmentManager(), "myDialogFragment");


Note:
show
方法第二个参数是一个标识符



将事件传递回对话框的宿主

有时候需要将对话框获取到的数据,比如登录对话框中的用户名,密码,传递回
activity
中进行下一步的操作。
DialogFragment
并没有提供类似的功能,需要自定义相应的接口,进行下一步的操作

首先,在
MyDialogFragment.java
中定义接口
MyDialogListener
,包含接口函数
onDialogClick
,用于按钮的回调:

public interface MyDialogListener {
void onDialogClick(String content, int type);
}


MyDialogFragment.java
中定义该接口,同时在
onAttach
函数中实例化该接口:

private MyDialogListener myDialogListener;

@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
// Instantiate the NoticeDialogListener so we can send events to the host
myDialogListener = (MyDialogListener) context;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(context.toString()
+ " must implement MyDialogListener");
}
}


onCreateDialog
函数中,创建
AlertDialog
过程中,设置按钮的点击事件,调用接口函数,点击
user
按钮,则返回用户名;点击
password
按钮,则返回密码:

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {

View view = View.inflate(getContext(), R.layout.dialog_login, null);

final EditText etUser = (EditText) view.findViewById(R.id.et_user);
final EditText etPassword = (EditText) view.findViewById(R.id.et_password);

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setTitle("MyDialogFragment")
.setView(view)
.setPositiveButton("user", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
myDialogListener.onDialogClick(etUser.getText().toString(), 1);
}
})
.setNegativeButton("password", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
myDialogListener.onDialogClick(etPassword.getText().toString(), 2);
}
});

return builder.create();
}


在宿主
activity
中绑定该接口,实现接口函数功能:

public class DialogFragmentActivity extends AppCompatActivity implements MyDialogFragment.MyDialogListener {

private TextView textView;

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

textView = (TextView) findViewById(R.id.text);

MyDialogFragment myDialogFragment = new MyDialogFragment(); myDialogFragment.show(getSupportFragmentManager(), "myDialogFragment");}

@Override
public void onDialogClick(String content, int type) {
if (type == 1) {
textView.setText("user: " + content);
} else {
textView.setText("password: " + content);
}
}
}


setCanceledOnTouchOutside
setCancelable
使用

DialogFragment
没有内置函数
setCanceledOnTouchOutside
,可以在创建
AlertDialog
时设置该函数:

AlertDialog alertDialog = builder.create();

alertDialog.setCanceledOnTouchOutside(false);


不应该直接调用
AlertDialog.setCancelable
方法,而是使用
DialogFragment
内置函数
setCancelable


myDialogFragment.setCancelable(false);


Note:可通过调用
isCancelable
获取
DialogFragment
状态

取消
DialogFragment

调用
DialogFragment
内置函数
dismiss
即可:

@Override
protected void onDestroy() {
super.onDestroy();
myDialogFragment.dismiss();
}


ProgressDialog
使用

android
系统自带了一个进度条对话框 -
ProgressDialog


在进行信息查询,数据上传时,可使用该对话框提示用户等待。

参考

ProgressDialog

创建
ProgressDialog
并显示

ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Hello World");
progressDialog.show();




Note:在程序中可能需要多次进行数据操作,可以创建一个
ProgressDialog
实例并保留下来

show
hide
dismiss
使用

创建对话框实例后,需要调用
show
方法显示该对话框

如果需要多次使用
ProgressDialog
,只需要创建一个
ProgressDialog
实例,在不需要使用时调用
hide
函数进行隐藏:

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


最后在结束时,可以调用
dismiss
函数将对话框清除:

/**
* Dismiss this dialog, removing it from the screen. This method can be
* invoked safely from any thread.  Note that you should not override this
* method to do cleanup when the dialog is dismissed, instead implement
* that in {@link #onStop}.
*/
@Override
public void dismiss() {
if (Looper.myLooper() == mHandler.getLooper()) {
dismissDialog();
} else {
mHandler.post(mDismissAction);
}
}


代码链接

OSChina:https://git.oschina.net/zjZSTU/dialogdemo.git
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: