本文分析Dialog的原理,其用到的设计模式,其各种子类,及在Activity中的使用。Toast、Log跟Dialog一样都有提示的功能,所以放一起分析。
1、Dialog实现了4个接口
1) android.content.DialogInterface
包含几个常量,cancel和dismiss方法,
6个嵌套接口OnCancelListener,OnDismissListener,OnShowListener,OnClickListener,
OnMultiChoiceClickListener,OnKeyListener。
2) android.view.Window.Callback
3) android.view.KeyEvent.Callback
4) android.view.View.OnCreateContextMenuListener
2、AlertDialog实现
new AlertDialog.Builder(this)
.setTitle("very good")
.create()//实例化AlertDialog
.show();
上面AlertDialog的实现用了建造者模式。
AlertDialog、AlertDialog.Builder分别适配了com.android.internal.app.AlertController和AlertController.AlertParams,用了对象的适配器模式。
final String[] items = {"I", "II", "III", "aVR", "aVL", "aVF", "V1", "V2", "V3", "V4", "V5", "V6"};
final SharedPreferences sp = getContext().getApplicationContext().getSharedPreferences("ecg12", Context.MODE_PRIVATE);
DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
//每次点击列表项将设置值保留
int mWhich;
@Override
public void onClick(DialogInterface dialog, int which) {
//-1,-2,-3不会和index发生冲突
if(which==DialogInterface.BUTTON_POSITIVE){
sp.edit().putInt("ecg12_index", mWhich).apply();
dialog.dismiss();
}else{
mWhich = which;
}
}
};
new AlertDialog.Builder(getContext())
.setSingleChoiceItems(items, sp.getInt("ecg12_index",0), onClickListener)
.setTitle("寻峰导联设置")
.setIcon(R.drawable.settings_ecg)
.setPositiveButton(R.string.confirm, onClickListener).show();
3、Toast
一般通过Toast.makeText(Context context, CharSequence text, int duration).show()来使用Toast。
也可直接实例化使用:
Toast toast = new Toast(MainActivity.this);
TextView tv = new TextView(MainActivity.this);
tv.setText("嘻嘻");
toast.setView(tv);
toast.show();
Toast包含内部类private static class TN extends ITransientNotification.Stub作为其属性,并封装了它的方法。
TN包含Handler属性,Handler实例化需要之前调用Looper.prepare(),否则new Handler()时报异常。
4、Log
Log只含有私有无参构造private Log(),所以禁止直接实例化。
Log.v(String tag, String msg)
Log.e(String tag, String msg, Throwable tr):可打印异常信息
Log.println(int priority, String tag, String msg)
priority区分优先级,用不同颜色显示,如Log.VERBOSE,Log.WARN,Log.ASSERT等。
System.out.println("Good");tag为System.out,level为i,priority为INFO
System.err.println("Bad");tag为System.err,level为w,priority为WARN
5、PopupWindow
TextView textView = new TextView(MainActivity.this);
textView.setText("so long");
mPopupWindow = new PopupWindow(textView, ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
mPopupWindow.showAtLocation((View) v.getParent(), Gravity.BOTTOM, 0, 0);
mPopupWindow.dismiss();
6、比较
Log在LogCat中显示,方便调试时查看,实现过滤、保存、删除。
Toast在指定时间到达后自动消失。
Dialog会挡住当前Activity,PopupWindow不会。
7、示例演示Dialog的各种用法
1)MainActivity.java
public class MainActivity extends FragmentActivity {
private static final String TAG = MainActivity.class.getSimpleName();
public static final int DIALOG_ID_TEST = 0x01;
EditText editText;
Editable editable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = new EditText(this);
editText.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
editable = Editable.Factory.getInstance().newEditable("WhyWhatHow");
}
public void onClick(View v){
Calendar calendar = Calendar.getInstance();
switch (v.getId()) {
case R.id.btn_dialog:
Bundle bundle = new Bundle();
bundle.putString("Content", new SimpleDateFormat("yyyy/MM/dd HH-mm-ss E").format(new Date()));
showDialog(DIALOG_ID_TEST, bundle);break;
case R.id.btn_char:
CharacterPickerDialog characterPickerDialog = new CharacterPickerDialog(this, editText, editable, "123456789", false){
public void onClick(View v) {
dismiss();
Log.i(TAG, "onClick-"+editText.getText());
};
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
Log.i(TAG, "onItemClick-"+position);
};
};
characterPickerDialog.show();break;
case R.id.btn_date:
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
DatePickerDialog dialog = new DatePickerDialog(this, mOnDateSetListener, year, month, day);
if(android.os.Build.VERSION.SDK_INT>=11){
dialog.getDatePicker().setCalendarViewShown(false);
dialog.getDatePicker().setMaxDate(new Date().getTime());
//1900年1月1号
dialog.getDatePicker().setMinDate(new Date(0, 0, 1).getTime());
}
dialog.show();break;
case R.id.btn_time:
int h = calendar.get(Calendar.HOUR_OF_DAY);
int m = calendar.get(Calendar.MINUTE);
TimePickerDialog timePickerDialog = new TimePickerDialog(this, mTimeSetListener, h, m, true);
timePickerDialog.show();break;
case R.id.btn_progress:
ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMax(100);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.show();break;
case R.id.btn_DialogFragment:
DialogFragment dialogFragment = MyDialogFragment.getInstance(
new SimpleDateFormat("yyyy/MM/dd HH-mm-ss E").format(new Date()));
dialogFragment.show(getSupportFragmentManager(), "fantastic");break;
case R.id.btn_Activity://Activity作为Dialog使用
startActivity(new Intent(this, DialogDemo.class));
default:
break;
}
}
@Override
protected Dialog onCreateDialog(int id, Bundle args) {
//首次showDialog才会触发
Log.i(TAG, "onCreateDialog");
switch (id) {
case DIALOG_ID_TEST:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("The current time is ...")
.setMessage("The present");
return builder.create();
default:
break;
}
return null;
}
@Override
protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
//每次showDialog都会触发
Log.i(TAG, "onPrepareDialog");
switch (id) {
case DIALOG_ID_TEST:
((AlertDialog)dialog).setMessage(args.getString("Content"));
break;
default:
break;
}
}
private DatePickerDialog.OnDateSetListener mOnDateSetListener = new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear,int dayOfMonth) {
Log.i(TAG, "onDateSet-"+year+"-"+monthOfYear+"-"+dayOfMonth);
}
};
private TimePickerDialog.OnTimeSetListener mTimeSetListener = new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Log.i(TAG, "onTimeSet-"+hourOfDay+"-"+minute);
}
};
}
2)activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="@+id/btn_dialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="dialog"/>
<Button
android:id="@+id/btn_Activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="Activity"/>
<Button
android:id="@+id/btn_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="date"/>
<Button
android:id="@+id/btn_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="time"/>
<Button
android:id="@+id/btn_char"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="char"/>
<Button
android:id="@+id/btn_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="progress"/>
<Button
android:id="@+id/btn_DialogFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="DialogFragment"/>
</LinearLayout>
3)MyDialogFragment.java
/**
* API level 4(API level 11引入)
* 高效封装和管理Dialog的lifecycle,和Dialog状态一致
* override either onCreateDialog or onCreateView
*/
public class MyDialogFragment extends DialogFragment {
private static final String TAG = MyDialogFragment.class.getSimpleName();
private static final String CURRENT_TIME = "CURRENT_TIME";
public static MyDialogFragment getInstance(String currentTime){
MyDialogFragment fragment = new MyDialogFragment();
Bundle bundle = new Bundle();
bundle.putString(CURRENT_TIME, currentTime);
fragment.setArguments(bundle);
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Log.i(TAG, "onCreateDialog");
// AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// builder.setTitle("The current time is ...")
// .setMessage(getArguments().getString(CURRENT_TIME));
// return builder.create();
Dialog dialog = new MyDialog(getActivity());
dialog.setTitle("Come on baby!");
dialog.getWindow().setContentView(R.layout.dialog);
EditText editText = (EditText) dialog.getWindow().findViewById(R.id.editText);
editText.setHint("input something");
return dialog;
}
// @Override
// public View onCreateView(LayoutInflater inflater, ViewGroup container,
// Bundle savedInstanceState) {
// View view = inflater.inflate(R.layout.dialog_view, container, false);
// TextView tv = (TextView) view.findViewById(R.id.dialog_view_text);
// tv.setText("The girl is my lover!");
// return view;
// }
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
}
@Override
public void onStart() {
Log.i(TAG, "onStart");
super.onStart();
}
@Override
public void onStop() {
Log.i(TAG, "onStop");
super.onStop();
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy");
super.onDestroy();
}
}
4)MyDialog.java
/**
* lifecycle of Dialog
*/
public class MyDialog extends Dialog {
private static final String TAG = MyDialog.class.getSimpleName();
public MyDialog(Context context) {
super(context);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
}
@Override
protected void onStart() {
Log.i(TAG, "onStart");
super.onStart();
}
@Override
protected void onStop() {
Log.i(TAG, "onStop");
super.onStop();
}
}
5)dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
6)dialog_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/dialog_view_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
7)DialogDemo.java
/**
* 作为Dialog使用
*/
public class DialogDemo extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dialog);
}
}
8)activity_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Activity"/>
</LinearLayout>
9)AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.dialogtest3"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.dialogtest3.MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.example.dialogtest3.DialogDemo"
android:theme="@android:style/Theme.Dialog"></activity>
</application>
</manifest>