Android实现底部弹出PopupWindow背景逐渐变暗效果

Android实现底部弹出PopupWindow背景逐渐变暗效果

作者:Arbo_Xjb 字体:[增加 减小] 类型:转载 时间:2016-10-22 我要评论

这篇文章主要为大家详细介绍了Android实现底部弹出PopupWindow背景逐渐变暗效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
scrolling="no" src="//pos.baidu.com/s?hei=100&wid=680&di=u2866688&ltu=http%3A%2F%2Fwww.jb51.net%2Farticle%2F95437.htm&ccd=24&ti=Android%E5%AE%9E%E7%8E%B0%E5%BA%95%E9%83%A8%E5%BC%B9%E5%87%BAPopupWindow%E8%83%8C%E6%99%AF%E9%80%90%E6%B8%90%E5%8F%98%E6%9A%97%E6%95%88%E6%9E%9C_Android_%E8%84%9A%E6%9C%AC%E4%B9%8B%E5%AE%B6&pss=1349x12757&ant=0&dis=0&tcn=1504602939&cpl=0&cec=gbk&cja=false&pcs=1349x604&ari=2&cce=true&chi=2&ps=826x179&dai=1&drs=1&tpr=1504602938925&exps=111000&col=zh-CN&cmi=0&psr=1366x768&dri=1&cdo=-1&tlm=1504602938&pis=-1x-1&dc=2&dtm=HTML_POST&par=1366x728&cfv=0" width="680" height="100">
    <div id="content">

在Android开发中,经常需要通过点击某个按钮弹出对话框或者选择框,通过Dialog或者PopupMenu、PopupWindow都能实现。
这里主要介绍后两者:PopupMenu、PopupWindow的实现。 先看两个效果图上边PopupMenu,下边PopupWindow:
PopupMenu PopupWindow

PopupMenuPopupWindow

一、PopupMenu实现:

PopupMenu实现起来比较简单,主要用来实现根据按钮附近弹出的对话框。

首先定义一个menu文件\res\menu\headmenu.xml:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  xmlns:tools = "http://schemas.android.com/tools" tools:context = "com.arbo.hero.LoginActivity" >
  < item
  android:id = "@+id/camera"
  android:title = "拍照"
  android:orderInCategory = "100"
  app:showAsAction = "never" />
  < item
  android:id = "@+id/gallery"
  android:title = "从相册中选取"
  android:orderInCategory = "100"
  app:showAsAction = "never" />
  < item
  android:id = "@+id/cancel"
  android:title = "取消"
  android:orderInCategory = "100"
  app:showAsAction = "never" />
 
</ menu >

创建一个PopupMenu并添加点击事件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private void showPopmenu(View view){
  popupMenu = new PopupMenu( this ,view);
  popupMenu.getMenuInflater().inflate(R.menu.headmenu,popupMenu.getMenu());
  popupMenu.setOnMenuItemClickListener( new PopupMenu.OnMenuItemClickListener() {
   @Override
   public boolean onMenuItemClick(MenuItem item) {
   switch (item.getItemId()){
    case R.id.camera:
    Toast.makeText(HeadPortrait. this , "Click camera" ,Toast.LENGTH_SHORT).show();
    break ;
    case R.id.gallery:
    Toast.makeText(HeadPortrait. this , "Click gallery" ,Toast.LENGTH_SHORT).show();
    break ;
    case R.id.cancel:
    Toast.makeText(HeadPortrait. this , "Click cancel" ,Toast.LENGTH_SHORT).show();
    break ;
   }
   return false ;
   }
  });
  popupMenu.show();
  }

