第三节 UI组件之弹出组件
3-1 消息提示
1.设置显示的位置
代码如下:
Toast toastCenter = Toast.makeText(getApplicationContext(),"居中Toast",Toast.LENGTH_SHORT);
toastCenter.setGravity(Gravity.CENTER, 0, 0);//后两个参数为x偏移量,y偏移量
toastCenter.show();
通过Toast的set方法进行设置
2.自定义显示内容
添加一个layout_toast布局来设置自定义toast的内容
实现代码如下:
Toast toastCustom = new Toast(getApplicationContext());//加载布局管理器LayoutInflater inflater = LayoutInflater.from(ToastActivity.this);//将xml布局转换为view对象View view = inflater.inflate(R.layout.layout_toast, null);ImageView imageView = (ImageView) view.findViewById(R.id.iv_toast);TextView textView = (TextView) view.findViewById(R.id.tv_toast);imageView.setImageResource(R.drawable.icon_toast);textView.setText("自定义Toast");toastCustom.setView(view);toastCustom.setDuration(Toast.LENGTH_LONG);toastCustom.show();
这样即可实现自定义toast,效果如下:
在这里注意到一个问题,当你连续触发toast后,toast并不会按最后一个触发的时间来计算,而且触发多少次就显示多少次toast
Toast.cancel();
用此方法可实现按最后一次触发toast的时间来计算
3.封装Toast
创建util包,然后创建ToastUtil文件
public class ToastUtil {public static Toast mToast;public static void showMsg(Context context, String msg){if(mToast == null){mToast = Toast.makeText(context,msg, Toast.LENGTH_LONG);}else {mToast.setText(msg);}mToast.show();}
}
封装了一个toast,使用时直接调用
ToastUtil.showMsg(getApplicationContext(),"封装Toast");
3-2 AlertDialog
AlertDialog(Android.support.v7.app)兼容包,可以向下兼容,使得旧版本系统也能兼容新版本的控件
AlertDialog(Android.app)
1.默认样式
AlertDialog.Builder builder = new AlertDialog.Builder(DialogActivity.this);builder.setTitle("请回答")//设置标题.setMessage("你觉得学的怎么样")//设置内容信息.setIcon(R.drawable.icon_user)//设置图标//设置选项.setPositiveButton("棒", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {ToastUtil.showMsg(DialogActivity.this, "你很诚实");//ToastUtil是自己封装的Toast}}).setNeutralButton("还行", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {ToastUtil.showMsg(DialogActivity.this, "你再想想~");}}).setNegativeButton("不好", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {ToastUtil.showMsg(DialogActivity.this, "你在瞎说");}}).show();
效果如下:
setPositionButton(最右侧按钮),setNeutralButton(中间按钮),setNegativeButton(最左侧按钮)
还有个setItem
final String[] array2 = new String[]{"男","女"};AlertDialog.Builder builder2 = new AlertDialog.Builder(DialogActivity.this);builder2.setTitle("选择性别").setItems(array2, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {//which是选中的位置ToastUtil.showMsg(DialogActivity.this, array2[which]);}}).show();
效果如下:其他设置同上面一样
2.单选样式
final String[] array3 = new String[]{"男","女"};AlertDialog.Builder builder3 = new AlertDialog.Builder(DialogActivity.this);builder3.setTitle("选择性别").setSingleChoiceItems(array3, 1, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {ToastUtil.showMsg(DialogActivity.this,array3[which]);dialog.dismiss();}}).setCancelable(false).show();
setSingleChiceItems(array3,1, OnclickListener)第二个参数指的是默认选中的位置
dialog.dismiss();选中后消失
setCancelable()设置false则点击其他区域不会取消该dialog,true则会取消该dialog
效果如下:
3.多选样式
final String[] array4 = new String[]{"唱歌","跳舞","写作业"};boolean[] isSelected = new boolean[]{false,false,true};AlertDialog.Builder builder4 = new AlertDialog.Builder(DialogActivity.this);builder4.setTitle("选择兴趣").setMultiChoiceItems(array4, isSelected, new DialogInterface.OnMultiChoiceClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which, boolean isChecked) {ToastUtil.showMsg(DialogActivity.this,array4[which]+":"+isChecked);}}).setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {//}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {//}}).show();
setMultiChoiceItems(array4, isSelected, OnclickListener)第二个参数是一个boolean数组,表示默认的选中状态 public void onClick(DialogInterface dialog, int which, boolean isChecked)which表示选中的位置,isChecked表示是否选中
效果如下:
4.自定义样式
AlertDialog.Builder builder5 = new AlertDialog.Builder(DialogActivity.this);View view = LayoutInflater.from(DialogActivity.this).inflate(R.layout.layout_dialog, null);EditText euserName = (EditText) view.findViewById(R.id.et_username);EditText epassWord = (EditText) view.findViewById(R.id.et_password);Button btnLogin = (Button) view.findViewById(R.id.btn_login);btnLogin.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View v) {//}});builder5.setTitle("请先登陆").setView(view).show();
绑定布局layout文件来自定义样式
效果如下:
3-3 ProgressBar&ProgressDialog
1.基本属性
若不设置style,则为最新的默认加载样式
style="@android:style/Widget.Material.ProgressBar.Horizontal"//最新的进度条样式
style="@android:style/Widget.ProgressBar"//旧系统的加载样式
style="@android:style/Widget.ProgressBar.Horizontal"//旧系统的进度条样式
效果如下:
部分属性作用如下:
android:max="100"//设置最大值 android:progress="10"//设置当前进度 android:secondaryProgress="30"//设置二级进度条当前进度
2.进度条加载动画
通过点击 模拟进度 按钮,上方的黄色进度条将开始加载
首先设置监听事件:
mBtnStart.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {handler.sendEmptyMessage(0);}});
handler.sendEmptyMessage(0);将传递消息0到handler
Handler handler = new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);if(mPb3.getProgress() < 100){handler.postDelayed(runnable, 500);}else {ToastUtil.showMsg(ProgressActivity.this, "加载完成");}}};
handler接收到该消息后,满足条件后调用
handler.postDelayed(runnable, 500);//延时加载,第一个参数为执行加载的操作,第二个操作位延时的时间,单位为ms
通过runnable来执行加载
Runnable runnable = new Runnable() {@Overridepublic void run() {mPb3.setProgress(mPb3.getProgress() + 5);handler.sendEmptyMessage(0);}};
setProgress()每次调用递增5,从而实现加载动画
最后返回消息0
3.自定义进度条
先创建一个animated-rotate的xml文件
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"android:drawable="@drawable/icon_progress"android:pivotX="50%"// 表示缩放/旋转起点 X 轴坐标,可以是整数值、百分数(或者小数)、百分数p 三种样式android:pivotY="50%">//与android:pivotX类似。 //这两个共同作用起来就是以中心为旋转轴旋转 </animated-rotate>
然后在values文件夹里的styles.xml文件里添加style
<style name="MyProgressBar"><item name="android:indeterminateDrawable">@drawable/bg_progress</item>//动画源文件<item name="android:indeterminate">true</item>//表示的是这个ProgressBar是模糊的,不明确的,实质就是不断地旋转 </style>
最后再在xml文件里引用就行了
style="@style/MyProgressBar"
4.ProgressDoalog
其实就和Dialog一样,首先是加载样式
mBtnProgress1.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View v) {ProgressDialog progressDialog = new ProgressDialog(ProgressActivity.this);progressDialog.setTitle("提示");progressDialog.setMessage("正在加载");progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {@Overridepublic void onCancel(DialogInterface dialog) {ToastUtil.showMsg(ProgressActivity.this, "cancel...");}});progressDialog.setCancelable(false);progressDialog.show();}});
新建一个ProgressDialog,然后通过set设置属性
setCancelable()表示是否能被点击对话框外部来取消
mBtnProgress1是按钮,点击该按钮来弹出Dialog
这里没有设置setProgressStyle,为默认样式
setOnCancelListerer设置取消监听器,当Dialog被取消后触发
效果如下:
进度条样式:
mBtnProgress2.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View v) {ProgressDialog progressDialog = new ProgressDialog(ProgressActivity.this);progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);progressDialog.setTitle("提示");progressDialog.setMessage("正在下载。。。");progressDialog.setButton(DialogInterface.BUTTON_POSITIVE, "棒", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {ToastUtil.showMsg(ProgressActivity.this, "已被点击");}});progressDialog.show();}});
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//进度条样式
这里在Dialog里设置了一个Button,setButton(按钮的位置,按钮内容,监听器)
其中按钮的位置同普通Dialog一样有3个,Position,Neutral,Negative
效果如下:
5.实现标准样式的Dialog
效果如下:
需要自定义一个Dialog类
public class CustomDialog extends Dialog implements View.OnClickListener{private TextView mTvTitle,mTvMessage, mTvCancel, mTvConfirm;private String title, message, cancel, confirm;private IOnCancelListener cancelListener;private IOnConfirmListener confirmListener;public CustomDialog setTitle(String title) {this.title = title;return this;}public CustomDialog setMessage(String message) {this.message = message;return this;}public CustomDialog setCancel(String cancel, IOnCancelListener listener) {this.cancel = cancel;this.cancelListener = listener;return this;}public CustomDialog setConfirm(String confirm, IOnConfirmListener listener) {this.confirm = confirm;this.confirmListener = listener;return this;}public CustomDialog(@NonNull Context context) {super(context);}public CustomDialog(@NonNull Context context, int themeResId) {super(context, themeResId);}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.layout_custom_dialog);//此段作用是设置宽度为手机屏幕的80%WindowManager windowManager = getWindow().getWindowManager();Display display = windowManager.getDefaultDisplay();WindowManager.LayoutParams layoutParams = getWindow().getAttributes();Point point = new Point();display.getSize(point);layoutParams.width = (int) (point.x * 0.8);//设置dialog的宽度为当前手机屏幕的宽度getWindow().setAttributes(layoutParams);mTvTitle = (TextView) findViewById(R.id.tv_title);mTvMessage = (TextView) findViewById(R.id.tv_message);mTvCancel = (TextView) findViewById(R.id.tv_cancel);mTvConfirm = (TextView) findViewById(R.id.tv_confirm);if(!TextUtils.isEmpty(title)){mTvTitle.setText(title);}if(!TextUtils.isEmpty(message)){mTvMessage.setText(message);}if(!TextUtils.isEmpty(cancel)){mTvCancel.setText(cancel);}if(!TextUtils.isEmpty(confirm)){mTvConfirm.setText(confirm);}mTvCancel.setOnClickListener(this);mTvConfirm.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()){case R.id.tv_cancel:if (cancelListener != null){cancelListener.onCancel(this);}dismiss();break;case R.id.tv_confirm:if (confirmListener != null){confirmListener.onConfirm(this);}dismiss();break;}}public interface IOnCancelListener{void onCancel(CustomDialog dialog);}public interface IOnConfirmListener{void onConfirm(CustomDialog dialog);} }
CustomDialog customDialog = new CustomDialog(CustomDialogActivity.this); customDialog.setTitle("提示").setMessage("确认删除此项?").setCancel("取消", new CustomDialog.IOnCancelListener() {@Overridepublic void onCancel(CustomDialog dialog) {ToastUtil.showMsg(CustomDialogActivity.this, "cancel...");}}).setConfirm("确认", new CustomDialog.IOnConfirmListener() {@Overridepublic void onConfirm(CustomDialog dialog) {ToastUtil.showMsg(CustomDialogActivity.this, "confirm...");} }).show();
3-5 PopupWindow
实现一个类似菜单的按钮,效果如下:
首先要新建一个layout_pop.xml用来显示弹出菜单内的视图,然后通过
View view = getLayoutInflater().inflate(R.layout.layout_pop, null);
获取该视图
代码如下:
mBtnPop = (Button) findViewById(R.id.btn_pop);mBtnPop.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {View view = getLayoutInflater().inflate(R.layout.layout_pop, null);mPop = new PopupWindow(view, mBtnPop.getWidth(), ViewGroup.LayoutParams.WRAP_CONTENT);//以下实现对“好”按钮的响应TextView textView = (TextView) view.findViewById(R.id.tv_good);textView.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View v) {mPop.dismiss();ToastUtil.showMsg(PopupWindowActivity.this, "好");}});//点击外部区域PopMenu消失mPop.setBackgroundDrawable(new BitmapDrawable());mPop.setOutsideTouchable(true);mPop.setFocusable(true);mPop.showAsDropDown(mBtnPop, 0, 0, Gravity.CENTER_HORIZONTAL);
其中想要实现点击外部区域关闭PopupMenu需要同时使用以下语句
mPop.setBackgroundDrawable(new BitmapDrawable()); mPop.setOutsideTouchable(true);
具体分析参考:https://www.jianshu.com/p/825d1cc9fa79