PopupWindow

PopupWindow的构造函数

public PopupWindow(View contentView, int width, int height, boolean focusable)

其中contentView为要显示的view,width和height为宽和高,
值为像素值,可以是MATCHT_PARENT和WRAP_CONTENT
来设置,如果focusable为false,在一个Activity弹出一个PopupWindow,按返回键,由于PopupWindow没有焦点,会直接退出Activity。如果focusable为true,PopupWindow弹出后,所有的触屏和物理按键都有PopupWindows处理。
如果PopupWindow中有Editor的话,focusable要为true。

下面来看一个简单的demo
主界面:就简单放一个button,点击弹出我们需要的PopupWindow

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:id="@+id/container"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent" >  
    <Button  
        android:id="@+id/btnOpen"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_centerInParent="true"  
        android:text="@string/app_name" />  
</RelativeLayout>  

popupwindow 界面:放了2个button 和一个文本框,用来输入值

<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:background="#b5555555" >  
    <LinearLayout  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:layout_alignParentBottom="true"  
        android:background="#eee"  
        android:orientation="vertical" >  
        <EditText  
            android:id="@+id/leaveword"  
            android:layout_width="fill_parent"  
            android:layout_height="wrap_content"  
            android:layout_marginBottom="20dp"  
            android:layout_marginLeft="20dp"  
            android:layout_marginRight="20dp"  
            android:layout_marginTop="20dp"  
            android:gravity="top"  
            android:hint="说点什么吧~"  
            android:inputType="textMultiLine"  
            android:lineSpacingExtra="6.0dp"  
            android:maxHeight="150dp"  
            android:minHeight="100dp"  
            android:paddingLeft="10.0dp"  
            android:paddingRight="10.0dp"  
            android:paddingTop="10.0dp" />  
        <LinearLayout  
            android:layout_width="fill_parent"  
            android:layout_height="wrap_content"  
            android:layout_marginBottom="20dp"  
            android:gravity="center"  
            android:orientation="horizontal" >  
            <Button  
                android:id="@+id/confirmButton"  
                android:layout_width="80.0dip"  
                android:layout_height="wrap_content"  
                android:gravity="center"  
                android:text="发表"  
                android:textColor="#fff"  
                android:textSize="16.0sp" />  
            <Button  
                android:id="@+id/cancleButton"  
                android:layout_width="80.0dip"  
                android:layout_height="wrap_content"  
                android:layout_marginLeft="30dp"  
                android:gravity="center"  
                android:text="取消"  
                android:textColor="#565656"  
                android:textSize="16.0sp" />  
        </LinearLayout>  
    </LinearLayout>  
</RelativeLayout>  

这样我们的界面布局就算完成了,下来我们来看一个Activity。写个了OpenView方法来弹出view

public void OpenView() {  
    LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);  
    popupWindowView = inflater.inflate(R.layout.popupwindow, null);  
    popupWindow = new PopupWindow(popupWindowView,  
            LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, true);  
    // 设置PopupWindow的弹出和消失效果  
    popupWindow.setAnimationStyle(R.style.popupAnimation);  
    btnsure = (Button) popupWindowView.findViewById(R.id.confirmButton);  
    btnsure.setOnClickListener(new ButtonOnClickListener());  
    cancleButton = (Button) popupWindowView.findViewById(R.id.cancleButton);  
    cancleButton.setOnClickListener(new ButtonOnClickListener());  
    leaveword = (EditText) popupWindowView.findViewById(R.id.leaveword);  
    popupWindow.showAtLocation(btnsure, Gravity.CENTER, 0, 0);  
}  

我们看到弹出来的有点动画效果,是因为我们在弹出时,加上了

popupWindow.setAnimationStyle(R.style.popupAnimation); 

我们需要在在styles.xml下加上popupAnimation

<style name="popupAnimation" parent="android:Animation">  
   <item name="android:windowEnterAnimation">@anim/in</item>  
   <item name="android:windowExitAnimation">@anim/out</item>  
lt;/style> 

在工程res下新建anim文件夹,在anim文件夹先新建两个xml文件

in.xml

<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android" >  
    <translate  
        android:duration="1500"  
        android:fromYDelta="5000"  
        android:toYDelta="0" />  
</set>  

out.xml

<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android">  
    <translate  
        android:fromYDelta="0"  
        android:toYDelta="5000"  
        android:duration="1500"  
    />  
</set>  

如果想要关闭弹出框
调用popupWindow.dismiss();就好.
完整的Activity源码

