popup view android,android的PopupWindow简解

本文出自 “阿敏其人” 简书博客,转载或引用请注明出处。

前言

注:为书写方便,本文的popup代表PopupWindow。

概述

PopupWindow在android.widget包下,弹出窗口的形式展示。官方文档对该控件的描述

“一个弹出窗口控件,可以用来显示任意视图(View),而且会浮动在当前 活动(activity)的顶部”。

PopupWindow可以让我们实现多种自定义控件,例如:menu、alertdialog等弹窗似的View。

与Dialog的对比

AlertDialog 和PopupWindow的不同点:

AlertDialog 的位置固定,PopupWindow 的位置是自定义的

AlertDialog 是非阻塞线程的,而PopupWindow 是阻塞线程的。

Popup的样子

3925fbd50027

Paste_Image.png

再来一个例子

3925fbd50027

Paste_Image.png

二、简单使用——展示

我们先把一个popup,给展示出来。

二、1 展示popup的三步曲

简单来说,我们的popup长什么样子,我们就需要使用一个写一个xml布局文件指明清楚。

最简单的三步曲

1、写一个item布局文件

2、利用popup的构造函数把item作为参数传进去。

3、调用popup的showAsDropDown或者showAtLocation方法将popup显示出来。

上面这三部是最基本最简单,但是这样是不够的,通过上面这和三步我们只是让popup显示出来,但是怎么消失,点击子项怎么产生效果我们还有指明,这个慢慢来。

先按照上面的三步曲附上简单示例代码:

三步曲第一:

写一个布局文件

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="#ff0000"

android:orientation="vertical">

android:id="@+id/btn_xixi"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:padding="5dp"

android:text="第一项"

android:textSize="18sp" />

android:id="@+id/btn_hehe"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:padding="5dp"

android:text="第二项"

android:textSize="18sp" />

.

.

3925fbd50027

Paste_Image.png

.

.

三步曲 第二:

利用构造函数关联

popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT,true);

.

.

三步曲 第三:

调用方法展示popup

popupWindow.showAsDropDown(view);

.

.

public class MainActivity extends Activity {

private TextView mTv;

private Context mContext;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mContext= this;

mTv = (TextView) findViewById(R.id.mTv);

mTv.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

initPopupWindow(v);

}

});

}

PopupWindow popupWindow;

private void initPopupWindow(View view) {

if(popupWindow == null){

View popupView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_popip,null);

// 三部曲第二 构造函数关联

popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT,true);

}

// 三部曲第三 展示popup

popupWindow.showAsDropDown(view);

}

}

.

.

通过上面的三部曲,我们就可以通过点击对应的View展示popup了

3925fbd50027

Paste_Image.png

.

.

三步曲走完了,先不着急往下看,我们先看看三步曲中涉及到

1、构造函数

2、展示popup的方法

开说。

.

.

二、2 PopupWindow的构造函数

PopupWindow的构造函数,5个。

3925fbd50027

Paste_Image.png

参数最长的 public PopupWindow(View contentView, int width, int height, boolean focusable) 才是日常使用的重点,其他的不怎么重要。

第一种,一个空的,没有焦点的Popup

第二种,没有焦点不能指定位置的popup

第三种,空的popup

第四种,没有焦点的popup

其实前4种都不常见,常见的是最后一种,第五种

第五种:可以指定父亲,位置,是否具备焦点。

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

这个构造方法才重点!!

附上google的源码

/**

*

Create a new empty, non focusable popup window of dimension (0,0).

*

*

The popup does not provide any background. This should be handled

* by the content view.

*/

public PopupWindow() {

this(null, 0, 0);

}

/**

*

Create a new non focusable popup window which can display the

* contentView. The dimension of the window are (0,0).

*

*

The popup does not provide any background. This should be handled

* by the content view.

*

* @param contentView the popup's content

*/

public PopupWindow(View contentView) {

this(contentView, 0, 0);

}

/**

*

Create a new empty, non focusable popup window. The dimension of the

* window must be passed to this constructor.

*

*

The popup does not provide any background. This should be handled

* by the content view.

*

* @param width the popup's width

* @param height the popup's height

*/

public PopupWindow(int width, int height) {

this(null, width, height);

}

/**

*

Create a new non focusable popup window which can display the

* contentView. The dimension of the window must be passed to

* this constructor.

*

*

The popup does not provide any background. This should be handled

* by the content view.

*

* @param contentView the popup's content

* @param width the popup's width

* @param height the popup's height

*/

public PopupWindow(View contentView, int width, int height) {

this(contentView, width, height, false);

}

/**

*

Create a new popup window which can display the contentView.

* The dimension of the window must be passed to this constructor.

*

*

The popup does not provide any background. This should be handled

* by the content view.

*

* @param contentView the popup's content

* @param width the popup's width

* @param height the popup's height

* @param focusable true if the popup can be focused, false otherwise

*/

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

if (contentView != null) {

mContext = contentView.getContext();

mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);

}

setContentView(contentView);

setWidth(width);

setHeight(height);

setFocusable(focusable);

}

.

.

二、2 展示方法:showAsDropDown和showAtLocation

3925fbd50027

Paste_Image.png

anchored是锚的意思

方法一:

showAsDropDown(View anchor)

出现的指定的锚View的左下角位置,也就是以锚View的左下角作为popup关联的布局文件自身的左上角的起始点

* Display the content view in a popup window anchored to the bottom-left

* corner of the anchor view. If there is not enough room on screen to show

* the popup in its entirety, this method tries to find a parent scroll

* view to scroll. If no parent scroll view can be scrolled, the

