(转)关于PopupWindow的showAsDropDown()和showAtLocation()使用方式及其区别

原地址:http://blog.csdn.net/lnn368/article/details/51185732


先看下demo的效果图,说明都在代码里面注释。


以下是个人编写代码:

1.MainActivity部分

[java]  view plain  copy
  1. package com.example.lainanzhou.popupwindoewlocation;  
  2.   
  3. import android.app.Activity;  
  4. import android.graphics.drawable.BitmapDrawable;  
  5. import android.os.Bundle;  
  6. import android.util.Log;  
  7. import android.view.Gravity;  
  8. import android.view.LayoutInflater;  
  9. import android.view.View;  
  10. import android.view.ViewGroup;  
  11. import android.view.animation.AlphaAnimation;  
  12. import android.view.animation.Animation;  
  13. import android.view.animation.AnimationSet;  
  14. import android.view.animation.Interpolator;  
  15. import android.view.animation.ScaleAnimation;  
  16. import android.widget.Button;  
  17. import android.widget.PopupWindow;  
  18. import android.widget.RelativeLayout;  
  19. import android.widget.TextView;  
  20.   
  21. /** 
  22.  * Android的对话框有两种:PopupWindow和AlertDialog。它们的不同点在于: 
  23.  * •AlertDialog的位置固定,而PopupWindow的位置可以随意 
  24.  * •AlertDialog是非阻塞线程的,而PopupWindow是阻塞线程的 
  25.  * •PopupWindow的位置按照有无偏移分,可以分为偏移和无偏移两种;按照参照物的不同, 
  26.  * 可以分为相对于某个控件(Anchor锚)和相对于父控件。具体如下 
  27.  * •showAsDropDown(View anchor):相对某个控件的位置(正左下方),无偏移 
  28.  * •showAsDropDown(View anchor,int xoff,int yoff):相对某个控件的位置,有偏移 
  29.  * •showAtLocation(View parent,int gravity,int x,int y):相对于父控件的位置 
  30.  * (例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移 
  31.  */  
  32.   
  33.   
  34. public class MainActivity extends Activity implements View.OnClickListener {  
  35.   
  36.     private TextView mTv;  
  37.     private TextView mMainView;  
  38.     private RelativeLayout mRl_parent;  
  39.     private PopupWindow mPopupWindow;  
  40.     private int mWidth;  
  41.     private boolean mIsClick5;  
  42.   
  43.     @Override  
  44.     protected void onCreate(Bundle savedInstanceState) {  
  45.         super.onCreate(savedInstanceState);  
  46.         setContentView(R.layout.activity_main);  
  47.         mTv = (TextView) findViewById(R.id.tv);  
  48.         mMainView = (TextView) findViewById(R.id.tv_mainView);  
  49.         mRl_parent = (RelativeLayout) findViewById(R.id.rl_parent);  
  50.         Button mButton01 = (Button) findViewById(R.id.button01);  
  51.         Button mButton02 = (Button) findViewById(R.id.button02);  
  52.         Button mButton03 = (Button) findViewById(R.id.button03);  
  53.         Button mButton04 = (Button) findViewById(R.id.button04);  
  54.         Button mButton05 = (Button) findViewById(R.id.button05);  
  55.         mButton01.setOnClickListener(this);  
  56.         mButton02.setOnClickListener(this);  
  57.         mButton03.setOnClickListener(this);  
  58.         mButton04.setOnClickListener(this);  
  59.         mButton05.setOnClickListener(this);  
  60.     }  
  61.   
  62.     /** 
  63.      * 根据类型设置显示的popupWindow方式 
  64.      * 
  65.      * @param type 1.为直接显示在某控件下方+点击外部不可关闭 
  66.      *             2.显示在某控件下方+点击外部可关闭 
  67.      *             3.相对父容器中心显示位置+点击外部可关闭 
  68.      *             4.相对父容器脚部显示位置+点击外部可关闭 
  69.      *             5.默认点击外部可关闭 
  70.      */  
  71.     private void initPopupWindow(int type) {  
  72.         LayoutInflater layoutInflater = LayoutInflater.from(this);  
  73.         View popupWindow = layoutInflater.inflate(R.layout.popup_window, null);  
  74.         //mode共有三种情况,取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY, MeasureSpec.AT_MOST。  
  75.         // MeasureSpec.EXACTLY是(完全)精确尺寸,父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;  
  76.         //      当我们将控件的layout_width或layout_height指定为具体数值时  
  77.         //      如andorid:layout_width="50dip",或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。  
  78.         // MeasureSpec.AT_MOST是(至多)最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,  
  79.         //      控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。  
  80.         //      因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。  
  81.         // MeasureSpec.UNSPECIFIED是未指定尺寸,父元素不对子元素施加任何束缚,子元素可以得到任意想要的大小;  
  82.         //      这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。  
  83.         //以下方式是为了在popupWindow还没有弹出显示之前就测量获取其宽高(单位是px相熟)  
  84.         int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);  
  85.         int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);  
  86.         TextView mTextView = (TextView) popupWindow.findViewById(R.id.tv_popupTv);  
  87.         mTextView.measure(w, h);  
  88.         mWidth = mTextView.getMeasuredWidth();//获取测量宽度px  
  89.         int mHeight = mTextView.getMeasuredHeight();//获取测量高度px  
  90.   
  91.         //设置点击popupWindow里面文本可以dismiss该popupWindow  
  92.         popupWindow.findViewById(R.id.tv_popupTv).setOnClickListener(new View.OnClickListener() {  
  93.             @Override  
  94.             public void onClick(View v) {  
  95.                 if (mPopupWindow != null && mPopupWindow.isShowing()) {  
  96.                     mPopupWindow.dismiss();  
  97.                 }  
  98.             }  
  99.         });  
  100.         // 创建一个PopupWindow  
  101.         // 参数1:contentView 指定PopupWindow的显示View  
  102.         // 参数2:width 指定PopupWindow的width可以固定死某些数值:  
  103.         //       如果不想固定死可以设置为ViewGroup.LayoutParams.WRAP_CONTENT/MATCH_CONTENT  
  104.         // 参数3:height 指定PopupWindow的height  
  105.         mPopupWindow = new PopupWindow(popupWindow, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);  
  106.   
  107.         //设置动画两种方式:动画效果可以参考该网址 http://blog.csdn.net/xiaanming/article/details/8997260  
  108.         //方式1:xml配置文件  
  109.         //        mPopupWindow.setAnimationStyle(R.anim.popupwindow_enter);  
  110.         //方式2:直接设置该popupWindow中的View的动画  
  111.         //        setPopupAnimation(popupWindow);  
  112.   
  113.         mPopupWindow.setFocusable(true); //这里很重要,设置该popupWindow可以获取焦点,不然无法响应点击事件  
  114.   
  115.         switch (type) {  
  116.             case 1:  
  117.                 //方式2:直接设置该popupWindow中的View的动画  
  118.                 setPopupAnimation(popupWindow);  
  119.                 //6.0无效  
  120.                 mPopupWindow.setOutsideTouchable(false);//设置点击外面不可以消失~注意该效果在设置背景的情况下是无效的  
  121.                 break;  
  122.             case 2:  
  123.                 //方式1:xml配置文件  
  124.                 mPopupWindow.setAnimationStyle(R.anim.popupwindow_enter);  
  125.                 mPopupWindow.setBackgroundDrawable(new BitmapDrawable());  
  126.                 mPopupWindow.setOutsideTouchable(true);//设置点击外面可以消失~注意则必须要设置该popupWindow背景才有效  
  127.                 break;  
  128.             case 3:  
  129.                 //方式2:直接设置该popupWindow中的View的动画  
  130.                 setPopupAnimation(popupWindow);  
  131.                 //6.0无效  
  132.                 mPopupWindow.setOutsideTouchable(false);//设置点击外面不可以消失~注意该效果在设置背景的情况下是无效的  
  133.                 break;  
  134.             case 4:  
  135.                 //方式1:xml配置文件  
  136.                 mPopupWindow.setAnimationStyle(R.anim.popupwindow_enter);  
  137.                 mPopupWindow.setBackgroundDrawable(new BitmapDrawable());  
  138.                 mPopupWindow.setOutsideTouchable(true);//设置点击外面可以消失~注意则必须要设置该popupWindow背景才有效  
  139.                 break;  
  140.             case 5:  
  141.                 mMainView.setVisibility(mIsClick5 ? View.VISIBLE : View.GONE);  
  142.                 RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, dip2px(48));  
  143.                 mMainView.measure(w, h);  
  144.                 int mMainViewWidth = mMainView.getMeasuredWidth();//获取测量宽度px  
  145.                 int width = (mTv.getWidth() - mMainViewWidth) / 2;//获取x轴偏移量px  
  146.                 params.setMargins(mTv.getLeft() + width, mTv.getHeight(), 00);  
  147.                 mMainView.setLayoutParams(params);//设置位置  
  148.                 if (mIsClick5)  
  149.                     mMainView.setAnimation(getAnimation());//设置动画  
  150.                 break;  
  151.             default:  
  152.                 //方式1:xml配置文件  
  153.                 mPopupWindow.setAnimationStyle(R.anim.popupwindow_enter);  
  154.                 mPopupWindow.setBackgroundDrawable(new BitmapDrawable());  
  155.                 mPopupWindow.setOutsideTouchable(true);//设置点击外面可以消失~注意则必须要设置该popupWindow背景才有效  
  156.                 break;  
  157.   
  158.         }  
  159.     }  
  160.   
  161.     /** 
  162.      * 动画效果 
  163.      * 
  164.      * @return 
  165.      */  
  166.     public Animation getAnimation() {  
  167.         AlphaAnimation localAlphaAnimation = new AlphaAnimation(0.0F, 1.0F);  
  168.         localAlphaAnimation.setInterpolator(new Interpolator() {  
  169.             public float getInterpolation(float paramFloat) {  
  170.                 return 10.0F * paramFloat;  
  171.             }  
  172.         });  
  173.         localAlphaAnimation.setDuration(500L);  
  174.         ScaleAnimation localScaleAnimation = new ScaleAnimation(0.0F, 1.0F, 0.0F, 1.0F, 10.5F, -10.0F);  
  175.         localScaleAnimation.setDuration(500L);  
  176.         AnimationSet localAnimationSet = new AnimationSet(true);  
  177.         localAnimationSet.addAnimation(localScaleAnimation);  
  178.         localAnimationSet.addAnimation(localAlphaAnimation);  
  179.         return localAnimationSet;  
  180.     }  
  181.   
  182.     /** 
  183.      * 设置组合动画 
  184.      * 
  185.      * @param paramView 
  186.      */  
  187.     private void setPopupAnimation(View paramView) {  
  188.         //透明度动画  
  189.         AlphaAnimation localAlphaAnimation = new AlphaAnimation(0.0F, 1.0F);  
  190.         localAlphaAnimation.setInterpolator(new Interpolator() {  
  191.             public float getInterpolation(float paramFloat) {  
  192.                 return 10.0F * paramFloat;  
  193.             }  
  194.         });  
  195.         localAlphaAnimation.setDuration(800L);//动画持续时长  
  196.         //缩放动画:  
  197.         // 参数:  
  198.         // 1.为x轴起始缩放度 2.为x结束缩放度  
  199.         // 3.为y起始缩放度 4.为y结束缩放度  
  200.         // 5.为相对x轴类型为顶部 6.为该类型上起始度(0.5f为中间位置)  
  201.         // 7.为相对y轴类型 8.为该类型起始位置(0F为原位置)  
  202.         ScaleAnimation localScaleAnimation = new ScaleAnimation(0F, 1.0F, 0F, 1.0F, Animation.ZORDER_TOP, 0.5F, Animation.ZORDER_TOP, 0F);  
  203.         localScaleAnimation.setDuration(500L);//动画持续时长  
  204.         AnimationSet localAnimationSet = new AnimationSet(true);  
  205.         localAnimationSet.addAnimation(localScaleAnimation);  
  206.         localAnimationSet.addAnimation(localAlphaAnimation);  
  207.         paramView.startAnimation(localAnimationSet);  
  208.     }  
  209.   
  210.     /** 
  211.      * dip与px之间转换 
  212.      * 
  213.      * @param dipValue 
  214.      * @return 
  215.      */  
  216.   
  217.     private int dip2px(float dipValue) {  
  218.         final float scale = getResources().getDisplayMetrics().density;  
  219.         return (int) (dipValue * scale + 0.5f);  
  220.     }  
  221.   
  222.     private int px2dip(float pxValue) {  
  223.         final float scale = getResources().getDisplayMetrics().density;  
  224.         return (int) (pxValue / scale + 0.5f);  
  225.     }  
  226.   
  227.     @Override  
  228.     public void onClick(View v) {  
  229.         switch (v.getId()) {  
  230.             // 相对某个控件的位置(正左下方),无偏移  
  231.             case R.id.button01:  
  232.                 initPopupWindow(1);  
  233.                 mPopupWindow.showAsDropDown(mTv);  
  234.                 break;  
  235.   
  236.             // 相对某个控件的位置(正左下方),有偏移  
  237.             case R.id.button02:  
  238.                 initPopupWindow(2);  
  239.                 //以下为分步介绍控件获取中间位置偏移量方式:(对应控件宽度-popup宽度)/2  
  240.                 int tv_width = mTv.getWidth();//获取对应的控件view宽度px值  
  241.                 int popup_width = dip2px(120);//将popupWindow宽度转为px值(这里的popup宽度是写死了的)  
  242.                 int width = (tv_width - mWidth) / 2;//获取x轴偏移量px  
  243.                 mPopupWindow.showAsDropDown(mTv, width, 0);//设置x轴偏移量:注意单位为px  
  244.                 break;  
  245.   
  246.             // 相对于父控件的位置,无偏移~参数1为父容器~参数2为相对父容器相对类型~参数34为偏移量  
  247.             case R.id.button03:  
  248.                 initPopupWindow(3);  
  249.                 //int[] locaitons = new int[2];//存放相应控件在屏幕的xy轴坐标点;单位px  
  250.                 //mTv.getLocationOnScreen(locaitons);//locaitons[0]为x轴 locaitons[1]为y轴  
  251.                 // X、Y方向偏移量:设置x轴偏移量为相应控件中心;y轴无偏移  
  252.                 mPopupWindow.showAtLocation(mRl_parent, Gravity.CENTER, 00);  
  253.                 break;  
  254.   
  255.             // 相对于父控件的位置,有偏移~参数1为父容器~参数2为相对父容器相对类型~参数34为偏移量  
  256.             case R.id.button04:  
  257.                 initPopupWindow(4);  
  258.                 mPopupWindow.showAtLocation(mRl_parent, Gravity.BOTTOM, 00);  
  259.                 break;  
  260.             case R.id.button05:  
  261.                 mIsClick5 = !mIsClick5;  
  262.                 initPopupWindow(5);  
  263.                 break;  
  264.             default:  
  265.                 break;  
  266.   
  267.         }  
  268.     }  
  269. }  

