美文网首页
PopupWindow

PopupWindow

作者: A_Coder | 来源:发表于2016-11-07 09:49 被阅读0次

官方文档对该控件的描述是:“一个弹出窗口控件,可以用来显示任意视图(View),而且会浮动在当前活动(activity)的顶部”。PopupWindow可以让我们实现多种自定义控件,例如:menu、alertdialog等弹窗似的View。

  • 改变PopupWindow的视图内容
    可以通过setContentView来改变popup的显示内容,也可以用来初始化PopupWindow的View,比如使用构造函数public PopupWindow (Context context)获得的Popupwindow就只能用setContentView来设置内容。
PopupWindow popupWindow = new PopupWindow(context);
popupWindow.setContentView(contentview);
  • 获得PopupWindow的视图内容
public View getContentView()
  • 显示PopupWindow

    • showAsDropDown(View anchor):相对某个控件的位置(正左下方),无偏移
    • showAsDropDown(View anchor, int xoff, int yoff):相对某个控件的位置,有偏移
    • showAtLocation(View parent, int gravity, int x, int y):相对于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移
  • 有两种方法设置PopupWindow的大小:

    • 调用有宽高参数的构造函数:
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View contentview = inflater.inflate(R.layout.popup_process, null);
PopupWindow popupWindow = new PopupWindow(contentview,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
  • 通过setWidth和setHeight设置
PopupWindow popupWindow = new PopupWindow(contentview);
popupWindow.setWidth(LayoutParams.WRAP_CONTENT);           
popupWindow.setHeight(LayoutParams.WRAP_CONTENT);
  • PopUpWindow的焦点:
    一般情况下setFocusable(true);
    其他任何事件的响应都必须发生在PopupWindow消失之后, (home 等系统层面的事件除外)。比如这样一个PopupWindow出现的时候,按back键首先是让PopupWindow消失,第二次按才是退出activity,准确的说是想退出activity你得首先让PopupWindow消失,因为不并是任何情况下按back PopupWindow都会消失,必须在PopupWindow设置了背景的情况下 。

  • 点击空白处的时候让PopupWindow消失
    要让点击PopupWindow之外的地方PopupWindow消失你需要调用setBackgroundDrawable(new BitmapDrawable());
    设置背景,为了不影响样式,这个背景是空的。还可以这样写,觉得这样要保险些:

setBackgroundDrawable(new ColorDrawable(0x00000000));

背景不为空但是完全透明。如此设置还能让PopupWindow在点击back的时候消失。


示例:
弹出框布局title_popupwindow.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="wrap_content"  
    android:layout_height="wrap_content">  
  
    <ListView  
        android:id="@+id/popupwindow"  
        android:background="@drawable/title_background"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:divider="@drawable/title_background_line"  
        android:listSelector="@drawable/title_background_pressed"  //选中的时候背景图片
        android:cacheColorHint="@android:color/transparent">  //去除listview的拖动背景色
    </ListView>  
</RelativeLayout>  

弹出框的item的布局popupwindow_item.xml

<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content"  
    android:padding="8.0dip" >  
  
    <TextView  
        android:id="@+id/popup_item"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:textStyle="bold"  
        android:singleLine="true"  
        android:ellipsize="end"  
        android:textColor="#ffffffff"/>  
  
</RelativeLayout>  

写一个PopupWindow的派生类MyPopupWindow

public class MyPopupWindow extends PopupWindow {  
    /** 
     * 上下文对象 
     */  
    private Context mContext;  
    /** 
     * 回调接口对象 
     */  
    private OnPopupWindowClickListener listener;  
    /** 
     * ArrayAdapter对象 
     */  
    private ArrayAdapter adapter;  
    /** 
     * ListView的数据源 
     */  
    private List<String> list = new ArrayList<String>();  
    /** 
     * PopupWindow的宽度 
     */  
    private int width = 0;  
  
    public MyPopupWindow(Context context){  
        super(context);   
        mContext = context;  
        initView();  
    }  
      
    private void initView(){  
        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
        View popupView = inflater.inflate(R.layout.title_popupwindow, null);  
        // 设置MyPopupWindow的View  
        this.setContentView(popupView);  
          
        //设置宽度,若没有设置宽度为LayoutParams.WRAP_CONTENT  
        this.setWidth(250);    
        this.setHeight(LayoutParams.WRAP_CONTENT);  
          
        //设置动画  
        this.setAnimationStyle(R.style.popupwindow_animation);  
          
        //设置ListView点击响应
        this.setFocusable(true);  
        // 实例化一个ColorDrawable颜色为半透明,点back键和其他地方使其消失
        this.setBackgroundDrawable(new ColorDrawable(0x00000000));   
        this.setOutsideTouchable(true);  
              
        ListView listView = (ListView) popupView.findViewById(R.id.popupwindow);  
        adapter = new ArrayAdapter(mContext, R.layout.popupwindow_item, R.id.popup_item, list);  
        listView.setAdapter(adapter);  
          
        //ListView的点击事件  
        listView.setOnItemClickListener(new OnItemClickListener() {  
  
            @Override  
            public void onItemClick(AdapterView<?> parent, View view,  
                    int position, long id) {  
                MyPopupWindow.this.dismiss();  //点击选项后,popupwindow消失
                if(listener != null){  
                    listener.onPopupWindowItemClick(position);  
                }  
            }  
        });  
          
    }  
      
    /** 
     * 为MyPopupWindow设置回调接口 
     * @param listener 
     */  
    public void setOnPopupWindowClickListener(OnPopupWindowClickListener listener){  
        this.listener = listener;  
    }  
      
  
    /** 
     * 设置数据的方法,供外部调用 
     * @param mList 
     */  
    public void changeData(List<String> mList) {  
        //这里用addAll也很重要,如果用this.list = mList,调用notifyDataSetChanged()无效  
        //notifyDataSetChanged()数据源发生改变的时候调用的,this.list = mList,list并没有发生改变  
        list.addAll(mList);  
        adapter.notifyDataSetChanged();  
    }  
      
      
    /** 
     * 回调接口.供外部调用 
     */  
    public interface OnPopupWindowClickListener{  
        /** 
         * 当点击PopupWindow的ListView 的item的时候调用此方法,用回调方法的好处就是降低耦合性 
         * @param position 位置 
         */  
        void onPopupWindowItemClick(int position);  
    }    
}  

用到了两个动画,在res文件夹下创建anim文件夹,里面创建两个动画xml
popupwindow_enter.xml

<?xml version="1.0" encoding="UTF-8"?>    
<set xmlns:android="http://schemas.android.com/apk/res/android">    
    <translate     
        android:fromXDelta="100%p"    
        android:toXDelta="0"    //这两行是從右邊進
        android:duration="500"/>    
</set>   

popupwindow_exit.xml

<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android">  
    <translate   
        android:fromXDelta="0"  
        android:toXDelta="100%p"  //这两行是往右邊消失
        android:duration="500"/>  
</set>  

在styles.xml里添加

 <style name="popupwindow_animation">  
        <item name="android:windowEnterAnimation">@anim/popupwindow_enter</item>  
        <item name="android:windowExitAnimation">@anim/popupwindow_exit</item>  
    </style>  

调用MyPopupWindow

public class PopupActivity extends AppcompatActivity {  
    MyPopupWindow mPopupWindow;  
    String [] items = {"刷新列表", "修改密码", "系统设置", "添加用户", "关于"};  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
          
        Button mButton = (Button) findViewById(R.id.button1);  
        mButton.setOnClickListener(new OnClickListener() {  
              
            @Override  
            public void onClick(View view) {  
                mPopupWindow.showAsDropDown(view);  
            }  
        });  
          
        mPopupWindow= new MyPopupWindow(this);  
        mPopupWindow.changeData(Arrays.asList(items));  
        mPopupWindow.setOnPopupWindowClickListener(new OnPopupWindowClickListener() {  
              
            @Override  
            public void onPopupWindowItemClick(int position) {  
                //需要实现的功能
                Toast.makeText(getApplication(), items[position], Toast.LENGTH_SHORT).show();  
            }  
        });  
    }  
  
  
}  