* bottom-left corner of the popup is pinned at the top left corner of the

* anchor view.

还是看图吧,直接。

3925fbd50027

Paste_Image.png

方法二:

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

出现在锚View的左下角,根据指定的x和y产生偏移

一切照旧,只改一行代码

popupWindow.showAsDropDown(view,30,150);

查看效果

3925fbd50027

Paste_Image.png

方法三:

public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) (基本忽略)

指定锚View,可以设定x和y的偏移量,而且,可以指定相对父控件的位置,(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移

注意:这个方法是API 19以后才提供的,谨慎采用,如果我们想指定偏移量和相对父控件的位置,那么可以用另外一个方法。也就是接下来要介绍的这个方法。

方法四:

重点方法

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

指定锚View,可以设定x和y的偏移量,而且,可以指定相对父控件的位置,(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移。这段描述和前面的方法三一样,他们可以做的事情一样,但是showAtLocation是API 1就已经提供的了。

一定注意gravity是相对锚View父控件。

popupWindow.showAtLocation(view, Gravity.CENTER,0, 0);

3925fbd50027

Paste_Image.png

再来一个,利用|指定popup出现在锚View的父控件的右下角

popupWindow.showAtLocation(view, Gravity.BOTTOM|Gravity.RIGHT,0, 0);

3925fbd50027

Paste_Image.png

.

.

三、关于Popup的各种设置

1、关于点击popup之外的地方让popup消失

需要两个方法一起使用才能产生效果

// ======= 两者结合才能让popup点击外部消失

popupWindow.setOutsideTouchable(true);

popupWindow.setBackgroundDrawable(new BitmapDrawable());

// ======= 两者结合才能让popup点击外部消失

2、关于焦点问题 .setFocusable(true);

我们看到,不管是微信右上角的点击弹出popup还是其他的什么软件,当我们的popup已经弹出来了,这是我们按下back(返回键),会发现是popup消失,而是不是退出当前的activity,这说明,当前程序(比如微信)在popup出现的时候,PopupWindow弹出后,所有的触屏和物理按键都有PopupWindows处理。所以第一次back键是先退出popup,第二次按下back键才是退出当前activity。

但是popup这个具有处理触屏和物理按键的能力不是与生俱来的,需要设置 popupWindow.setFocusable(true); ,这里不单单应该理解为具备焦点,而且让popup具备优先的交互响应等级。

如果 .setFocusable(false); 那么如果当前popup已经展示着了,这是按下back键,结果是 popup和activity一起退出。

3、关于popup的和软键盘的关系

利用 setSoftInputMode 这个方法可以指定,一共有9中模式。

4、关于popup的动画

利用下面这个方法就可以指定

public void setAnimationStyle(int animationStyle)

可以选用系统提供的

popWindow.setAnimationStyle(android.R.style.Animation_InputMethod);

可以使用自定义的进出动画:

android:windowEnterAnimation表示进入窗口动画

android:windowExitAnimation表示窗口退出动画

在res/values/style.xml代码:

@anim/popup_enter

@anim/popup_exit

.

.

在res/anim/popup_enter.xml声明所需进入动画

android:fromYScale="0.6"android:toYScale="1.0"android:pivotX="50%"

android:pivotY="50%"android:duration="1000"/>

android:fromAlpha="0.0"android:toAlpha="1.0"android:duration="1000"/>

在res/anim/popup_exit.xml声明所需退出动画

android:fromXScale="1.0"

android:toXScale="0.5"

android:fromYScale="1.0"

android:toYScale="0.5"

android:pivotX="50%"

android:pivotY="50%"

android:duration="500"/>

android:interpolator="@android:anim/accelerate_interpolator"

android:fromAlpha="1.0"

android:toAlpha="0.0"

android:duration="500"/>

设置popwindow的位置及动画

popupWindow.setAnimationStyle(R.style.PopupAnimation);

6. popup的消失

popupWindow.dismiss();

这个没什么好讲的

7、popup子项的点击相应,这个么没什么好说的

.

.

基本上popup开发中所常用的涉及到的上看都提及了,现在附上完整demo代码

public class MainActivity extends Activity {

private TextView mTv;

private Context mContext;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mContext= this;

mTv = (TextView) findViewById(R.id.mTv);

mTv.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

initPopupWindow(v);

}

});

}

PopupWindow popupWindow;

private void initPopupWindow(View view) {

if(popupWindow == null){

View popupView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_popip,null);

// 三部曲第二 构造函数关联

popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT,true);

initClick(popupView);

}

// ======= 两者结合才能让popup点击外部消失

popupWindow.setOutsideTouchable(true);

popupWindow.setBackgroundDrawable(new BitmapDrawable());

// ======= 两者结合才能让popup点击外部消失

// 让popup占有优先于activity的交互响应能力,不单单是焦点问题。

popupWindow.setFocusable(true);

// 设置动画 这里选用系统提供的

popupWindow.setAnimationStyle(android.R.style.Animation_InputMethod);

// popup和软键盘的关系

// 三部曲第三 展示popup

popupWindow.showAsDropDown(view);

}

private void initClick(View popupView) {

Button btn1 = (Button) popupView.findViewById(R.id.btn1);

Button btn2 = (Button) popupView.findViewById(R.id.btn2);

btn1.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Toast.makeText(MainActivity.this,"点击第一项",Toast.LENGTH_SHORT).show();

}

});

btn2.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Toast.makeText(MainActivity.this,"点击第二项",Toast.LENGTH_SHORT).show();

}

});

}

}

3925fbd50027

GIF.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值