动画弹出PopupWindow并使背景变暗
来源:互联网 发布:mac用哪个word 编辑:程序博客网 时间:2024/05/05 18:45
我们在平常的android应用开发过程中,当应用数据太多太繁杂时,通常都会通过分类筛选让用户更好的找到自己想要的信息。因此利用PopupWindow或Dialog让用户快速选择定位是一个很好的选择。如我们想在美团上查找附近有什么电影院时:
点击按钮弹出popupwindow,popupwindow是很好实现的,只需要使用PopupWindow的构造方法再将自己写的布局引入进去即可:
View popupView = getLayoutInflater().inflate(R.layout.layout_popupwindow, null); mPopupWindow = new PopupWindow(popupView, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, true); //设置点击空白处消失 mPopupWindow.setTouchable(true); mPopupWindow.setOutsideTouchable(true); mPopupWindow.setBackgroundDrawable(new BitmapDrawable(getResources(), (Bitmap) null));
- 1
最后通过
mPopupWindow.showAsDropDown(anchor,xoff,yoff);
- 1
弹出popupwindow。
但是这样实现出来的效果只是在原来某个view旁弹出一个选项框,其他地方没有发生任何变化。如果想要在界面上实现一层黑色半透明遮罩将弹出框与主界面区分开来给用户更好的体验,这黑色透明背景又如何实现呢?
通过网上翻看资料,有各种各样的实现方法。其中有一种是在popupwindow弹出时改变window的透明度的属性,而监听到popupwindow dismiss的事件时再将其改回来。主要代码实现如下:
// 设置背景颜色变暗 WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.alpha = 0.7f; getWindow().setAttributes(lp); mPopupWindow.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss() { WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.alpha = 1f; getWindow().setAttributes(lp); } }); //摘自:http://blog.csdn.net/harryweasley/article/details/46914121
- 1
如果当PopupWindow是在屏幕中间或者从下方弹出时,这是一种很好的实现方式,但是如果我想要它从ActionBar正下方弹出,就会发现ActionBar的背景也变暗了,这样会显得界面很不协调。
由上面联想到,如果我在界面最上层自己放一个黑色半透明的View,平常让它隐藏掉,当PopupWindow显示的时候让它也显示出来就OK了,PopupWindow可以使用动画让其从ActionBar后面慢慢滑出来!
具体代码实现如下:
content_main.xml:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:showIn="@layout/activity_main" tools:context=".MainActivity"> <!--黑色背景遮罩层,平时隐藏 --> <View android:id="@+id/gray_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" android:background="#66000000"/></RelativeLayout>
- 1
MainActivity.java
public class MainActivity extends AppCompatActivity { private final static String TAG="MainActivity"; private PopupWindow mPopupWindow; private Toolbar toolbar; private View mGrayLayout; private boolean isPopWindowShowing=false; int fromYDelta; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); toolbar = (Toolbar) findViewById(R.id.toolbar); mGrayLayout=findViewById(R.id.gray_layout); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); //对黑色半透明背景做监听,点击时开始退出动画并将popupwindow dismiss掉 mGrayLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(isPopWindowShowing){ mPopupWindow.getContentView().startAnimation(AnimationUtil.createOutAnimation(MainActivity.this, fromYDelta)); mPopupWindow.getContentView().postDelayed(new Runnable() { @Override public void run() { mPopupWindow.dismiss(); } },AnimationUtil.ANIMATION_OUT_TIME); } } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { if(isPopWindowShowing){ mPopupWindow.getContentView().startAnimation(AnimationUtil.createOutAnimation(MainActivity.this, fromYDelta)); mPopupWindow.getContentView().postDelayed(new Runnable() { @Override public void run() { mPopupWindow.dismiss(); } },AnimationUtil.ANIMATION_OUT_TIME); }else{ showPopupWindow(); } // return true; } return super.onOptionsItemSelected(item); } private void showPopupWindow(){ final View contentView= LayoutInflater.from(this).inflate(R.layout.selectlist,null); TextView t1= (TextView) contentView.findViewById(R.id.text1); mPopupWindow=new PopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT); mPopupWindow.setBackgroundDrawable(new BitmapDrawable()); //将这两个属性设置为false,使点击popupwindow外面其他地方不会消失 mPopupWindow.setOutsideTouchable(false); mPopupWindow.setFocusable(false); mGrayLayout.setVisibility(View.VISIBLE); //获取popupwindow高度确定动画开始位置 int contentHeight=ViewUtils.getViewMeasuredHeight(contentView); Log.i(TAG,"contentview height="+contentHeight); mPopupWindow.showAsDropDown(toolbar, 0, 0); fromYDelta=-contentHeight-50; Log.i(TAG,"fromYDelta="+fromYDelta); mPopupWindow.getContentView().startAnimation(AnimationUtil.createInAnimation(this, fromYDelta)); mPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { @Override public void onDismiss() { isPopWindowShowing=false; mGrayLayout.setVisibility(View.GONE); } }); t1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Snackbar.make(findViewById(R.id.gray_layout), "click 1", Snackbar.LENGTH_SHORT) .setAction("Action", null).show(); } }); isPopWindowShowing=true; }}
- 1
AnimationUtil.java
public class AnimationUtil { //动画持续时间 public final static int ANIMATION_IN_TIME=500; public final static int ANIMATION_OUT_TIME=500; public static Animation createInAnimation(Context context,int fromYDelta){ AnimationSet set=new AnimationSet(context,null); set.setFillAfter(true); TranslateAnimation animation=new TranslateAnimation(0,0,fromYDelta,0); animation.setDuration(ANIMATION_IN_TIME); set.addAnimation(animation); AlphaAnimation alphaAnimation=new AlphaAnimation(0,1); alphaAnimation.setDuration(ANIMATION_IN_TIME); set.addAnimation(alphaAnimation); return set; } public static Animation createOutAnimation(Context context,int toYDelta){ AnimationSet set=new AnimationSet(context,null); set.setFillAfter(true); TranslateAnimation animation=new TranslateAnimation(0,0,0,toYDelta); animation.setDuration(ANIMATION_OUT_TIME); set.addAnimation(animation); AlphaAnimation alphaAnimation=new AlphaAnimation(1,0); alphaAnimation.setDuration(ANIMATION_OUT_TIME); set.addAnimation(alphaAnimation); return set; }}
- 1
selectlist.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ffffff" android:orientation="vertical"> <TextView android:id="@+id/text1" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:text="@string/select_1"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:text="@string/select_2"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:text="@string/select_3"/></LinearLayout>
- 1
ViewUtils.java
public class ViewUtils { /** * 获取控件的高度 */ public static int getViewMeasuredHeight(View view) { calculateViewMeasure(view); return view.getMeasuredHeight(); } /** * 获取控件的宽度 */ public static int getViewMeasuredWidth(View view) { calculateViewMeasure(view); return view.getMeasuredWidth(); } /** * 测量控件的尺寸 */ private static void calculateViewMeasure(View view) { int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); view.measure(w, h); }}
- 1
实现效果如下:
注意!!!
onCreate方法中调用PopupWindow的错误:android.view.WindowManager$BadTo
如题:在activity的oncreate方法中使用popupwindow出现以下错误:
android.view.WindowManager$BadTokenException: Unable to add window --
token null is not valid; is your activity running?
错误代码如下 :
- pop = new PopupWindow(pop_view,320,250);
- pop.showAtLocation(parent, Gravity.TOP,0, 0);
解决方法:
应把pop.showAtLocation(parent, Gravity.TOP,0, 0)这一句移出oncreate方法,在控件渲染完毕后再使用。
但是移出oncreate方法的话该移到哪里去呢?网友的方法大概是这几种:
1、移到事件中(比如一个button的click事件中);
2、移到子线程中;另起一线程,在线程中不断循环,直到判断控件是否渲染完毕(如长宽大于0),不推荐。。。
3、移到重写的控件(parent)中,在控件ondraw()完后生成pop。
ps:1、2绝对没问题,3没测试过。
后来在网上找到一个绝佳的方法:
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
- // TODO Auto-generated method stub
- super.onWindowFocusChanged(hasFocus);
- if(hasFocus){
- showPopupWindow(getApplicationContext());
- }
- }
其中showPopupWindow(getApplicationContext())是我自己定义的专门显示popupwindow的一个函数。
当activity获得焦点之后,activity是加载完毕的了,这个方法的技巧性比较强,很难想到
源码下载:https://github.com/lololiu/demo4popupwindow.git
- 动画弹出PopupWindow并使背景变暗
- 动画弹出PopupWindow并使背景变暗
- 【Android开发】动画弹出PopupWindow并使背景变暗
- 弹出popupwindow背景变暗
- Android 动画效果弹出PopupWindow,同时屏幕背景变暗
- Android-实现底部弹出PopupWindow并让背景逐渐变暗
- 如何弹出窗口并使背景变暗
- popupwindow弹出,父类背景变暗问题
- popupWindow弹出来后,背景变暗
- PopupWindow弹出框且背景变暗
- 弹出PopupWindow背景变暗的实现
- popupWindow弹出来后,背景变暗
- PopupWindow弹出框与背景变暗的实现(附带动画效果)
- 解决PopupWindow弹出后背景变暗的问题 背景透明度
- Android弹出popupWindow 背景变暗(背景半透明)(两种写法)
- 华为手机PopupWindow弹出时背景不变暗问题
- 华为手机PopupWindow弹出时背景不变暗问题
- Android实现底部弹出PopupWindow背景逐渐变暗效果
- 让用户故事真的像故事那样
- Android中如何区分TF【SD】卡路径和USB路径
- 对于Unity中旋转问题的一点总结
- UEditor配置笔记(持续更新中)
- 树莓派玩转A7模块(gprs篇)
- 动画弹出PopupWindow并使背景变暗
- spring boot 学习地址
- Android Https的安全使用
- Axios 请求配置参数详解
- chrome Provisional headers are shown
- React 简介、准备
- empty 与 !
- xxxx
- 线上应用故障排查之一:高CPU占用