2023年7月15日发(作者:)
PopUpWindow使⽤详解(⼀)——基本使⽤本来想写⼀篇关于PopUpWindow的⽂章,但在学习过程中发现启舰⼤佬写的特别好。⾃认写不出这么通俗易懂的⽂章,看来⾃⼰和真正的⼤神还是有很⼤差距的。特意转载到此,以激励⾃⼰奋⼒前⾏,不忘初⼼。
相关⽂章:1、《PopUpWindow使⽤详解(⼀)——基本使⽤》2、先看⼀下我们要做的效果:
这个效果很容易理解:当点击btn时,在底部弹出PopupWindow,然后点击各个item弹出对应toast。⼀、概述1、PopupWindow与AlertDialog的区别最关键的区别是AlertDialog不能指定显⽰位置,只能默认显⽰在屏幕最中间(当然也可以通过设置WindowManager参数来改变位置)。⽽PopupWindow是可以指定显⽰位置的,随便哪个位置都可以,更加灵活。
有关Dialog的相关知识,⼤家可以参考⼤佬的系列博客:2、PopupWindow的相关函数(1)、构造函数: //⽅法⼀:
public PopupWindow (Context context)
//⽅法⼆:
public PopupWindow(View contentView)
//⽅法三:
public PopupWindow(View contentView, int width, int height)
//⽅法四:
public PopupWindow(View contentView, int width, int height, boolean focusable)
⾸要注意:看这⾥有四个构造函数,但要⽣成⼀个PopupWindow最基本的三个条件是⼀定要设置的:View contentView,int width, intheight ;少任意⼀个就不可能弹出来PopupWindow
所以,如果使⽤⽅法⼀来构造PopupWindow,那完整的构造代码应该是这样的: View contentView = ().inflate(ayout, null);
PopupWindwo popWnd = PopupWindow (context);
tentView(contentView);
th(_CONTENT);
ght(_CONTENT);
有关为什么⼀定要设置width和height的原因,我们后⾯会讲,这⾥说⼀下为什么样强制设置contentView;很简单的原因是因为PopupWindow没有默认布局,它不会像AlertDialog那样只setTitle,就能弹出来⼀个框。PopupWindow是没有默认布局的,它的布局只有通过我们⾃⼰设置才⾏。由于⽅法三中,含有了这三个必备条件,不⽤单独设置contentview或者width、height,所以构造⽅法三是⽤的最多的⼀个构造⽅法。
最后,⽅法四中的focusable变量不是必须的,有关它的⽅法和意义,我们会在下⼀篇中细讲。(2)显⽰函数显⽰函数主要使⽤下⾯三个: //相对某个控件的位置(正左下⽅),⽆偏移
showAsDropDown(View anchor):
//相对某个控件的位置,有偏移;xoff表⽰x轴的偏移,正值表⽰向右,负值表⽰向左;yoff表⽰相对y轴的偏移,正值是向下,负值是向上;
showAsDropDown(View anchor, int xoff, int yoff):
//相对于⽗控件的位置(例如正中央,下⽅等),可以设置偏移或⽆偏移
showAtLocation(View parent, int gravity, int x, int y):
这⾥有两种显⽰⽅式:
1、显⽰在某个指定控件的下⽅showAsDropDown(View anchor):showAsDropDown(View anchor, int xoff, int yoff);2、指定⽗视图,显⽰在⽗控件的某个位置(,等)showAtLocation(View parent, int gravity, int x, int y);(3)、其它函数 public void dismiss()
//另外⼏个函数,这⾥不讲其意义,下篇细讲
public void setFocusable(boolean focusable)
public void setTouchable(boolean touchable)
public void setOutsideTouchable(boolean touchable)
public void setBackgroundDrawable(Drawable background)
这⼏个函数⾥,这篇只会⽤到dismiss(),⽤于不需要的时候,将窗体隐藏掉。好了,废话不多说了,我们就做⼀个上⾯的例⼦来看⼀下。⼆、简单⽰例(showAtLocation显⽰窗体)在这个例⼦中,我们实现两个功能,弹出popupWindow和Item点击响应1、主布局()从效果图中也可以看到主布局只有⼀个button,什么都没有,所以它的布局代码哪下:
android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
2、PopupWindow布局()
在概述中,我们提到了,必须为PopupWindow设置布局,从效果图中,我也可以看到它的布局有三个item,中间⽤横线分开。所以这⾥布局使⽤Listview应该更合适,但为了减轻代码难度,我们直接使⽤TextView和分隔线来代替,代码如下:
xmlns:android="/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#ffffff" android:orientation="vertical" android:paddingBottom="2dp"> android:layout_width="match_parent" android:layout_height="2.25dp" android:background="#fa7829" android:layout_alignParentTop="true"/> android:id="@+id/pop_computer" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/pop_text_style" android:text="计算机"/> android:layout_width="match_parent" android:layout_height="1dp" android:background="@drawable/list_line"/> android:id="@+id/pop_financial" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/pop_text_style" android:text="⾦融"/> android:layout_width="match_parent" android:layout_height="1dp" android:background="@drawable/list_line"/> android:id="@+id/pop_manage" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/pop_text_style" android:text="管理"/> android:layout_width="match_parent" android:layout_height="1dp"/>
3、MainActivity代码先贴出来完整代码,然后再逐步讲解: public class MainActivity extends Activity implements kListener{
private PopupWindow mPopWindow;
@Override
public void onCreate(Bundle savedInstanceState) {
te(savedInstanceState);
setContentView();
Button btn = (Button) findViewById();
lickListener(new kListener() {
@Override
public void onClick(View v) {
showPopupWindow();
}
});
}
private void showPopupWindow() {
//设置contentView
View contentView = ().inflate(ayout, null);
mPopWindow = new PopupWindow(contentView,
_CONTENT, _CONTENT, true);
tentView(contentView);
//设置各个控件的点击响应
TextView tv1 = (TextView)ewById(_computer);
TextView tv2 = (TextView)ewById(_financial);
TextView tv3 = (TextView)ewById(_manage);
lickListener(this);
lickListener(this);
lickListener(this);
//显⽰PopupWindow
View rootview = ().inflate(, null);
Location(rootview, , 0, 0);
}
@Override
public void onClick(View v) {
int id = ();
switch (id){
case _computer:{
xt(this,"clicked computer",_SHORT).show();
s();
}
break;
case _financial:{
xt(this,"clicked financial",_SHORT).show();
s();
}
break;
case _manage:{
xt(this,"clicked manage",_SHORT).show();
s();
}
break;
}
}
}
(1)⾸先看OnCreate()在OnCreate()中只做了⼀个操作,当点击Button时,显⽰窗体: public void onCreate(Bundle savedInstanceState) {
te(savedInstanceState);
setContentView();
Button btn = (Button) findViewById();
lickListener(new kListener() {
@Override
public void onClick(View v) {
showPopupWindow();
}
});
}
(2)、显⽰PopupWindow下⾯是有关窗体操作的代码: private void showPopupWindow() {
//设置contentView
View contentView = ().inflate(ayout, null);
mPopWindow = new PopupWindow(contentView,
_CONTENT, _CONTENT, true);
//设置各个控件的点击响应
TextView tv1 = (TextView)ewById(_computer);
TextView tv2 = (TextView)ewById(_financial);
TextView tv3 = (TextView)ewById(_manage);
lickListener(this);
lickListener(this);
lickListener(this);
//显⽰PopupWindow
View rootview = ().inflate(, null);
Location(rootview, , 0, 0);
}
这⾥同样分为三部分:
第⼀部分:设置ContentView View contentView = ().inflate(ayout, null);
mPopWindow = new PopupWindow(contentView,_CONTENT, _CONTENT, true);
利⽤LayoutInflater获取ayout对应的View,然后利⽤我们上⾯所讲的构造函数三来⽣成mPopWindow;
这⾥ 要注意⼀个问题:在这个构造函数⾥,我们传进去了width和height全部都是WRAP_CONTENT;⽽在ayou的根布局中,我们定义的width和height代码是:layout_width="fill_parent",layout_height="wrap_content";原代码如下:
xmlns:android="/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#ffffff" android:orientation="vertical" android:paddingBottom="2dp"> ………………
从效果图中来看,明显PopupWindow宽度并没有全屏,显然是按代码中的布局为准。
这说明了:
如果在代码中重新设置了popupWindow的宽和⾼,那就以代码中所设置为准。(⾄于原因,下篇会讲)第⼆部分:设置各个控件的点击响应 TextView tv1 = (TextView)ewById(_computer);
TextView tv2 = (TextView)ewById(_financial);
TextView tv3 = (TextView)ewById(_manage);
lickListener(this);
lickListener(this);
lickListener(this);
这部分没什么好讲了,设置PopupWindow中各个控件的点击响应,但⼀定要注意的是,PopupWindow中各个控件的所在的布局是contentView,⽽不是在Activity中,如果⼤家直接使⽤ TextView tv1 = (TextView)findViewById(_computer);
肯定会报错,因为_computer这个ID值在当前Activtiy的布局⽂件中是找不到的。只有在ayout的布局⽂件中才会有!所以,这就是为什么,要在findViewById(_computer)前指定contentView的原因在实际项⽬中,很容易遇到像这种需要指定根布局的情况,⼤家需要注意。
有关响应,就没什么好讲的了,因为我们在类顶部派⽣了kListener,所以在OnClick函数中,直接处理即可,代码如下:(在点击不同的Item时,⼀边弹出不同的toast,⼀边将PopupWindow隐藏掉) @Override
public void onClick(View v) {
int id = ();
switch (id){
case _computer:{
xt(this,"clicked computer",_SHORT).show();
s();
}
break;
case _financial:{
xt(this,"clicked financial",_SHORT).show();
s();
}
break;
case _manage:{
xt(this,"clicked manage",_SHORT).show();
s();
}
break;
}
}
第三部分:showAtLocation显⽰窗体 View rootview = ().inflate(, null);
Location(rootview, , 0, 0);
showAtLocation的显⽰就将PopupWindow的实例放在⼀个⽗容器中,然后指定显⽰在⽗容器中的位置。
由于,我们要将mPopWindow放在整个屏幕的最低部,所以我们将做为它的⽗容器。将其显⽰在BOTTOM的位置。到这⾥,有关PopupWindow的显⽰及其中控件响应基本都讲完了,下⾯,我们就讲讲showAsDropDown显⽰窗体的⽤法。源码在⽂章底部给出三、另⼀⽰例(showAsDropDown显⽰窗体)⼤家先看下⾯这个效果图:
这个效果图演⽰的是,在点击标题栏右⽅的“菜单”按钮时,在其下⽅显⽰⼀个⾃定义的菜单列表。1、同样,我们先看看主布局代码()
android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> android:layout_height="wrap_content" android:background="#ffffff"> android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:textColor="#50484b" android:padding="10dp" android:text="返回"/> android:id="@+id/menu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:textColor="#50484b" android:padding="10dp" android:text="菜单"/>
这段代码的布局很简单,就是⽣成⼀个标题栏,上⾯有两个按钮,“返回”和“菜单”2、PopupWindow布局代码()这部分布局也不难,只得利⽤纯代码硬⽣成⼀个列表的布局。在实际项⽬中,⼤家应该使⽤listview来动态⽣成列表,这样⽣成的popupWindow就是可以复⽤的了。有关布局就不再多讲,跟上⾯的布局基本⼀样,只是换了背景。
xmlns:android="/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/pop_bg" android:orientation="vertical" android:paddingBottom="2dp"> android:id="@+id/pop_computer" android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/pop_text_style" android:text="计算机"/> android:layout_width="match_parent" android:layout_height="1dp" android:background="@drawable/list_line"/> android:id="@+id/pop_financial" android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/pop_text_style" android:text="⾦融"/> android:layout_width="match_parent" android:layout_height="1dp" android:background="@drawable/list_line"/> android:id="@+id/pop_manage" android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/pop_text_style" android:text="管理"/> android:layout_width="match_parent" android:layout_height="1dp"/>
3、MainActivity代码同样是先贴出来完整代码,然后再细讲。 public class MainActivity extends Activity implements kListener{
private PopupWindow mPopWindow;
private TextView mMenuTv;
@Override
public void onCreate(Bundle savedInstanceState) {
te(savedInstanceState);
setContentView();
mMenuTv = (TextView)findViewById();
lickListener(new kListener() {
@Override
public void onClick(View v) {
showPopupWindow();
}
});
}
private void showPopupWindow() {
View contentView = ().inflate(ayout, null);
mPopWindow = new PopupWindow(contentView);
th(_CONTENT);
ght(_CONTENT);
TextView tv1 = (TextView)ewById(_computer);
TextView tv2 = (TextView)ewById(_financial);
TextView tv3 = (TextView)ewById(_manage);
lickListener(this);
lickListener(this);
lickListener(this);
DropDown(mMenuTv);
}
@Override
public void onClick(View v) {
int id = ();
switch (id){
case _computer:{
xt(this, "clicked computer", _SHORT).show();
s();
}
break;
case _financial:{
xt(this,"clicked financial",_SHORT).show();
s();
}
break;
case _manage:{
xt(this,"clicked manage",_SHORT).show();
s();
}
break;
}
}
}
这段代码的意义就是点击menu弹出popupwindow,然后对各个item进⾏响应,我们主要讲讲showPopupWindow() 这部分,对于item响应的部分与上个⽰例都⼀样,就不再细讲。 private void showPopupWindow() {
View contentView = ().inflate(ayout, null);
mPopWindow = new PopupWindow(contentView);
th(_CONTENT);
ght(_CONTENT);
TextView tv1 = (TextView)ewById(_computer);
TextView tv2 = (TextView)ewById(_financial);
TextView tv3 = (TextView)ewById(_manage);
lickListener(this);
lickListener(this);
lickListener(this);
DropDown(mMenuTv);
}
这⾥⾸先注意的⼀个地⽅,在这个⽰例中,我们是使⽤的构造⽅法⼆来⽣成的PopupWindow实例的,同样,再强调⼀遍:contentView,Width,Height这三个元素是必须设置的,缺⼀不可!⾄于为什么要显式设置Width,Height,我们下篇会讲到。 View contentView = ().inflate(ayout, null);
mPopWindow = new PopupWindow(contentView);
th(_CONTENT);
ght(_CONTENT);
然后就是使⽤showAsDropDown()显⽰PopupWindow: DropDown(mMenuTv);
⼤家也现样可以使⽤showAsDropDown(View anchor, int xoff, int yoff):来添加相对x轴和y轴的位移量。具体⽤法就不再细讲,没什么难度,⼤家试⼀试即可。
好了,这部分⽰例也讲完了,下⾯我们就在这个⽰例上升级⼀个功能:讲讲怎么在弹出PopupWindow的同时利⽤阴影把背景全部给遮罩起来。
源码在⽂章底部给出四、提⾼:为菜单添加阴影这部分的效果图是下⾯这样的:
从效果图中可以看出,这部分是上⼀个⽰例的升级版,就是在点出PopupWindow的同时,把背景⽤半透明⿊⾊遮罩住,像弹出AlertDialog⼀样的效果。下⾯就来看看这个效果是怎么实现的吧。1、PopupWindow布局()其实原理很简单,使PopupWindow的界⾯充满全屏,⽽实际的列表菜单只是其中的⼀个⼦布局即可,所以此时的PopupWindow的布局代码如下:
xmlns:android="/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#66000000"> android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/pop_bg" android:orientation="vertical" android:paddingBottom="2dp" android:layout_alignParentRight="true"> android:id="@+id/pop_computer" android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/pop_text_style" android:text="计算机"/> android:layout_width="match_parent" android:layout_height="1dp" android:background="@drawable/list_line"/> android:id="@+id/pop_financial" android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/pop_text_style" android:text="⾦融"/> android:layout_width="match_parent" android:layout_height="1dp" android:background="@drawable/list_line"/> android:id="@+id/pop_manage" android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/pop_text_style" android:text="管理"/> android:layout_width="match_parent" android:layout_height="1dp"/>
可见在列表项外⾯⼜包了⼀层RelativeLayout,将列表的根布局LinearLayout靠⽗窗⼝右边显⽰即可。给RelativeLayout添加了半透明背景android:background=”#66000000”
这样要⾮常注意的是,根布局RelativeLayout设置的android:layout_width和android:layout_height是⽆意义的,因为我们会通过代码重新设置: private void showPopupWindow() {
View contentView = ().inflate(ayout, null);
mPopWindow = new PopupWindow(contentView);
th(_PARENT);
ght(_PARENT);
………………//设置各控件点击响应
DropDown(mMenuTv);
}
在这⾥,我们通过代码将PopupWindow的width和height设置为_PARENT。那⼤家可能会有疑问:为什么我在xml中布局中明明写好了根布局RelativeLayout的宽和⾼,为什么⾮要我们在代码中重新设置呢?不设置还显⽰不出来…………
下篇,我们将会解答这个问题。
好啦,这个⽰例关键部分讲完了,其它的⼤家就看源码吧。
源码在⽂章底部给出五、为PopupWindow添加动画先看看效果:
为PopupWindow添加动画并不难,只需要使⽤⼀个函数即可: //设置动画所对应的style
mationStyle(tMenuAnim);
下⾯就来看看具体是如何添加动画的1、⽣成动画对应的style(1)、进⼊时的动画:(context_menu_)
android:duration="@android:integer/config_shortAnimTime" android:fromXDelta="0" android:fromYDelta="100%p" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:toXDelta="0" android:toYDelta="0"/> 这段代码的意义就是从底部进⼊,即从Y轴100%的位置移动到0的位置。。(2)、退出时动画(context_menu_) android:duration="@android:integer/config_shortAnimTime" android:fromXDelta="0" android:fromYDelta="0" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:toXDelta="0" android:toYDelta="100%p" /> 效果是从上向下移动。(3)、最后,⽣成对应的style—contextMenuAnim android:windowEnterAnimation设置进场动画,android:windowExitAnimation设置出场动画。2、使⽤AnimationStyle使⽤时⾮常简单,直接将对应的style通过setAnimationStyle设置进PopupWindow实例即可,代码如下,难度不⼤,不再细讲。 private void showPopupWindow() { View contentView = ().inflate(ayout, null); mPopWindow = new PopupWindow(contentView); th(_PARENT); ght(_PARENT); ………………//设置各⼦项点击响应 mationStyle(tMenuAnim); DropDown(mMenuTv); } 到这⾥,这个⽰例的代码就讲完了。源码在⽂章底部⼀起给出。这篇讲述了有关PopupWindow的基本使⽤⽅法,下篇将针对还未讲述的⼏个函数,以及问题点结合源码深⼊剖析。源码内容:1、《PopshowAtLocation》:第⼆部分:简单⽰例(showAtLocation显⽰窗体)对应源码2、《PopupShowAsDropDown》:第三部分:另⼀⽰例(showAsDropDown显⽰窗体) 对应源码3、《PopDropDownBg》:第四部分:提⾼:为菜单添加阴影 对应源码4、《PopupAnim》:第五部分:为PopupWindow添加动画 对应源码如果本⽂有帮到你,记得加关注哦
发布者:admin,转转请注明出处:http://www.yc00.com/web/1689430015a246915.html
评论列表(0条)