自定义弹窗 VS AlertDialog分享弹窗

2016-04-15 20:53 阅读 6,405 次 评论 2 条
版权声明:本文著作权归TeachCourse所有,未经许可禁止转载,谢谢支持!
转载请注明出处:http://teachcourse.cn/1659.html

一.摘要

弹窗通常用于提示用户进行某种操作,比如:点击分享按钮,弹窗分享对话框;双击返回按钮,弹窗退出对话框;下载文件,提示下载对话框等等,分享对话框/退出对话框/下载对话框,都可以直接使用AlertDialog实现,类似的效果如下图:
popup-alertdialog-demo

二.AlertDialog基础知识

AlertDialog无法直接通过new关键字获取对象,调用方法:new AlertDialog.Builder.create()获取AlertDialog对象,这个时候容易让人疑惑的是:如何设置对话框的属性?比如:对话框标题,对话框消息,对话框按钮等等

设置对话框属性的两种方式

第一种:设置AlertDialog对象属性,具体代码如下:

  1. private void showDialog() {  
  2.         AlertDialog mDialog = null;  
  3.         mDialog = new AlertDialog.Builder(this).create();;  
  4.           
  5.         mDialog.setIcon(R.drawable.ic_launcher);  
  6.         mDialog.setTitle("系统提示");  
  7.         mDialog.setMessage("你确定要退出吗?");  
  8.         mDialog.setButton(DialogInterface.BUTTON_POSITIVE,"确定"new DialogInterface.OnClickListener() {  
  9.               
  10.             @Override  
  11.             public void onClick(DialogInterface dialog, int which) {  
  12.                   
  13.                 finishMyself();  
  14.             }  
  15.               
  16.         });  
  17.         mDialog.setButton(DialogInterface.BUTTON_NEGATIVE,"取消"new DialogInterface.OnClickListener() {  
  18.               
  19.             @Override  
  20.             public void onClick(DialogInterface dialog, int which) {  
  21.                 Toast.makeText(MainActivity.this"再按一次退出程序", (int) touchTime)  
  22.                 .show();  
  23.                   
  24.             }  
  25.         });  
  26.           
  27.         mDialog.show();  
  28.           
  29.     }  

第二种:设置Builder对象属性,具体代码如下:

  1. private void showDialog() {  
  2.         AlertDialog mDialog = null;  
  3.         Builder mBuilder = new AlertDialog.Builder(this);  
  4.           
  5.         mBuilder.setIcon(R.drawable.ic_launcher);  
  6.         mBuilder.setTitle("系统提示");  
  7.         mBuilder.setMessage("你确定要退出吗?");  
  8.         mBuilder.setPositiveButton("确定"new DialogInterface.OnClickListener() {  
  9.   
  10.             @Override  
  11.             public void onClick(DialogInterface dialog, int which) {  
  12.   
  13.                 finish();  
  14.             }  
  15.   
  16.         });  
  17.         mBuilder.setNegativeButton("取消"new DialogInterface.OnClickListener() {  
  18.   
  19.             @Override  
  20.             public void onClick(DialogInterface dialog, int which) {  
  21.                 Toast.makeText(MainActivity.this"再按一次退出程序", (int) touchTime)  
  22.                         .show();  
  23.   
  24.             }  
  25.         });  
  26.   
  27.         mDialog = mBuilder.create();//创建AlertDialog对象  
  28.   
  29.         mDialog.show();//显示创建的AlertDialog  
  30.   
  31.     }  

这两种方式的对话框展示默认属性——对话框水平垂直居中显示,对话框与左右窗体之间有一小段距离,效果图如下:

alertdialog

如何修改默认对话框属性?

如何修改AlertDialog对话框默认属性,然后实现对话框内容宽度布满屏幕,高度根据内容自适应,类似文章开头点击分享按钮,从底部弹出弹窗的效果。首先创建AlertDialog对话框,然后自定义对话框的布局View,最后设置Window对象属性。

设置Window对象屏幕宽度/高度的三种方式

第一种方式:setLayout()