2.activity_main.xml部分

[html]  view plain  copy
  1. <RelativeLayout android:id="@+id/rl_parent"  
  2.                 xmlns:android="http://schemas.android.com/apk/res/android"  
  3.                 android:layout_width="fill_parent"  
  4.                 android:layout_height="fill_parent">  
  5.   
  6.     <TextView  
  7.         android:id="@+id/tv"  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:layout_centerHorizontal="true"  
  11.         android:gravity="center"  
  12.         android:text="popupwindow相对该view显示位置"/>  
  13.   
  14.     <TextView  
  15.         android:id="@+id/tv_mainView"  
  16.         android:layout_width="wrap_content"  
  17.         android:layout_height="48dp"  
  18.         android:gravity="center"  
  19.         android:text="我是MainView"  
  20.         android:textColor="#333333"  
  21.         android:background="#dddddd"  
  22.         android:visibility="gone"/>  
  23.   
  24.     <LinearLayout  
  25.         android:layout_width="match_parent"  
  26.         android:layout_height="wrap_content"  
  27.         android:layout_alignParentBottom="true"  
  28.         android:layout_marginBottom="18dp"  
  29.         android:orientation="vertical">  
  30.   
  31.         <Button  
  32.             android:id="@+id/button01"  
  33.             android:layout_width="fill_parent"  
  34.             android:layout_height="wrap_content"  
  35.             android:text="直接显示在某控件下方,不偏移且点击外面不可关闭"/>  
  36.   
  37.         <Button  
  38.             android:id="@+id/button02"  
  39.             android:layout_width="fill_parent"  
  40.             android:layout_height="wrap_content"  
  41.             android:text="显示在某控件下方,有偏移且点击外面可关闭"/>  
  42.   
  43.         <Button  
  44.             android:id="@+id/button03"  
  45.             android:layout_width="fill_parent"  
  46.             android:layout_height="wrap_content"  
  47.             android:text="相对父容器中心显示位置,不偏移且点击外面不可关闭"/>  
  48.   
  49.         <Button  
  50.             android:id="@+id/button04"  
  51.             android:layout_width="fill_parent"  
  52.             android:layout_height="wrap_content"  
  53.             android:text="相对父容器脚部显示位置,下方中间且点击外面可关闭"/>  
  54.   
  55.         <Button  
  56.             android:id="@+id/button05"  
  57.             android:layout_width="fill_parent"  
  58.             android:layout_height="wrap_content"  
  59.             android:text="直接使用view显示,随便设置弹出位置"/>  
  60.   
  61.     </LinearLayout>  
  62. </RelativeLayout>  

3.popup_window.xml部分

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.                 android:layout_width="match_parent"  
  4.                 android:layout_height="match_parent"  
  5.                 android:background="#dddddd"  
  6.                 android:orientation="vertical">  
  7.   
  8.     <TextView  
  9.         android:id="@+id/tv_popupTv"  
  10.         android:layout_width="wrap_content"  
  11.         android:layout_height="48dp"  
  12.         android:layout_centerInParent="true"  
  13.         android:gravity="center"  
  14.         android:text="我是PopupWindow"  
  15.         android:textColor="#333333"/>  
  16.   
  17.   
  18. </RelativeLayout>  

4.popupwindow_enter.xml动画xml

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <set xmlns:android="http://schemas.android.com/apk/res/android">  
  3.     <!--位移动画:1为持续时长;2为X轴起始位置;3为X轴到达位置 ~看需求还可以添加设置Y轴位置-->  
  4.     <!--X轴相对左右方向,Y轴相对上下方向-->  
  5.     <translate  
  6.         android:duration="500"  
  7.         android:fromYDelta="-100"  
  8.         android:toYDelta="0"/>  
  9. </set>  

以上为相关代码。

源码下载链接:源码下载


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值