MainActivity很简单,点击按钮调用showPopmenu()方法即可:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MainActivity extends Activity{
  @Override
  protected void onCreate(Bundle savedInstanceState) {
  super .onCreate(savedInstanceState);
  //main.xml页面主布局只有一个按钮,这里就不贴代码了
  setContentView(R.layout.main);
  Button button = (Button) findViewById(R.id.button);
  button.setOnClickListener( new View.OnClickListener() {
   @Override
   public void onClick(View view) {
   //点击按钮就创建并显示一个popupMenu
   showPopmenu(btnmenu);
   }
  }
  }
}

以上,就实现了利用PopupMenu在按钮附近弹出一个选择框。
PopupMenu的优点:简单;根据菜单大小自适应位置,在按钮附近弹出;适合某些情景。

缺点:形式比较单一,效果一般。

二、PopupWindow实现:

相比之下,PopupWindow的实现复杂一些,但是自定义性更强,它可以将任意界面设置为PopupWindow。

先看弹出window布局window_popup.xml:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout
  android:layout_width = "match_parent"
  android:layout_height = "match_parent"
  android:layout_marginLeft = "@dimen/activity_horizontal_margin"
  android:layout_marginRight = "@dimen/activity_horizontal_margin"
  android:background = "#dadada"
  android:orientation = "vertical" >
  < LinearLayout
  android:layout_width = "match_parent"
  android:layout_height = "wrap_content"
  android:orientation = "vertical" >
  < Button
   android:id = "@+id/camera"
   android:layout_width = "match_parent"
   android:layout_height = "wrap_content"
   android:text = "拍照"
   android:background = "#f0f0f0"
   />
  < TextView
   android:layout_width = "match_parent"
   android:layout_height = "1dp"
   android:background = "#2d2c2c"
   />
  < Button
   android:background = "#f0f0f0"
   android:id = "@+id/gallery"
   android:layout_width = "match_parent"
   android:layout_height = "wrap_content"
   android:text = "从手机相册选择" />
  < TextView
   android:layout_width = "match_parent"
   android:layout_height = "1dp"
   android:background = "#2d2c2c"
   />
  < Button
   android:background = "#f0f0f0"
   android:id = "@+id/savepicture"
   android:layout_width = "match_parent"
   android:layout_height = "wrap_content"
   android:text = "保存图片" />
 
  </ LinearLayout >
 
  < LinearLayout
  android:layout_width = "match_parent"
  android:layout_height = "wrap_content"
  android:layout_marginTop = "10dp"
  android:orientation = "vertical" >
 
  < Button
   android:background = "#f0f0f0"
   android:id = "@+id/cancel"
   android:layout_width = "match_parent"
   android:layout_height = "wrap_content"
   android:text = "取消"
   />
  </ LinearLayout >
</ LinearLayout >

布局的效果图:

布局

创建popupWindow并为其添加点击事件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void bottomwindow(View view) {
  if (popupWindow != null && popupWindow.isShowing()) {
   return ;
  }
  LinearLayout layout = (LinearLayout) getLayoutInflater().inflate(R.layout.window_popup, null );
  popupWindow = new PopupWindow(layout,
   ViewGroup.LayoutParams.MATCH_PARENT,
   ViewGroup.LayoutParams.WRAP_CONTENT);
  //点击空白处时,隐藏掉pop窗口
  popupWindow.setFocusable( true );
  popupWindow.setBackgroundDrawable( new BitmapDrawable());
  //添加弹出、弹入的动画
  popupWindow.setAnimationStyle(R.style.Popupwindow);
  int [] location = new int [ 2 ];
  view.getLocationOnScreen(location);
  popupWindow.showAtLocation(view, Gravity.LEFT | Gravity.BOTTOM, 0 , -location[ 1 ]);
  //添加按键事件监听
  setButtonListeners(layout);
  //添加pop窗口关闭事件,主要是实现关闭时改变背景的透明度
  popupWindow.setOnDismissListener( new poponDismissListener());
  backgroundAlpha(1f);
  }

事件监听的函数setButtonListeners() :

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
private void setButtonListeners(LinearLayout layout) {
  Button camera = (Button) layout.findViewById(R.id.camera);
  Button gallery = (Button) layout.findViewById(R.id.gallery);
  Button savepicture = (Button) layout.findViewById(R.id.savepicture);
  Button cancel = (Button) layout.findViewById(R.id.cancel);
 
  camera.setOnClickListener( new View.OnClickListener() {
   @Override
   public void onClick(View view) {
   if (popupWindow != null && popupWindow.isShowing()) {
    //在此处添加你的按键处理 xxx
    popupWindow.dismiss();
   }
   }
  });
  gallery.setOnClickListener( new View.OnClickListener() {
   @Override
   public void onClick(View view) {
   if (popupWindow != null && popupWindow.isShowing()) {
    //在此处添加你的按键处理 xxx
    popupWindow.dismiss();
   }
   }
  });
  savepicture.setOnClickListener( new View.OnClickListener() {
   @Override
   public void onClick(View view) {
   if (popupWindow != null && popupWindow.isShowing()) {
    //在此处添加你的按键处理 xxx
    popupWindow.dismiss();
   }
   }
  });
  cancel.setOnClickListener( new View.OnClickListener() {
   @Override
   public void onClick(View view) {
   if (popupWindow != null && popupWindow.isShowing()) {
    popupWindow.dismiss();
   }
   }
  });
  }

弹出、收回的动画:

若res文件夹下没有anim目录,则自己添加一个:new–>Android resource directory 名字填anim。然后新建两个tranlate文件:

弹出 window_out.xml :

?
1
2
3
4
5
<? xml version = "1.0" encoding = "utf-8" ?>
< translate xmlns:android = "http://schemas.android.com/apk/res/android"
  android:interpolator = "@android:anim/decelerate_interpolator"
  android:fromYDelta = "100%" android:toYDelta = "0"
  android:duration = "300" />

收回 window_back.xml:

?
1
2
3
4
5
<? xml version = "1.0" encoding = "utf-8" ?>
< translate xmlns:android = "http://schemas.android.com/apk/res/android"
  android:interpolator = "@android:anim/accelerate_interpolator"
  android:fromYDelta = "0" android:toYDelta = "100%"
  android:duration = "200" />

然后在style.xml中添加我们的这两个动画:

?
1
2
3
4
< style name = "Popupwindow" >
  < item name = "android:windowEnterAnimation" >@anim/window_out</ item >
  < item name = "android:windowExitAnimation" >@anim/window_back</ item >
  </ style >

还是上面的同一个MainActivity,把按钮点击事件的处理函数换成popupwindow的即可:

?
1
2
3
4
5
6
btnmenu.setOnClickListener( new View.OnClickListener() {
   @Override
   public void onClick(View view) {
   bottomwindow(btnmenu);
   }
  }

以上,就可以实现这样的点击按钮从屏幕底部弹出window窗口的效果,如下:

底部弹出

底部弹出

但是,这样的效果并不好,我们希望弹出windows的时候,其他背景可以变成半透明,这样可以突出重点。网上的方法是通过这段代码来改变背景的透明度的:

?
1
2
3
4
5
6
7
8
9
10
/**
  * 设置添加屏幕的背景透明度
  * @param bgAlpha
  */
  public void backgroundAlpha( float bgAlpha)
  {
  WindowManager.LayoutParams lp = getWindow().getAttributes();
  lp.alpha = bgAlpha; //0.0-1.0
  getWindow().setAttributes(lp);  getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
  }

然后在弹出的时候将背景设为半透明:

bottomwindow(btnmenu);
backgroundAlpha(0.5f);

在返回的时候设置回来:

backgroundAlpha(1f);

这的确是可以实现效果,但是点击的时候突然变暗和变亮,效果不太好!如下:

变暗

我希望是弹出的过程中,慢慢变暗。是有一个过程的,而不是一下子就暗下来了。这里利用延时和Handler来动态地改变背景的透明度。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//在调用弹出的方法后,开启一个子线程
   @Override
   public void onClick(View view) {
   bottomwindow(btnmenu);
   new Thread( new Runnable(){
    @Override
    public void run() {
    while (alpha> 0 .5f){
     try {
     //4是根据弹出动画时间和减少的透明度计算
     Thread.sleep( 4 );
     } catch (InterruptedException e) {
     e.printStackTrace();
     }
     Message msg =mHandler.obtainMessage();
     msg.what = 1 ;
     //每次减少0.01,精度越高,变暗的效果越流畅
     alpha-= 0 .01f;
     msg.obj =alpha ;
     mHandler.sendMessage(msg);
    }
    }
 
   }).start();
   }

同理,返回的时候把透明度跳回来:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
  * 返回或者点击空白位置的时候将背景透明度改回来
  */
  class poponDismissListener implements PopupWindow.OnDismissListener{
 
  @Override
  public void onDismiss() {
   // TODO Auto-generated method stub
   new Thread( new Runnable(){
   @Override
   public void run() {
    //此处while的条件alpha不能<= 否则会出现黑屏
    while (alpha<1f){
    try {
     Thread.sleep( 4 );
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    Log.d( "HeadPortrait" , "alpha:" +alpha);
    Message msg =mHandler.obtainMessage();
    msg.what = 1 ;
    alpha+= 0 .01f;
    msg.obj =alpha ;
    mHandler.sendMessage(msg);
    }
   }
 
   }).start();
  }
 
  }

在Handler里面我们调用改变背景透明的方法即可:

?
1
2
3
4
5
6
7
8
9
10
Handler mHandler = new Handler(){
  @Override
  public void handleMessage(Message msg) {
   switch (msg.what){
   case 1 :
    backgroundAlpha(( float )msg.obj);
    break ;
   }
  }
  };

这样修改以后,效果是这样的:

最终效果

以上,基本达到了逐渐变暗、变量的目的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

如对本文有疑问,请提交到交流社区,广大热心网友会为你解答!! 点击进入社区

scrolling="no" src="http://pos.baidu.com/s?hei=250&wid=650&di=u3025827&ltu=http%3A%2F%2Fwww.jb51.net%2Farticle%2F95437.htm&tlm=1504602938&tpr=1504602938925&pcs=1349x604&chi=2&ps=0x0&exps=111000&ant=0&cec=gbk&dri=1&ari=2&dai=2&cpl=0&col=zh-CN&drs=1&dis=0&cdo=-1&dc=2&cfv=0&cce=true&ccd=24&ti=Android%E5%AE%9E%E7%8E%B0%E5%BA%95%E9%83%A8%E5%BC%B9%E5%87%BAPopupWindow%E8%83%8C%E6%99%AF%E9%80%90%E6%B8%90%E5%8F%98%E6%9A%97%E6%95%88%E6%9E%9C_Android_%E8%84%9A%E6%9C%AC%E4%B9%8B%E5%AE%B6&pis=-1x-1&psr=1366x768&cja=false&pss=1349x12857&cmi=0&tcn=1504602939&dtm=HTML_POST&par=1366x728" width="650" height="250">
scrolling="no" src="http://pos.baidu.com/s?hei=200&wid=680&di=u2866701&ltu=http%3A%2F%2Fwww.jb51.net%2Farticle%2F95437.htm&ari=2&cja=false&cce=true&pss=1349x13107&chi=2&exps=111000&ti=Android%E5%AE%9E%E7%8E%B0%E5%BA%95%E9%83%A8%E5%BC%B9%E5%87%BAPopupWindow%E8%83%8C%E6%99%AF%E9%80%90%E6%B8%90%E5%8F%98%E6%9A%97%E6%95%88%E6%9E%9C_Android_%E8%84%9A%E6%9C%AC%E4%B9%8B%E5%AE%B6&tlm=1504602939&pis=-1x-1&cfv=0&cmi=0&cdo=-1&ps=12927x179&dtm=HTML_POST&dri=1&par=1366x728&cpl=0&cec=gbk&dis=0&tpr=1504602938925&pcs=1349x604&ant=0&dc=2&dai=3&col=zh-CN&drs=1&psr=1366x768&ccd=24&tcn=1504602939" width="680" height="200">

最新评论

评论 (2人参与0条评论)
等级不够,发表评论升至指定级别才能获得该特权。详情请参见等级说明
还没有评论,快来抢沙发吧!
  </div>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值