获得Window对象后,设置Window对象的布局参数,即调用setLayout(int width,int height)方法,width取值:android.view.WindowManager.LayoutParams.MATCH_PARENT/android.view.WindowManager.LayoutParams.WRAP_CONTENT,同理height取值:android.view.WindowManager.LayoutParams.MATCH_PARENT/android.view.WindowManager.LayoutParams.WRAP_CONTENT,具体代码如下:

  1. View view = getLayoutInflater().inflate(R.layout.popup_dialog, null);  
  2. AlertDialog mDialog = new AlertDialog.Builder(this).create();  
  3.         mDialog.show();// 显示创建的AlertDialog,并显示,必须放在Window设置属性之前  
  4.   
  5. /** 
  6.  *设置mDialog窗口属性:MATCH_PARENT/WRAP_CONTENT 
  7.  * 
  8.  */  
  9. Window window =mDialog.getWindow();  
  10.         window.setGravity(Gravity.BOTTOM); // 此处可以设置dialog显示的位置  
  11.         window.setLayout(android.view.WindowManager.LayoutParams.MATCH_PARENT,  
  12.                 android.view.WindowManager.LayoutParams.WRAP_CONTENT);  

第二种方式:setAttributes()

获得Window对象后,设置Window对象的属性值,即调用setAttributes(LayoutParams)方法,LayoutParams的width变量取值:android.view.WindowManager.LayoutParams.MATCH_PARENT/android.view.WindowManager.LayoutParams.WRAP_CONTENT,同理height变量取值:android.view.WindowManager.LayoutParams.MATCH_PARENT/android.view.WindowManager.LayoutParams.WRAP_CONTENT,具体代码如下:

  1. View view = getLayoutInflater().inflate(R.layout.popup_dialog, null);  
  2. AlertDialog mDialog = new AlertDialog.Builder(this).create();  
  3.         mDialog.show();// 显示创建的AlertDialog,并显示,必须放在Window设置属性之前  
  4.   
  5. Window window =mDialog.getWindow();  
  6.          window.setGravity(Gravity.BOTTOM); // 此处可以设置dialog显示的位置  
  7. WindowManager.LayoutParams mParams = window.getAttributes();  
  8.          mParams.width = android.view.WindowManager.LayoutParams.MATCH_PARENT;  
  9.          mParams.height = android.view.WindowManager.LayoutParams.WRAP_CONTENT;  
  10.          window.setGravity(Gravity.BOTTOM); // 此处可以设置dialog显示的位置  
  11.          window.setAttributes(mParams);  

第三种方式:setLayout()

具体代码如下:

  1. View view = getLayoutInflater().inflate(R.layout.popup_dialog, null);  
  2. AlertDialog mDialog = new AlertDialog.Builder(this).create();  
  3.         mDialog.show();// 显示创建的AlertDialog,并显示,必须放在Window设置属性之前  
  4.   
  5. Window window =mDialog.getWindow();  
  6.         window.setGravity(Gravity.BOTTOM); // 此处可以设置dialog显示的位置  
  7. WindowManager manager = getWindowManager();  
  8.          Display display = manager.getDefaultDisplay();  
  9.          int width = display.getWidth();//获取当前屏幕宽度  
  10.          int height = 300;//自定义高度值,比如:300dp  
  11.          window.setGravity(Gravity.BOTTOM); // 此处可以设置dialog显示的位置  
  12.          window.setLayout(width, height);  

三.弹窗动画基础知识

Android的基本动画包括:渐变动画/平移动画/缩放动画/旋转动画/组合动画,更多内容可以参考《Android代码绘制虚线、圆角、渐变和阴影效果图》,点击“分享”按钮,弹窗从底部弹窗,再次点击弹窗消失,设置的动画——平移动画,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!--enter_dialog_anim.xml,弹窗进入动画-->  
  3. <translate xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     android:duration="300"  
  5.     android:fromYDelta="100%">  
  6.   
  7. </translate>  
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!--exit_dialog_anim.xml,弹窗退出动画-->  
  3. <translate xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     android:duration="300"  
  5.     android:toYDelta="100%" >  
  6.   
  7. </translate>  

在style.xml文件中添加Window进入和退出分别引用的动画类型,代码如下:

  1. <!-- 分享功能弹窗动画 -->  
  2. <style name="popup_style" parent="android:Animation">  
  3.         <item name="@android:windowEnterAnimation">@anim/enter_dialog_anim</item>  
  4.         <item name="@android:windowExitAnimation">@anim/exit_dialog_anim</item>  
  5. </style>  

