2.实践
前面提到几种实现方式均可以达到同样的演示效果,但其中又是各有不同。这里先逐一列举各种具体实现,最后加以综述总结和归纳吧。
在此之前呢,先看一下这里实现的对话框共用布局layout/confirm_dialog.xml 。
<?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="wrap_content" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:background="@drawable/confirm_dialog_bg" android:orientation="vertical"> <LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:background="@android:color/transparent"android:orientation="vertical" ><TextView android:id="@+id/title_name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:paddingBottom="10dp" android:paddingTop="15dp" android:text="Message Title"android:textColor="@android:color/black" android:textSize="20sp" android:visibility="visible" /> </LinearLayout> <LinearLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:background="@android:color/transparent"android:orientation="vertical" ><TextViewandroid:id="@+id/text_view" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" android:layout_marginTop="10dp" android:textColor="@android:color/black" android:text="this is message content" android:textSize="16dip"/><View android:layout_width="match_parent" android:layout_height="1px" android:layout_marginTop="15dip" android:background="#c5c5c5" /><LinearLayout android:layout_width="fill_parent" android:layout_height="50dip" android:background="@android:color/transparent" android:gravity="center_horizontal" android:orientation="horizontal" > <!-- 取消按钮 --> <Buttonandroid:id="@+id/btn_cancel"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_weight="1"android:text="Cancel"android:textStyle="bold"android:textColor="#0072c6"android:background="@drawable/confirm_dialog_cancel_selector"android:textSize="15sp" /> <!-- 确认按钮 --> <View android:layout_width="1px"android:layout_height="match_parent"android:layout_gravity="center_horizontal"android:background="#c5c5c5"/> <Buttonandroid:id="@+id/btn_ok"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_weight="1"android:text="OK"android:textStyle="bold"android:textColor="#0072c6"android:background="@drawable/confirm_dialog_ok_selector"android:textSize="15sp" /></LinearLayout> </LinearLayout></LinearLayout>仅仅通过布局预览就可以看到效果了:
下边我们分别通过上述几种方式来使用这个布局展示消息提示框。
2.1 Dialog
这个是最基本也最常见的非阻塞式对话框。具体形式可分为七种,详细参见网上各种文章,随便引用一篇7种形式的Android Dialog使用举例。
(注:官方在fragmentDialog推出后就不在推荐直接使用Dialog来创建对话框,这是后话)
我们这里自定义的提示框ConfirmDialog继承自Dialog,使用confirm_dialog.xml 初始化布局,绑定相应事件。
public class ConfirmDialog extends Dialog { private Context context; private TextView titleTv,contentTv; private View okBtn,cancelBtn; private OnDialogClickListener dialogClickListener; public ConfirmDialog(Context context) {super(context);this.context = context;initalize(); } //初始化View private void initalize() {LayoutInflater inflater = LayoutInflater.from(context);View view = inflater.inflate(R.layout.confirm_dialog, null);setContentView(view);initWindow();titleTv = (TextView) findViewById(R.id.title_name);contentTv = (TextView) findViewById(R.id.text_view);okBtn = findViewById(R.id.btn_ok);cancelBtn = findViewById(R.id.btn_cancel);okBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {dismiss();if(dialogClickListener != null){ dialogClickListener.onOKClick();} }});cancelBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {dismiss();if(dialogClickListener != null){ dialogClickListener.onCancelClick();} }}); } /** *添加黑色半透明背景 */ private void initWindow() {Window dialogWindow = getWindow();dialogWindow.setBackgroundDrawable(new ColorDrawable(0));//设置window背景dialogWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);//设置输入法显示模式WindowManager.LayoutParams lp = dialogWindow.getAttributes();DisplayMetrics d = context.getResources().getDisplayMetrics();//获取屏幕尺寸lp.width = (int) (d.widthPixels * 0.8); //宽度为屏幕80% lp.gravity = Gravity.CENTER;//中央居中dialogWindow.setAttributes(lp); } public void setOnDialogClickListener(OnDialogClickListener clickListener){dialogClickListener = clickListener; } /** *添加按钮点击事件 */ public interface OnDialogClickListener{void onOKClick();void onCancelClick(); }}2.2 PopupWindow
public class ConfirmPopWindow extends PopupWindow{ private Context context; private TextView titleTv,contentTv; private View okBtn,cancelBtn; private OnDialogClickListener dialogClickListener; public ConfirmPopWindow(Context context) {super(context);this.context = context;initalize(); } private void initalize() {LayoutInflater inflater = LayoutInflater.from(context);View view = inflater.inflate(R.layout.confirm_dialog, null);setContentView(view);initWindow();titleTv = (TextView) view.findViewById(R.id.title_name);contentTv = (TextView) view.findViewById(R.id.text_view);okBtn = view.findViewById(R.id.btn_ok);cancelBtn = view.findViewById(R.id.btn_cancel);okBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {dismiss();if(dialogClickListener != null){ dialogClickListener.onOKClick();} }});cancelBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {dismiss();if(dialogClickListener != null){ dialogClickListener.onCancelClick();} }}); } private void initWindow() {this.setBackgroundDrawable(new ColorDrawable(0)); DisplayMetrics d = context.getResources().getDisplayMetrics();this.setWidth((int) (d.widthPixels * 0.8)); this.setHeight(LayoutParams.WRAP_CONTENT); this.setFocusable(true); this.setOutsideTouchable(true); this.update();} public void showAtBottom(View view){showAsDropDown(view, Math.abs((view.getWidth() - getWidth())/2), 20); } public void setOnDialogClickListener(OnDialogClickListener clickListener){dialogClickListener = clickListener; } public interface OnDialogClickListener{void onOKClick();void onCancelClick(); }}2.3 自定义Layout
protected void initialize() {initBackground();//初始化黑色背景initContentView();//初始化confirm_layout 对应的ViewwindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);setOnKeyListener(new OnKeyListener() { //添加按键返回事件 @Override public boolean onKey(View v, int keyCode, KeyEvent event) {if (KeyEvent.KEYCODE_BACK == keyCode && KeyEvent.ACTION_DOWN == event.getAction()) { hide();//隐藏当前view return true;}return false; }setFocusable(true); //可获得焦点setFocusableInTouchMode(true); //可触碰获得焦点 }2.显示自定义VIew : show()
public void show() {((Activity) getContext()).runOnUiThread(new Runnable() { @Override public void run() {if (getParent() == null) { //没有添加则添加至窗体 //获取窗体的布局属性,设置左上角对齐,填充父容器 WindowManager.LayoutParams wlp = new WindowManager.LayoutParams(); wlp.type = WindowManager.LayoutParams.TYPE_APPLICATION; wlp.format = PixelFormat.TRANSPARENT; wlp.gravity = Gravity.LEFT | Gravity.TOP; wlp.width = LayoutParams.MATCH_PARENT; wlp.height = LayoutParams.MATCH_PARENT; windowManager.addView(ConfirmLayout.this, wlp);}showBackGround();//显示背景动画和自定义View }}); } /** *显示背景动画 */ protected void showBackGround() {if (isShowing) return;isShowing = true;background.clearAnimation();background.setVisibility(View.VISIBLE);AlphaAnimation an = new AlphaAnimation(0, 1);an.setDuration(durationMillis);background.startAnimation(an); }3.隐藏自定义VIew : hide()
public void hide() {((Activity) getContext()).runOnUiThread(new Runnable() { @Override public void run() {hideBackGround();//隐藏背景if (getParent() != null) windowManager.removeView(ConfirmLayout.this);//移除view }}); } /** *隐藏背景背景动画 */ protected void hideBackGround() {if (!isShowing) return;isShowing = false;background.clearAnimation();AlphaAnimation an = new AlphaAnimation(1, 0);an.setDuration(durationMillis);an.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) {background.setVisibility(View.GONE); }});background.startAnimation(an); }其他部分同上,不再一一贴出,详细可查看示例源码。
<resources> <style name="DialogStyle" parent="@android:style/Theme.Dialog"><item name="android:windowBackground">@android:color/transparent</item><item name="android:windowFrame">@null</item><item name="android:windowNoTitle">true</item><item name="android:windowIsFloating">true</item><item name="android:windowIsTranslucent">true</item><item name="android:windowFullscreen">true</item><item name="android:backgroundDimEnabled">true</item> </style></resources>然后使用 > android:theme=”@style/DialogStyle” 达到上述效果。具体实现跟dialog类似:
public class ConfirmActivity extends Activity{ private TextView titleTv,contentTv; private View okBtn,cancelBtn; private OnDialogClickListener dialogClickListener; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.confirm_dialog);initViews();initListeners(); } private void initViews() {initWindow();titleTv = (TextView) findViewById(R.id.title_name);contentTv = (TextView) findViewById(R.id.text_view);okBtn = findViewById(R.id.btn_ok);cancelBtn = findViewById(R.id.btn_cancel);okBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {finish();if(dialogClickListener != null){ dialogClickListener.onOKClick();} }}); } private void initWindow() {getWindow().setBackgroundDrawable(new ColorDrawable(0));getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN |WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); } private void initListeners() {cancelBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {finish();if(dialogClickListener != null){ dialogClickListener.onCancelClick();} }}); } public void setOnDialogClickListener(OnDialogClickListener clickListener){dialogClickListener = clickListener; } public interface OnDialogClickListener{void onOKClick();void onCancelClick(); }}2.5 DialogFragment
public class ConfirmFragment extends DialogFragment{ @Override @NonNull public Dialog onCreateDialog(Bundle savedInstanceState) {return new ConfirmDialog(getActivity()); }public void setOnDialogClickListener(OnDialogClickListener clickListener){((ConfirmDialog)getDialog()).setOnDialogClickListener(clickListener); }}当然并不推荐偷懒直接返回前面定义好的ConfirmDialog。我们实际上使用fragment的onCreateView也更合理和简介,他可以产生同样的Dialog效果,同时可以作为内嵌fragment引用。从使用总结来看,FragmentDialog 相较于Dialog有两点好处:
PopupWindow的几种使用场景
4.补充
其实还有种长按弹出菜单,这种除了可以通过上述方法弹出菜单选项外,还可以通过系统提供的 View.setOnCreateContextMenu()方法来实现。比如:
itemView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {@Overridepublic void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { menu.add("删除").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {@Overridepublic boolean onMenuItemClick(MenuItem item) { //执行删除操作 return true;} });} });长按弹出,基本效果为:
有兴趣的不妨试一下。
后边的话我们先从源码角度来看一下这里讲的几种实现方案的具体原理,最后通过一些简易封装来做一个类似IOS上的ActionSheet控件的效果。
演示效果大概为:
详情请继续关注接下来的博文。
最后附上本篇所讲内容的源码:示例源码demo(已重新更新)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。