代码中的回调机制:

回调机制.png

注:

android:fromXDelta="0" android:toXDelta="-100%p" 往左邊消失
android:fromXDelta="-100%p" android:toXDelta="0" 從左邊進
android:fromXDelta="0" android:toXDelta="100%p" 往右邊消失
android:fromXDelta="100%p" android:toXDelta="0" 從右邊進

fromXDelta,fromYDelta 起始时X,Y座标,屏幕右下角的座标是X:320,Y:480
toXDelta, toYDelta 动画结束时X,Y的座标
interpolator 指定动画插入器
常见的有加速减速插入器 accelerate_decelerate_interpolator
加速插入器 accelerate_interpolator,
减速插入器 decelerate_interpolator。
fromXScale,fromYScale, 动画开始前X,Y的缩放,0.0为不显示, 1.0为正常大小
toXScale,toYScale, 动画最终缩放的倍数, 1.0为正常大小,大于1.0放大
pivotX, pivotY 动画起始位置,相对于屏幕的百分比,两个都为50%表示动画从屏幕中间开始
startOffset, 动画多次执行的间隔时间,如果只执行一次,执行前会暂停这段时间,单位毫秒 duration,一次动画效果消耗的时间,单位毫秒,值越小动画速度越快 repeatCount,动画重复的计数,动画将会执行该值+1次
repeatMode,动画重复的模式,reverse为反向,当第偶次执行时,动画方向会相反。
restart为重新执行,方向不变

参考:
PopupWindow的使用以及ArrayAdatper.notifyDataSetChanged()无效详解
Android-自定义PopupWindow

相关文章

网友评论

      本文标题:PopupWindow

      本文链接:https://www.haomeiwen.com/subject/smuguttx.html