在Window属性设置中调用setContentView()指定View对象,同时调用setWindowAnimations()指定添加的动画,代码如下:

  1. window.setContentView(view);//这一步必须指定,否则不出现弹窗  
  2. window.setWindowAnimations(R.style.popup_style); // 添加动画  

四.自定义弹窗:MyDialogActivity

自定义MyDialogActivity实现AlertDialog同样的功能,点击“分享按钮”,从窗口底部弹出弹窗,点击“取消”弹窗消息,最终效果和AlertDialog实现的弹窗效果一模一样,如下图:

popup-mydialog-demo

开发步骤:

1.定义布局popup_main.xml。popup_main.xml定义弹窗最终展示的样子,可以放置多个平台的分享按钮,比如:微信/微博/空间/人人等,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!-- 底部弹窗布局 -->  
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:background="@color/transparent"  
  7.     android:orientation="vertical" >  
  8.   
  9.     <LinearLayout  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="wrap_content"  
  12.         android:orientation="horizontal" >  
  13.   
  14.         <TextView  
  15.             android:id="@+id/share_weibo_tv"  
  16.             android:layout_width="0dp"  
  17.             android:layout_height="wrap_content"  
  18.             android:layout_margin="@dimen/share_padding"  
  19.             android:layout_weight="1"  
  20.             android:gravity="center_horizontal"  
  21.             android:text="@string/weibo" />  
  22.   
  23.         <TextView  
  24.             android:id="@+id/share_weixin_tv"  
  25.             android:layout_width="0dp"  
  26.             android:layout_height="wrap_content"  
  27.             android:layout_margin="@dimen/share_padding"  
  28.             android:layout_weight="1"  
  29.             android:gravity="center_horizontal"  
  30.             android:text="@string/weixin" />  
  31.     </LinearLayout>  
  32.   
  33.     <LinearLayout  
  34.         android:layout_width="match_parent"  
  35.         android:layout_height="wrap_content"  
  36.         android:orientation="horizontal" >  
  37.   
  38.         <TextView  
  39.             android:id="@+id/share_kongjian_tv"  
  40.             android:layout_width="0dp"  
  41.             android:layout_height="wrap_content"  
  42.             android:layout_margin="@dimen/share_padding"  
  43.             android:layout_weight="1"  
  44.             android:gravity="center_horizontal"  
  45.             android:text="@string/kongjian" />  
  46.   
  47.         <TextView  
  48.             android:id="@+id/share_qq_tv"  
  49.             android:layout_width="0dp"  
  50.             android:layout_height="wrap_content"  
  51.             android:layout_margin="@dimen/share_padding"  
  52.             android:layout_weight="1"  
  53.             android:gravity="center_horizontal"  
  54.             android:text="@string/qq" />  
  55.     </LinearLayout>  
  56.   
  57.     <Button  
  58.         android:id="@+id/cancel_btn"  
  59.         android:layout_width="match_parent"  
  60.         android:layout_height="wrap_content"  
  61.         android:layout_margin="@dimen/activity_vertical_margin"  
  62.         android:background="@drawable/btn_bg"  
  63.         android:text="@string/cancel" />  
  64.   
  65. </LinearLayout>  

2.定义Theme样式。Theme样式定义在style.xml文件中,在AndroidManifest.xml文件中的标签的android:theme=""属性中引用,代码如下:

  1. <!-- MyDialogActivity自定义Threme -->  
  2. <style name="Theme.CustomDialog" parent="@android:style/Theme.Dialog">  
  3.         <item name="android:windowNoTitle">true</item>  
  4.         <!-- 设置title -->  
  5.         <item name="android:windowBackground">@android:color/transparent</item>  
  6.         <item name="android:windowFrame">@null</item>  
  7.         <!-- 设置边框 -->  
  8.         <item name="android:windowIsTranslucent">true</item>  
  9.         <!-- 设置半透明 -->  
  10.         <item name="android:windowFullscreen">true</item>  
  11.         <!-- 设置全屏 -->  
  12. </style>  
  1. <activity android:name="MyDialogActivity" android:theme="@style/Theme.CustomDialog"/>  

