PopupWindow在android中的使用分析

PopupWindow在android中的使用分析

PopupWindow是应用开发中经常用到的组建,使用它可以在当前屏幕的上层显示一个弹窗,同时也可以指定弹窗的位置以及背景色等特性,大大提高用户体验,那么这里我就以下几点介绍它的使用:

1
从指定的位置弹出这个窗口(淡入淡出动画)

2
从屏幕底部弹出这个窗口(带有透明度背景,自定义触摸其他位置自动关闭弹窗)

我的效果图如下:

下面直接上代码,具体如下所示(按开发顺序排列)

1
自定义一个继承自PopupWindow的类

publicclassPopupDialog
extendsPopupWindow {

publicPopupDialog(View
view,intwidth,intheight)
{

super(view,width,height);

}

}

2自定义一个负责设定PopupWindow特性的属性类

publicclassPopup
{

privateintxPos;
//弹出窗口的x方向位置

privateintyPos;
//弹出窗口的y方向位置

privateintvWidth;
//窗口显示内容的视图宽度

privateintvHeight;
//窗口显示内容的视图高度

privateintanimFadeInOut;
//窗口显示动画

privateintcontentView;
//潜入在窗口的视图

privateView
customView;
//潜入的窗口视图view

privatebooleanisClickable;
//视图外部是否可以点击

privateOnDismissListener
listener;
//监听弹窗是否dismiss

privateOnTouchListener
touchListener;
//监听触摸位置

privatefloatbgAlpha;
//背景遮罩的透明度

publicintgetxPos()
{

returnxPos;

}

publicvoidsetxPos(intxPos)
{

this.xPos=
xPos;

}

publicintgetyPos()
{

returnyPos;

}

publicvoidsetyPos(intypos)
{

this.yPos=
ypos;

}

publicintgetvWidth()
{

returnvWidth;

}

publicvoidsetvWidth(intvWidth)
{

this.vWidth=
vWidth;

}

publicintgetvHeight()
{

returnvHeight;

}

publicvoidsetvHeight(intvHeight)
{

this.vHeight=
vHeight;

}

publicintgetAnimFadeInOut()
{

returnanimFadeInOut;

}

publicvoidsetAnimFadeInOut(intanimFadeInOut){

this.animFadeInOut=
animFadeInOut;

}

publicintgetContentView()
{

returncontentView;

}

publicvoidsetContentView(intcontentView){

this.contentView=
contentView;

}

publicbooleanisClickable()
{

returnisClickable;

}

publicvoidsetClickable(booleanisClickable){

this.isClickable=
isClickable;

}

publicView getCustomView() {

returncustomView;

}

publicvoidsetCustomView(View
customView){

this.customView=
customView;

}

publicOnDismissListener getListener()
{

returnlistener;

}

publicvoidsetListener(OnDismissListener
listener){

this.listener=
listener;

}

publicfloatgetBgAlpha()
{

returnbgAlpha;

}

publicvoidsetBgAlpha(floatbgAlpha)
{

this.bgAlpha=
bgAlpha;

}

publicOnTouchListener getTouchListener()
{

returntouchListener;

}

publicvoidsetTouchListener(OnTouchListener
touchListener){

this.touchListener=
touchListener;

}

3
自定义一个用来管理PopupWindow的工具类

publicclassPopupUtils
{

privatestaticPopupDialog
popupDialog=
null;

@SuppressLint("NewApi")

publicstaticPopupDialog
createPopupDialog(Context context,Popupdialog) {

dismissPopupDialog();

Viewview =null;

if(ValueUtils.isEmpty(dialog.getCustomView())){

LayoutInflaterinflater =LayoutInflater.from(context);

view=
inflater.inflate(dialog.getContentView(),null);

}else{

view=
dialog.getCustomView();

}

view.setOnTouchListener(dialog.getTouchListener());

if(0!=
dialog.getBgAlpha()){

view.setAlpha(dialog.getBgAlpha());

}

popupDialog=
newPopupDialog(view,dialog.getvWidth(),dialog.getvHeight());

ColorDrawabledw =
newColorDrawable(Color.TRANSPARENT);
//follow two lines is used for back key -00000

popupDialog.setBackgroundDrawable(dw);

popupDialog.setAnimationStyle(dialog.getAnimFadeInOut());

popupDialog.setOutsideTouchable(dialog.isClickable());

popupDialog.setFocusable(true);
//not allow user click popupwindowbackground event or not permit

popupDialog.setOnDismissListener(dialog.getListener());

popupDialog.update();

returnpopupDialog;

}

publicstaticvoiddismissPopupDialog()
{

if(ValueUtils.isNotEmpty(popupDialog)&&

popupDialog.isShowing()){

popupDialog.dismiss();

popupDialog=
null;

}

}

publicstaticbooleanisPopupShowing()
{

if(ValueUtils.isNotEmpty(popupDialog)&&

popupDialog.isShowing()){

returntrue;

}else{

returnfalse;

}

}

}

接下来,我们需要准备相关的资源文件了,比如:导航按钮页面,采购清单弹窗页面以,选择美图窗口页面以及需要用到的动画文件和圆角背景文件,具体如下:

导航按钮页面xml:

<ScrollViewxmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:id="@+id/main"

android:background="#f2f3f4">

<LinearLayout

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical">

<Button

android:id="@+id/btnDropDownPopupDialog"

android:layout_width="match_parent"

android:layout_height="40dp"

android:layout_gravity="center_horizontal"

android:layout_marginLeft="10dp"

android:layout_marginRight="10dp"

android:layout_marginTop="10dp"

android:background="#FFFFFF"

android:textColor="#5084FE"

android:text="采购清单"

/>

<Button

android:id="@+id/btnDownUpPopupDialog"

android:layout_width="match_parent"

android:layout_height="40dp"

android:layout_gravity="center_horizontal"

android:layout_marginLeft="10dp"

android:layout_marginRight="10dp"

android:layout_marginTop="10dp"

android:background="#FFFFFF"

android:textColor="#5084FE"

android:text="选择美图"

/>

</LinearLayout>

</ScrollView>

采购清单弹窗页面xml:

<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="#c9cbce"

android:gravity="center"

>

<TextView

android:id="@+id/tvbillTypeYc"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="粤菜"

android:textColor="#5084FE"

android:padding="10dp"

android:layout_margin="10dp"

android:gravity="center"

android:background="@drawable/corners_bk_gray2"

/>

<TextView

android:id="@+id/tvbillTypeCc"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="川菜"

android:textColor="#5084FE"

android:padding="10dp"

android:layout_margin="10dp"

android:gravity="center"

android:layout_below="@id/tvbillTypeYc"

android:background="@drawable/corners_bk_gray2"

/>

<TextView

android:id="@+id/tvbillTypeXc"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="湘菜"

android:textColor="#5084FE"

android:padding="10dp"

android:layout_margin="10dp"

android:gravity="center"

android:layout_below="@id/tvbillTypeCc"

android:background="@drawable/corners_bk_gray2"

/>

<TextView

android:id="@+id/tvbillTypeMore"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="..."

android:textColor="#5084FE"

android:padding="10dp"

android:layout_margin="10dp"

android:gravity="center"

android:layout_below="@id/tvbillTypeXc"

android:background="@drawable/corners_bk_gray2"

/>

</RelativeLayout>

选择美图弹窗页面xml:

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#00000000"

>

<FrameLayout

android:id="@+id/flMaskLayer"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#000000"

/>

<LinearLayout

android:id="@+id/llHeader"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginLeft="10dp"

android:layout_marginRight="10dp"

android:orientation="vertical"

android:layout_alignParentBottom="true"

>

<RelativeLayout

android:layout_width="match_parent"

android:layout_height="81.0dp"

android:background="@drawable/corners_bk_white"

>

<TextView

android:id="@+id/tvTakeHeader"

android:layout_width="match_parent"

android:layout_height="40dp"

android:text="拍照"

android:textColor="#5084FE"

android:gravity="center"

/>

<View

android:layout_width="match_parent"

android:layout_height="1dp"

android:background="@color/gray"

android:layout_centerVertical="true"

/>

<TextView

android:id="@+id/tvHeaderFromSD"

android:layout_width="match_parent"

android:layout_height="40dp"

android:text="从相册中选"

android:textColor="#5084FE"

android:gravity="center"

android:layout_below="@id/tvTakeHeader"

/>

</RelativeLayout>

<TextView

android:id="@+id/tvCancel"

android:layout_width="match_parent"

android:layout_height="40dp"

android:text="取消"

android:textColor="#5084FE"

android:background="@drawable/corners_bk_white"

android:gravity="center"

android:layout_marginTop="18dp"

/>

</LinearLayout>

</RelativeLayout>

淡入淡出动画文件xml:

淡入动画:

<?xmlversion="1.0"encoding="utf-8"standalone="no"?>

<setxmlns:android="http://schemas.android.com/apk/res/android"

android:interpolator="@android:anim/decelerate_interpolator">

<alpha

android:duration="500"

android:fromAlpha="0.0"

android:toAlpha="1.0"/>

</set>

淡出动画:

<?xmlversion="1.0"encoding="utf-8"standalone="no"?>

<setxmlns:android="http://schemas.android.com/apk/res/android"

android:interpolator="@android:anim/decelerate_interpolator">

<alpha

android:duration="300"

android:fromAlpha="1.0"

android:toAlpha="0.0"/>

</set>

圆角背景文件xml:

采购清单背景:

<?xmlversion="1.0"encoding="utf-8"?>

<shapexmlns:android="http://schemas.android.com/apk/res/android">

<solidandroid:color="#efece0"/>

<corners

android:radius="4dp"/>

<padding

android:bottom="5dp"

android:left="10dp"

android:right="10dp"

android:top="5dp"/>

<stroke

android:width="1dp"

android:color="#efece0"/>

</shape>

底部弹窗:

<?xmlversion="1.0"encoding="utf-8"?>

<shapexmlns:android="http://schemas.android.com/apk/res/android">

<solidandroid:color="#FFFFFF"/>

<corners

android:bottomLeftRadius="6dp"

android:bottomRightRadius="6dp"

android:topLeftRadius="6dp"

android:topRightRadius="6dp"/>

</shape>

到这里,我们已经准备了所有需要的工作,接下来就是在我们的前段页面中调用即可。主要是通过参数对象包装参数,并调用上面的工具类进行展示和隐藏我们需要的PopupWindow即可,具体如下:

publicclassViewUtilsActivity
extendsFragmentActivity {

privatestaticViewUtilsFragment
fragment=
null;

@Override

protectedvoidonCreate(Bundle
bundle){

super.onCreate(bundle);

requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.activity_base_main);

if(null==
bundle){

FragmentTransactionft =getSupportFragmentManager().beginTransaction();

fragment=
newViewUtilsFragment();

ft.add(R.id.container,fragment);

ft.commit();

}

}

publicclassViewUtilsFragment
extendsFragment
implementsView.OnClickListener {

privatePopupDialog
popupDialog=
null;

privateButton
btnDropDownPopupDialog=
null;

privateButton
btnDownUpPopupDialog=
null;

@Override

publicView onCreateView(LayoutInflater
inflater,ViewGroup
container,

BundlesavedInstanceState){

ViewrootView =(View)
inflater.inflate(R.layout.fragment_viewutils,container,false);

btnDropDownPopupDialog= (Button)rootView.findViewById(R.id.btnDropDownPopupDialog);

btnDropDownPopupDialog.setOnClickListener(this);

btnDownUpPopupDialog= (Button)
rootView.findViewById(R.id.btnDownUpPopupDialog);

btnDownUpPopupDialog.setOnClickListener(this);

returnrootView;

}

@Override

publicvoidonClick(View
v){

switch(v.getId()){

caseR.id.btnDropDownPopupDialog:

showDropDownPopupDialog();

break;

caseR.id.btnDownUpPopupDialog:

showDownUpPopupDialog();

break;

default:

break;

}

}

privatevoidshowDropDownPopupDialog()
{

Popuppopup =
newPopup();

//这里是获得屏幕宽度使弹窗水平居中

intxPos
=(AppUtils.getScreenWidth(getActivity())-
btnDropDownPopupDialog.getWidth())/ 2;

popup.setxPos(xPos);

popup.setyPos(0);

popup.setvWidth(LayoutParams.WRAP_CONTENT);

popup.setvHeight(LayoutParams.WRAP_CONTENT);

popup.setClickable(true);

popup.setAnimFadeInOut(R.style.AnimationFade);

popup.setContentView(R.layout.view_popup_dialog);

popupDialog= ViewUtils.createPopupDialog(getActivity(),popup);

popupDialog.showAsDropDown(btnDropDownPopupDialog,popup.getxPos(),popup.getyPos());

}

@SuppressLint({"NewApi","ClickableViewAccessibility"})

privatevoidshowDownUpPopupDialog()
{

Popuppopup =
newPopup();

popup.setvWidth(LayoutParams.MATCH_PARENT);

popup.setvHeight(LayoutParams.MATCH_PARENT);

popup.setClickable(true);

popup.setContentView(R.layout.view_userheader_modifydetail);

//设置触摸其他位置时关闭窗口

OnTouchListenerlistener =newOnTouchListener()
{

@Override

publicbooleanonTouch(View
view,MotionEvent
event){

intheight
=view.findViewById(R.id.llHeader).getTop();

inty
= (int)event.getY();

if(event.getAction()==MotionEvent.ACTION_UP){

if(y<height){

ViewUtils.dismissPopupDialog();

}

}

returntrue;

}

};

popup.setTouchListener(listener);

popupDialog= ViewUtils.createPopupDialog(getActivity(),popup);

popupDialog.showAtLocation(getActivity().findViewById(R.id.main),

Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL,popup.getxPos(),popup.getyPos());

Viewview =popupDialog.getContentView();

//背景透明度设置

view.findViewById(R.id.flMaskLayer).setAlpha(0.75f);

View.OnClickListenerl =
newView.OnClickListener() {

@Override

publicvoidonClick(View
v){

if(v.getId()==
R.id.tvCancel){

ViewUtils.dismissPopupDialog();

}

elseif(v.getId()==
R.id.tvTakeHeader){

//take phone

Toast.makeText(getActivity(),"拍照",Toast.LENGTH_SHORT).show();

ViewUtils.dismissPopupDialog();

}

elseif(v.getId()==
R.id.tvHeaderFromSD){

//pick picture from
sd

Toast.makeText(getActivity(),"从相册中选",Toast.LENGTH_SHORT).show();

ViewUtils.dismissPopupDialog();

}

}

};

view.findViewById(R.id.tvCancel).setOnClickListener(l);

view.findViewById(R.id.tvTakeHeader).setOnClickListener(l);

view.findViewById(R.id.tvHeaderFromSD).setOnClickListener(l);

}

publicPopupDialog getPopupDialog()
{

returnpopupDialog;

}

}

//监听返回按钮

@Override

publicbooleanonKeyDown(intkeyCode,KeyEvent
event){

switch(keyCode){

caseKeyEvent.KEYCODE_BACK:
{

booleanflag
=ViewUtils.isPopupShowing();

if(flag){

ViewUtils.dismissPopupDialog();

returnfalse;

}

}

break;

default:

break;

}

returnsuper.onKeyDown(keyCode,event);

}

好了,到这里我们的工作就完成啦,可以欣赏自己的作品了。

如果有问题,可以在评论中或群(179914858)进行讨论,谢谢。

时间: 2024-11-03 01:16:27

PopupWindow在android中的使用分析的相关文章

【转载+整理】Android中TouchEvent事件分析

原文地址:http://mobile.51cto.com/abased-374715.htm 一.知识回顾 一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE...->ACTION_MOVE->ACTION_UP 二.问题提出 当屏幕中包含一个ViewGroup,而这个ViewGroup又包含一个子view,这个时候android系统如何处理Touch事件呢?到底是 View

Android 中图片压缩分析(上)

作者: shawnzhao,QQ音乐技术团队一员 一.前言 在 Android 中进行图片压缩是非常常见的开发场景,主要的压缩方法有两种:其一是质量压缩,其二是下采样压缩. 前者是在不改变图片尺寸的情况下,改变图片的存储体积,而后者则是降低图像尺寸,达到相同目的. 由于本文的篇幅问题,分为上下两篇发布. 二.Android 质量压缩逻辑 在Android中,对图片进行质量压缩,通常我们的实现方式如下所示: ByteArrayOutputStream outputStream = new Byte

android中SELINUX规则分析和语法简介

############################################# 本文为极度寒冰原创,转载请注明出处 ############################################# 1. SELINUX是可以理解为一种android上面的安全机制,是有美国国家安全局和一些公司设计的一个针对linux的安全加强系统 我们可以通过配置SELINUX的相关policy,来定制自己的手机的一些权限,比如,我们可以完全让root用户没有任何的权限和user一样 2.

Android 中LayoutInflater原理分析

概述 在Android开发中LayoutInflater的应用非常普遍,可以将res/layout/下的xml布局文件,实例化为一个View或者ViewGroup的控件.与findViewById的作用类似,但是findViewById在xml布局文件中查找具体的控件,两者并不完全相同. 应用场景: 1.在一个没有载入或者想要动态载入的界面中,需要使用layoutInflater.inflate()来载入布局文件: 2.对于一个已经载入的界面,就可以使用findViewById方法来获得其中的界

如何使用Android中TraceView性能分析工具

现来看一下整个界面的图,整个界面包括上下两部分,上面是你测试的进程中每个线程的执行情况,每个线程占一行:下面是每个方法执行的各个指标的值 上面一部分是你测试进程的中每个线程运行的时间线,下图中可以可以看到,主要只有一个main线程在执行,因为我滑动了一下列表,main线程(UI线程)正在进行绘制View呢~ 附相关视频教程Android应用开发视频教程 然后我点击了序号为133的一个方法io.bxbxbai.android.examples.activity.ExpandableLayoutMa

Android中Parcel的分析以及使用

简单点来说:Parcel就是一个存放读取数据的容器, Android系统中的binder进程间通信(IPC)就使用了Parcel类来进行客户端与服务端数据的交互,而且AIDL的数据也是通过Parcel来交互的.在Java空间和C++都实现了Parcel,由于它在C/C++中,直接使用了内存来读取数据,因此,它更有效率. 分析Binder机制中的客户端与服务器端进行实际操作ontransact()函数 : [java] //参数说明: // code :是请求的ID号 // data :客户端请求

Android中应用安装分析

#1 安装方式 1 安装系统APK和预制APK时,通过PMS的构造函数中安装,即第一次开机时安装应用,没有安装界面. 2 网络下载安装,通过应用商店等,即调用PackageManager.installPackages(),有安装界面. 3 通过adb工具安装,没有安装界面,它通过启动pm脚本的形式,然后调用com.android.commands.pm.Pm类,之后调用到PMS.installStage()完成安装. 4 安装本地apk,有安装界面,由PackageInstaller系统应用安

Android中相机和相册使用分析

Android中相机和相册使用分析 欢迎转载,但请尊重原创(文章来自不易,转载请标明转载出处,谢谢) 在手机应用程序中,使用自带的相机拍照以及相册选择喜欢的图片是最常见不过的用户需求,那么怎么合理使用相机和相册来选择照片是重要的,下面就以项目中实际需求为例进行说明,这里实现的功能如下: 1 使用相机和相册选择图片,并裁剪较小图片(常用于剪裁小图) 2 使用相机和相册选择图片,并裁剪较大图片(常用于裁剪大图) 具体的实现功能清楚了,那么就一一进行说明,具体如下(这里不会罗列怎么上传图片到服务端,只

Android中View绘制流程以及invalidate()等相关方法分析

前言: 本文是我读<Android内核剖析>第13章----View工作原理总结而成的,在此膜拜下作者 .同时真挚地向渴望了解 Android 框架层的网友,推荐这本书,希望你们能够在Android开发里学到更多的知识 . 整个View树的绘图流程是在ViewRoot.java类的performTraversals()函数展开的,该函数做的执行过程可简单概况为 根据之前设置的状态,判断是否需要重新计算视图大小(measure).是否重新需要安置视图的位置(layout).以及是否需要重绘 (d