第三节 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() {
@Override
public void onClick(DialogInterface dialog, int which) {
ToastUtil.showMsg(DialogActivity.this, "你很诚实");//ToastUtil是自己封装的Toast
}
}).setNeutralButton("还行", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ToastUtil.showMsg(DialogActivity.this, "你再想想~");
}
}).setNegativeButton("不好", new DialogInterface.OnClickListener() {
@Override
public 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() {
@Override
public 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() {
@Override
public 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() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
ToastUtil.showMsg(DialogActivity.this,array4[which]+":"+isChecked);
}
}).setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public 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(){
@Override
public 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() {
@Override
public void onClick(View v) {
handler.sendEmptyMessage(0);
}
});
handler.sendEmptyMessage(0);将传递消息0到handler
Handler handler = new Handler(){
@Override
public 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() {
@Override
public 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(){
@Override
public void onClick(View v) {
ProgressDialog progressDialog = new ProgressDialog(ProgressActivity.this);
progressDialog.setTitle("提示");
progressDialog.setMessage("正在加载");
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public 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(){
@Override
public 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() {
@Override
public 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); } @Override protected 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); } @Override public 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() { @Override public void onCancel(CustomDialog dialog) { ToastUtil.showMsg(CustomDialogActivity.this, "cancel..."); } }).setConfirm("确认", new CustomDialog.IOnConfirmListener() { @Override public 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() {
@Override
public 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(){
@Override
public 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);