3.实现MyDialogActivity具体功能

  1. package cn.teachcourse.main;  
  2.   
  3. import android.annotation.SuppressLint;  
  4. import android.app.Activity;  
  5. import android.graphics.Bitmap;  
  6. import android.graphics.BitmapFactory;  
  7. import android.graphics.drawable.BitmapDrawable;  
  8. import android.graphics.drawable.Drawable;  
  9. import android.os.Bundle;  
  10. import android.view.Gravity;  
  11. import android.view.View;  
  12. import android.view.View.OnClickListener;  
  13. import android.view.Window;  
  14. import android.widget.Button;  
  15. import android.widget.TextView;  
  16.   
  17. /* 
  18.  @author postmaster@teachcourse.cn 
  19.  @date 创建于:2016-4-14 
  20.  */  
  21. public class MyDialogActivity extends Activity implements OnClickListener {  
  22.     private View view;  
  23.   
  24.     @Override  
  25.     protected void onCreate(Bundle savedInstanceState) {  
  26.         // TODO Auto-generated method stub  
  27.         super.onCreate(savedInstanceState);  
  28.         view = getLayoutInflater().inflate(R.layout.popup_main, nullfalse);  
  29.         setContentView(view);  
  30.         initView();  
  31.     }  
  32.   
  33.     private void initView() {  
  34.         Window window = getWindow();  
  35.         window.setLayout(android.view.ViewGroup.LayoutParams.MATCH_PARENT,  
  36.                 android.view.ViewGroup.LayoutParams.WRAP_CONTENT);  
  37.         window.setGravity(Gravity.BOTTOM);  
  38.         window.setWindowAnimations(R.style.popup_style); // 添加动画  
  39.   
  40.         TextView weibo_tv = (TextView) view.findViewById(R.id.share_weibo_tv);  
  41.         TextView weixin_tv = (TextView) view.findViewById(R.id.share_weixin_tv);  
  42.         TextView qq_tv = (TextView) view.findViewById(R.id.share_qq_tv);  
  43.         TextView kongjian_tv = (TextView) view  
  44.                 .findViewById(R.id.share_kongjian_tv);  
  45.         Button cancel_btn = (Button) view.findViewById(R.id.cancel_btn);  
  46.         // 添加控件事件  
  47.         weibo_tv.setOnClickListener(this);  
  48.         weixin_tv.setOnClickListener(this);  
  49.         qq_tv.setOnClickListener(this);  
  50.         kongjian_tv.setOnClickListener(this);  
  51.         cancel_btn.setOnClickListener(this);  
  52.           
  53.         // 调整图片的大小/位置  
  54.         abjustDrawablePos(weibo_tv, R.drawable.share_weibo);  
  55.         abjustDrawablePos(weixin_tv, R.drawable.share_weixin);  
  56.         abjustDrawablePos(kongjian_tv, R.drawable.share_kongjian);  
  57.         abjustDrawablePos(qq_tv, R.drawable.share_qq);  
  58.   
  59.     }  
  60.   
  61.     /** 
  62.      * 添加图标和调整位置 
  63.      *  
  64.      * @param tv 
  65.      * @param draw 
  66.      */  
  67.     @SuppressLint("ResourceAsColor")  
  68.     private void abjustDrawablePos(TextView tv, int draw) {  
  69.         Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), draw);  
  70.         mBitmap = centerSquareScaleBitmap(mBitmap, 250);  
  71.         Drawable drawable = new BitmapDrawable(mBitmap);  
  72.         drawable.setBounds(048048);// 设置图片的边界  
  73.         tv.setTextColor(R.color.fontcolor);  
  74.         tv.setCompoundDrawables(null, drawable, nullnull);// setCompoundDrawables()和setBounds()方法一起使用  
  75.         // 添加TextView图标  
  76.         tv.setCompoundDrawablesWithIntrinsicBounds(null, drawable, nullnull);  
  77.         tv.setCompoundDrawablePadding(10);// 设置图片和text之间的间距  
  78.         if (mBitmap != null) {  
  79.             mBitmap = null;  
  80.             drawable = null;  
  81.         }  
  82.     }  
  83.   
  84.     /** 
  85.      *  
  86.      * @param bitmap 
  87.      *            原图 
  88.      * @param edgeLength 
  89.      *            希望得到的正方形部分的边长 
  90.      * @return 缩放截取正中部分后的位图。 
  91.      */  
  92.     public static Bitmap centerSquareScaleBitmap(Bitmap bitmap, int edgeLength) {  
  93.         if (null == bitmap || edgeLength <= 0) {  
  94.             return null;  
  95.         }  
  96.   
  97.         Bitmap result = bitmap;  
  98.         int widthOrg = bitmap.getWidth();  
  99.         int heightOrg = bitmap.getHeight();  
  100.   
  101.         if (widthOrg >= edgeLength && heightOrg >= edgeLength) {  
  102.             // 压缩到一个最小长度是edgeLength的bitmap  
  103.             int longerEdge = (int) (edgeLength * Math.max(widthOrg, heightOrg) / Math  
  104.                     .min(widthOrg, heightOrg));  
  105.   
  106.             int scaledWidth = widthOrg > heightOrg ? longerEdge : edgeLength;  
  107.             int scaledHeight = widthOrg > heightOrg ? edgeLength : longerEdge;  
  108.             Bitmap scaledBitmap;  
  109.   
  110.             try {  
  111.                 scaledBitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth,  
  112.                         scaledHeight, true);  
  113.             } catch (Exception e) {  
  114.                 return null;  
  115.             }  
  116.   
  117.             // 从图中截取正中间的正方形部分。  
  118.             int xTopLeft = (scaledWidth - edgeLength) / 2;  
  119.             int yTopLeft = (scaledHeight - edgeLength) / 2;  
  120.   
  121.             try {  
  122.                 result = Bitmap.createBitmap(scaledBitmap, xTopLeft, yTopLeft,  
  123.                         edgeLength, edgeLength);  
  124.                 scaledBitmap.recycle();  
  125.             } catch (Exception e) {  
  126.                 return null;  
  127.             }  
  128.         }  
  129.   
  130.         return result;  
  131.     }  
  132.   
  133.     @Override  
  134.     public void onClick(View v) {  
  135.         switch (v.getId()) {  
  136.         /** 
  137.          * 点击分享图标,弹出分享界面 
  138.          */  
  139.         case R.id.share_to_btn:  
  140.               
  141.             break;  
  142.         case R.id.share_weibo_tv:  
  143.   
  144.             break;  
  145.         case R.id.share_weixin_tv:  
  146.   
  147.             break;  
  148.         case R.id.share_qq_tv:  
  149.   
  150.             break;  
  151.         case R.id.share_kongjian_tv:  
  152.   
  153.             break;  
  154.         case R.id.cancel_btn:  
  155.             finish();  
  156.               
  157.             break;  
  158.   
  159.         default:  
  160.             break;  
  161.         }  
  162.   
  163.     }  
  164. }  