public class MainActivity extends Activity {
        private View popupWindowView;
        private PopupWindow popupWindow;
        private Button btnsure, cancleButton, btnOpen;
        private EditText leaveword;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);  
            btnOpen = (Button) findViewById(R.id.btnOpen);
            btnOpen.setOnClickListener(new ButtonOnClickListener());
        }

        public void OpenView() {
            LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
            popupWindowView = inflater.inflate(R.layout.popupwindow, null);
            popupWindow = new PopupWindow(popupWindowView,
                    LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, true);
            // 设置PopupWindow的弹出和消失效果  
            popupWindow.setAnimationStyle(R.style.popupAnimation);
            btnsure = (Button) popupWindowView.findViewById(R.id.confirmButton);
            btnsure.setOnClickListener(new Butto
                    ```

                    nOnClickListener());
            cancleButton = (Button) popupWindowView.findViewById(R.id.cancleButton);
            cancleButton.setOnClickListener(new ButtonOnClickListener());
            leaveword = (EditText) popupWindowView.findViewById(R.id.leaveword);
            popupWindow.showAtLocation(btnsure, Gravity.CENTER, 0, 0);
        }

        private class ButtonOnClickListener implements OnClickListener {
            @Override
            public void onClick(View vid) {

                switch (vid.getId()) {

                    case R.id.btnOpen:
                        OpenView();
                        break;
                    case R.id.confirmButton:

                        Toast.makeText(MainActivity.this, leaveword.getText().toString(), Toast.LENGTH_SHORT)
                                .show();

                        break;
                    case R.id.cancleButton:
                        if (popupWindow!= null && popupWindow.isShowing()) {
                            popupWindow.dismiss();
                        }
                        break;

                    default:
                        break;
                }
            }
        }
    }

解析:

 window.setBackgroundDrawable(new ColorDrawable()); 
 window.setOutsideTouchable(true);

只有同时设置PopupWindow的背景和可以响应外部点击事件,它才能“真正”响应外部点击事件。也就是说,当你点击PopupWindow的外部或者按下“Back”键时,PopupWindow才会消失。

showAtLocation(相对于组件parent屏幕)

 public void showAtLocation(View parent, int gravity, int x, int y)

● parent可以为Activity中的任意一个View(最终的效果一样),会通过这个View找到其父Window,也就是Activity的Window。
● gravity,默认为Gravity.NO_GRAVITY,等效于Gravity.LEFT | Gravity.TOP
● x, y,边距。这里的x,y表示距离Window边缘的距离,方向由Gravity决定。例如:设置了Gravity.TOP,则y表示与Window上边缘的距离;而如果设置了Gravity.BOTTOM,则y表示与下边缘的距离。
● 如果弹窗位置超出了Window的范围,会自动处理使其处于Window中
● 相对于屏幕(左上角0,0),窗位置超出了Window的范围,会自动处理使其处于Window中,显示范围是顶部和底部

注意:使用的时候,如果设置Gravity.TOP,则要计算状态栏的高度

备注:

android:fromYDelta — 表示Y的起始值

android:toYDelta — 表示Y的结束值

在这些属性里面还可以加上%和p,例如:

android:toXDelta=”100%”,表示自身的100%,也就是从View自己的位置开始。

android:toXDelta=”80%p”,表示父层View的80%,是以它父层View为参照的。

另外,如下:

android:fromXDelta=”0” android:toXDelta=”-100%p”
往左邊消失

android:fromXDelta=”-100%p” android:toXDelta=”0”
從左邊進

android:fromXDelta=”0” android:toXDelta=”100%p”
往右邊消失

android:fromXDelta=”100%p” android:toXDelta=”0”
從右邊進

经查阅资料才发现动画的启始位置虽然是在控件的左下角,但是相对位置却不是我们平时想的那样.

在实现左右动画的时候,其相对位置应该为(位置2为起始位置):

这里写图片描述

这里写图片描述

showAsDropDown(相对于组件)

public void showAsDropDown(View anchor, int xoff, int yoff)

第一个参数是PopupWindow的锚点,第二和第三个参数分别强调内容是PopupWindow相对锚点的x、y偏移

使用showAsDropDown方法显示PopupWindow

通常情况下,调用showAsDropDown方法后PopupWindow将会在锚点的左下方显示(drop down)。但是,有时想让PopupWindow在锚点的上方显示,或者在锚点的中间位置显示,此时就需要用到showAsDropDown方法的xoff和yoff参数了。

这里我们的目的不仅包括上面提到的两种情况(锚点上方或锚点中部),而是囊括了水平和垂直方向各5种显示方式:
● 水平方向:

○ ALIGN_LEFT:在锚点内部的左边;
○ ALIGN_RIGHT:在锚点内部的右边;
○ CENTER_HORI:在锚点水平中部;
○ TO_RIGHT:在锚点外部的右边;
○ TO_LEFT:在锚点外部的左边。

● 垂直方向:

○ ALIGN_ABOVE:在锚点内部的上方;
○ ALIGN_BOTTOM:在锚点内部的下方;
○ CENTER_VERT:在锚点垂直中部;
○ TO_BOTTOM:在锚点外部的下方;
○ TO_ABOVE:在锚点外部的上方。

下面来看张图:

这里写图片描述

这里写图片描述

注意参数Gravity.NO_GRAVITY:用来标明没有设定对齐方向

(1)在控件的上方:

 1 private void showPopUp(View v) {  
 2         LinearLayout layout = new LinearLayout(this);  
 3         layout.setBackgroundColor(Color.GRAY);  
 4         
 5         TextView tv = new TextView(this);          
 6         tv.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));  
 7         tv.setText("I'm a pop !");  
 8         tv.setTextColor(Color.WHITE); 
 9         
10         layout.addView(tv);  
11   
12         popupWindow = new PopupWindow(layout,120,120);       
13         popupWindow.setFocusable(true);  
14         popupWindow.setOutsideTouchable(true);  
15         popupWindow.setBackgroundDrawable(new BitmapDrawable());  
16           
17         int[] location = new int[2];  
18         v.getLocationOnScreen(location);  
19           
20         popupWindow.showAtLocation(v, Gravity.NO_GRAVITY, location[0], location[1]-popupWindow.getHeight());  
21     }  

(2)在控件的下方:

在控件的其他方向上显示只需修改最后一行代码即可,如:

1. popupWindow.showAsDropDown(v);

(3)在控件的左边:

1. popupWindow.showAtLocation(v, Gravity.NO_GRAVITY, location[0]-popupWindow.getWidth(), location[1]);  

(4)在控件的右边:

1.popupWindow.showAtLocation(v, Gravity.NO_GRAVITY, location[0]+v.getWidth(), location[1]); 

总结:
showAtLocation 和 showAsDropDown 主要区别于显示位置相对于屏幕还是组件

转自 https://www.jianshu.com/p/6a6a05e498d7

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值