一、对话框
1.1、基本使用流程
- Step1:创建AlertDialog.Builder对象;
- Step2:调用setIcon()设置图标,setTitle()或setCustomTitle()设置标题;
- Step3:设置对话框内容:setMessage()或其他方法指定显示的内容;
- Step4:调用setPositive/Negative/NeutraButton()设置确定、取消、中立按钮;
- Step5:调用create()方法创建这个对象,再调用show()方法将对话框显示出来;
1.2、常用对话框
a) 确定取消对话框
public void click01(View view) { AlertDialog.Builder builder = new Builder(this); builder.setTitle("友情提醒"); builder.setMessage("若练此功,必先自宫,是否继续?"); builder.setPositiveButton("好的,想好了", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "啊。。。", 0).show(); Toast.makeText(MainActivity.this, "即使自宫,也不一定成功", 0).show(); } }); builder.setNegativeButton("想想再说", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "若不自宫,一定不成功", 0).show(); } }); builder.create().show(); }
b) 单选对话框
public void click02(View view) { AlertDialog.Builder builder = new Builder(this); builder.setTitle("请选择性别:"); final String[] items = { "男", "女", "未知" }; builder.setSingleChoiceItems(items, 2, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); Toast.makeText(MainActivity.this, "您的性别:" + items[which], 0).show(); } }); builder.show(); }
c) 多选对话框
public void click03(View view) { AlertDialog.Builder builder = new Builder(this); builder.setTitle("请选择您喜欢的水果:"); final String[] items = { "苹果", "香蕉", "葡萄", "橘子" }; final boolean[] result = new boolean[] { true, true, false, false }; builder.setMultiChoiceItems(items, result, new OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int which, boolean isChecked) { result[which] = isChecked; Toast.makeText(MainActivity.this,items[which] + isChecked, 0).show(); } }); builder.setPositiveButton("提交", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < result.length; i++) { if (result[i]) sb.append(items[i] + ","); } Toast.makeText(MainActivity.this, "您喜欢:" + sb.toString(), 0).show(); } }); builder.show(); }
d) 进度对话框
public void click04(View view) { final ProgressDialog pd = new ProgressDialog(this); pd.setTitle("提醒"); pd.setMessage("正在处理中。。。请稍后"); pd.show(); new Thread() { public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } pd.dismiss(); }; }.start(); }
e) 进度条对话框
public void click05(View view) { final ProgressDialog pd = new ProgressDialog(this); // 设置进度的样式 pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pd.setTitle("提醒"); pd.setMessage("正在处理中。。。请稍后"); pd.show(); new Thread() { public void run() { pd.setMax(100); try { for (int i = 0; i <= 100; i++) { pd.setProgress(i); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } pd.dismiss(); }; }.start(); }
1.3、样式对话框
1、基本用法
public void click(View v){ Builder builder = new Builder(this); View view = View.inflate(this, R.layout.item_dialog, null); final AlertDialog dialog = builder.create(); dialog.setView(view,0,0,0,0); dialog.show(); Button btn_ok = (Button) view.findViewById(R.id.btn_item_ok); Button btn_cancel = (Button) view.findViewById(R.id.btn_item_cancel); btn_ok.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "确认对话框被按下", 0).show(); dialog.dismiss(); } }); btn_cancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "取消对话框被按下", 0).show(); dialog.dismiss(); } }); }
2、底部弹出对话框
/**打开底部选择对话框*/ private void showPhotoDialog() { View view = getLayoutInflater().inflate(R.layout.photo_choose_dialog, null); dialog = new Dialog(this, R.style.transparentFrameWindowStyle); dialog.setContentView(view, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); Window window = dialog.getWindow(); window.setWindowAnimations(R.style.main_menu_animstyle); WindowManager.LayoutParams wl = window.getAttributes(); wl.x = 0; wl.y = getWindowManager().getDefaultDisplay().getHeight(); wl.width = ViewGroup.LayoutParams.MATCH_PARENT; wl.height = ViewGroup.LayoutParams.WRAP_CONTENT; dialog.onWindowAttributesChanged(wl); dialog.setCanceledOnTouchOutside(false); dialog.show(); // 初始化 Button btnCamera = (Button) view.findViewById(R.id.btn_phonedialog_camera); Button btnPhoto = (Button) view.findViewById(R.id.btn_phonedialog_photo); Button btnCancel = (Button) view.findViewById(R.id.btn_phonedialog_cancel); btnCamera.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { } }); btnPhoto.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { } }); btnCancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { } }); }
其中使用到的样式
<style name="transparentFrameWindowStyle" parent="android:style/Theme.Dialog"> <item name="android:windowBackground">@drawable/photo_choose_bg</item> </style> <style name="main_menu_animstyle"> <item name="android:windowEnterAnimation">@anim/photo_dialog_in_anim</item> <item name="android:windowExitAnimation">@anim/photo_dialog_out_anim</item> </style>
布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#00000000" android:gravity="bottom" android:orientation="vertical" android:padding="5dip" > <Button android:id="@+id/btn_phonedialog_camera" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/photo_gallery_selector" android:paddingBottom="10dip" android:paddingTop="10dip" android:text="拍照" android:textSize="16sp" /> <TextView android:layout_width="match_parent" android:layout_height="0.5dip" android:background="#DAD9DB" /> <Button android:id="@+id/btn_phonedialog_photo" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/photo_camera_selector" android:paddingBottom="10dip" android:paddingTop="10dip" android:text="从手机相册选择" android:textSize="16sp" /> <Button android:id="@+id/btn_phonedialog_cancel" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dip" android:background="@drawable/photo_cancel_selector" android:paddingBottom="10dip" android:paddingTop="10dip" android:text="取消" android:textSize="16sp" /> </LinearLayout>
3、全局对话框
写好Alter功能块后,在alter.show()语句前加入:
alert.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
如果只在Service中写入正常开启对话框的代码的话会发生错误,因为Alter的显示需要依附于一个确定的Activity类。而以上做法就是声明我们要弹出的这个提示框是一个系统的提示框,即全局性质的提示框。
AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Are you sure you want to exit?") .setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { MyActivity.this.finish(); } }) .setNegativeButton("No", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = builder.create(); alert.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); alert.show();
其中全局对话框用到的权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"></uses-permission>
4、登陆态对话框
假设有这样一个场景,我们需要用到全局性的对话框,用来针对登陆态的判断,以此返回到登录界面。我们知道Dialog需要依附某个Activity而启动,
而我们跳转到登录界面后,Dialog还持有当前Activity的引用,导致当前Activity还存在于栈中无法被销毁,故我们可以在类中定义登陆态对话框。
public class ReLogin { /** * 登录态判断对话框 */ public static void showLoginDialog(final Activity activity) { new com.hll.phoneserver.dialog.AlertDialog(activity).builder().setTitle("登录提示!") .setMsg("账号在其他设备已登录,如果不是本人操作,请及时修改密码,防止盗号。").setCancelable(false) .setPositiveButton("重新登录", new View.OnClickListener() { @Override public void onClick(View v) { // 跳转到登录界面 Context _context = activity.getApplicationContext(); activity.finish(); Intent intent = new Intent(_context, LoginActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK); _context.startActivity(intent); // 或者重启应用 Intent intent = _context.getPackageManager() .getLaunchIntentForPackage(_context.getPackageName()); PendingIntent restartIntent = PendingIntent.getActivity(_context, 0, intent, PendingIntent.FLAG_ONE_SHOT); AlarmManager mgr = (AlarmManager)_context.getSystemService(Context.ALARM_SERVICE); mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent); System.exit(0); } }).show(); } }
二、Toast
1.1、基本吐司
Toast.makeText(MainActivity.this, "按钮被单击", Toast.LENGTH_SHORT).show();
Toast默认的位置在于屏幕的下方居中的位置,如果想改变Toast的位置则可以设置Gravity:
Toast toast = Toast.makeText(this, "当前已是最新版本", Toast.LENGTH_SHORT); toast.setGravity(Gravity.CENTER, 0, 0); toast.show();
1.2、自定义吐司
/** * 自定义的吐司 * */ private void showMyToast(String address) { WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); View view = View.inflate(this, R.layout.total_address, null); TextView tv_address = (TextView) view.findViewById(R.id.tv_address); tv_address.setText(address); WindowManager.LayoutParams params = new WindowManager.LayoutParams(); params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; params.format = PixelFormat.TRANSLUCENT; params.type = WindowManager.LayoutParams.TYPE_TOAST; wm.addView(view, params); }
注意:在不使用时间要调用WindowManager的removeView(view)来释放资源。
三、菜单
Menu接口下有两个子接口:SubMenu和ContextMenu。
Menu接口下的方法:
- Menu的方法归纳起来只有两个:add()方法用于添加菜单项;addSubMenu()用于添加子菜单。
- 这些重载方法的区别:是否将子菜单、菜单项添加到指定菜单组中和是否使用资源文件中的字符串资源设置标题。
1.1、选项菜单(Option Menu)
当用户点击设备菜单按钮(Menu),触发的就是选项菜单,该菜单最多六项,超出六项则显示更多。
- 覆盖Activity的onCreateOpitionMenu(Menu menu)方法,并指定menu下的布局文件。
- 调用Menu的add()方法添加菜单项(MenuItem),调用MenuItem的setIcon()方法为菜单项设置图标。
- 当菜单项(MenuItem)被选中时,覆盖Activity的onOptionsMenuSelected()方法响应事件。
1.2、上下文菜单(Context Menu)
当用户长按Activity页面时,弹出的的菜单就是上下文菜单,不支持菜单快捷键和图标。
- 覆盖Activity的onCreateContextMenu()方法,调用Menu的add()方法添加菜单项(MenuItem)。
- 覆盖onContextItemSelected()方法,响应菜单单击事件。
- 调用registerForContextMenu()方法,为视图注册上下文菜单。
1.3、子菜单(Sub Menu)
子菜单就是将相同功能的分组进行多级显示的一种菜单,不支持菜单项图标和嵌套子菜单。
- 覆盖Activity的onCreateOptionsMenu()方法,调用Menu的addSubMenu()方法添加子菜单项。
- 调用SubMenu的add()方法,添加子菜单项。
- 覆盖onCreateItemSelected()方法,响应菜单单击事件。
源码下载:
链接:http://pan.baidu.com/s/1bpBL4Wv 密码:s8rx
三、悬浮窗
Popupwindow和AlertDialog的区别在于AlertDialog只能默认显示在屏幕中间(不包括自定义的Dialog),即使是自定义的dialog处理位置也比较麻烦。
而Popupwindow是可以指定显示在任意位置的,相当的灵活。
1.1、简单构建
1、构造函数
Popupwindow有四个构造函数,其中contentView、width、height是必须具备的,否则无法弹出悬浮窗。其中focusable则不是必须的。
public PopupWindow(View contentView, int width, int height, boolean focusable)
所以,带contentView、width和height的构造函数是最常用的。当然,我们不一定非要在构造函数设置,也可以通过方法来指定。
View contentView = LayoutInflater.from(MainActivity.this).inflate(R.layout.popuplayout, null); PopupWindow popWnd = new PopupWindow (this); popWnd.setContentView(contentView); popWnd.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT); popWnd.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); popWnd.showAtLocation(contentView, Gravity.BOTTOM, 0, 0);
这样即可以弹出一个简单的悬浮窗,要关闭悬浮窗只需调用dismiss()方法即可,下面我们看看悬浮窗的两种位置设置方式:
1、显示在某个指定控件的下方
showAsDropDown(View anchor): showAsDropDown(View anchor, int xoff, int yoff);
这两个方法用来设置相对某个控件的相对位置,可以选择是否带有偏移,xoff表示x轴的偏移,正值表示向左,负值表示向右;yoff表示相对y轴的偏移,正值是向下,负值是向上;
2、指定父视图,显示在父控件的某个位置(Gravity.TOP,Gravity.RIGHT等)
showAtLocation(View parent, int gravity, int x, int y);
这个方法用来设置相对父容器的位置,也可以选择是否带有偏移。
2、常用函数
Popupwindow还有以下一些常用的函数:
public void dismiss() public void setFocusable(boolean focusable) public void setTouchable(boolean touchable) public void setOutsideTouchable(boolean touchable) public void setBackgroundDrawable(Drawable background)
dismiss():表示关闭悬浮窗。
setFocuseable():设置是否获取焦点,默认为false,如果PopupWindow布局中有控件需要获取焦点,那么该方法必须设置true。
setTouchable():设置是否响应touch事件,默认是true,如果为false则无法响应所有事件(包括点击事件)。
setOutsideTouchable():设置PopupWindow以外的区域是否可以点击,并且点击会让Popupwindow消失。
setBackgroundDrawable():设置悬浮窗的背景,可以设置BitmapDrawable或ColorDrawable等。
private void showPopWindow() { View contentView = LayoutInflater.from(MainActivity.this).inflate(R.layout.popuplayout, null); popWnd = new PopupWindow (this); popWnd.setContentView(contentView); popWnd.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT); popWnd.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); popWnd.setOutsideTouchable(true); popWnd.setBackgroundDrawable(new ColorDrawable(Color.GRAY)); popWnd.showAtLocation(contentView, Gravity.BOTTOM, 0, 0); } @Override public void onBackPressed() { super.onBackPressed(); popWnd.dismiss(); }
注意:需要设置手机返回键按下时关闭悬浮窗,否则会报异常。
1.2、PopupWindow动画
1、生成动画的Style
为Popupwindow添加动画只需要调用setAnimationStyle()方法即可。
popwindow.setAnimationStyle(R.style.contextMenuAnim);
a) 显示悬浮窗的代码
public class MainActivity extends Activity { private PopupWindow popWnd; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void open(View view){ showPopWindow(); } private void showPopWindow() { View contentView = LayoutInflater.from(MainActivity.this).inflate(R.layout.popuplayout, null); popWnd = new PopupWindow (this); popWnd.setContentView(contentView); popWnd.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT); popWnd.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); popWnd.setOutsideTouchable(true); popWnd.setAnimationStyle(R.style.PopwindowAnim); popWnd.showAtLocation(contentView, Gravity.CENTER, 0, 0); } @Override public void onBackPressed() { super.onBackPressed(); popWnd.dismiss(); } }
b) res/anim/下定义进场动画和出场动画:
context_menu_enter.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="@android:integer/config_shortAnimTime" android:fromXDelta="0" android:fromYDelta="100%p" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:toXDelta="0" android:toYDelta="0"/> </set>
context_menu_exit.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="@android:integer/config_shortAnimTime" android:fromXDelta="0" android:fromYDelta="0" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:toXDelta="0" android:toYDelta="100%p" /> </set>
c) 在values/style.xml中定义动画样式:
<style name="PopwindowAnim" parent="@android:style/Animation.Activity"> <item name="android:windowEnterAnimation">@anim/context_menu_enter</item> <item name="android:windowExitAnimation">@anim/context_menu_exit</item> </style>
这样一个带动画的PopupWindow就实现了。