4.弹出弹窗,调用startActivity(this,MyDialogActivity.class)

关注公众号 扫一扫二维码,加我QQ

如果文章对你有帮助,欢迎点击上方按钮关注作者

来源:TeachCourse每周一次,深入学习Android教程,关注(QQ1589359239或公众号TeachCourse)
转载请注明出处:http://teachcourse.cn/1659.html

资源分享

源码下载
分类:Android, Java基础 标签:,
Android开发之TextView控件设置颜色切换器的问题 Android开发之TextView控件设
浅谈Android SDK 浅谈Android SDK
Android学习笔记六:Java基础知识 Android学习笔记六:Java基础知
MVP设计模式嵌入百度地图小结 MVP设计模式嵌入百度地图小结

发表评论

呲牙 憨笑 坏笑 偷笑 色 微笑 抓狂 睡觉 酷 流汗 鼓掌 大哭 可怜 疑问 晕 惊讶 得意 尴尬 发怒 奋斗 衰 骷髅 啤酒 吃饭 礼物 强 弱 握手 OK NO 勾引 拳头 差劲 爱你

表情

  1. yumanutong
    yumanutong 【农民】 @回复

    自动弹有时候不友好啊

    • TeachCourse
      TeachCourse 【县长】【站长】 @回复

      这里的弹窗不是类似广告的弹窗,而是一种Android开发中非常友好的一种视图,不要误解