实现从底部弹出的PopupWindow

根据项目需求了一个从底部弹出的PopupWindow,它的作用是选择地址的。省份,市,区都在同一个里面,同时选择。先上效果图。
这里写图片描述

一、思路

1、用一个ListView加载这三个部分的数据,在切换的时候,直接切换数据选择。
2、选完某个地址时,对外提供一个回调事件,比如在省份选择后,则应该查询对应的城市,这时候是要对外提供接口,查询到城市的数据后,再切换到城市的选择。
3、一个从底部弹出的popupwindow的实现。

二、代码实现

1、在构造方法里,初始化popupWindow,需要继承PopupWindow

public MyPopupWindow(final Activity activity, final View parent,
            List<String> provinces) {
        this.activity = activity;
        this.provinces = provinces;
        citys = new ArrayList<String>();
        districts =new ArrayList<String>();
        view = LayoutInflater.from(activity).inflate(R.layout.my_pop, null);
        //透明度
    view.startAnimation(AnimationUtils.loadAnimation(activity,R.anim.fade_ins));
    //从下往上出现    
     view.startAnimation(AnimationUtils.loadAnimation(activity,
                R.anim.push_bottom_in));
        //设置它的宽高
        setWidth(LayoutParams.MATCH_PARENT);
        setHeight(LayoutParams.WRAP_CONTENT);
        // 实例化一个ColorDrawable颜色为半透明
        ColorDrawable dw = new ColorDrawable(0xb0000000);
        // 设置SelectPicPopupWindow弹出窗体的背景
        this.setBackgroundDrawable(dw);
        setFocusable(true);
        setOutsideTouchable(true);
        setContentView(view);
        initView();
        initListener();
        initData();
    }

2、点击其他区域,取消popupview。

这部分代码是放在initListener();方法里面,单独抽出来的。取消它的时候同时在setOnDismissListener()里改变Activity的透明度。


        view.setOnTouchListener(new OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {

                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    int y = (int) event.getY();
                    // 没有点击到布局的区域
                    if (isShowing()) {
                        if (ll_content != null) {
                            if (y < getScreenHeight()
                                    - (ll_content.getHeight() + 50)) {
                                dismiss();
                            }
                        } else {
                            if (y < getScreenHeight() - (view.getHeight() + 50)) {
                                dismiss();
                            }
                        }
                    }
                    break;
                default:
                    break;
                }
                return true;
            }
        });
        setOnDismissListener(new OnDismissListener() {

            @Override
            public void onDismiss() {
                params = activity.getWindow().getAttributes();
                params.alpha = 1f;
                activity.getWindow().setAttributes(params);
            }
        });

3、对外提供更新数据的接口

共3个接口,主要是对外提供选中的数据,同时获取对应的地区的数据,让用户进行下一步的选择。

/**
     * @author Lenovo
     *选择省份后回调事件,这时候就要查询省份,对应的城市,需要自行保存省份的值,之后不在传
     */
    public interface SelectProvince{
        /**param 选中的省份*/
        public void onSelectProvince(String province,MyAdapter myAdapter);
    }
    /**
     * @author Lenovo
     *选择城市后回调事件,这时候要查询城市对应的地区,需要自行保存城市的值,之后不在传
     */
    public interface SelectCity{
        public void onSelectCity(String city,MyAdapter myAdapter);
    }
    /**
     * @author Lenovo
     *选择地区后回调事件
     */
    public interface SelectDistrict{
        public void onSelectDistrict(String district,MyAdapter myAdapter);
    }

4、设置Listview的点击事件,并调用上面的接口。

listView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View view, int pos,
                    long id) {
                if(currentPos==0){//省份
                    provinceSelected = pos;
                    citySelected = 0;
                    districtSelected = 0;
                    tv_city.setVisibility(View.VISIBLE);
                    showLine(1);
                    if(selectProvince!=null){
//回调事件1
                        selectProvince.onSelectProvince(provinces.get(pos),myAdapter);
                    }
                    tv_province.setText(provinces.get(pos));
                }else if(currentPos==1){//市区
                    citySelected = pos;
                    districtSelected = 0;
                    tv_district.setVisibility(View.VISIBLE);
                    showLine(2);
                    if(selectCity!=null){
//回调事件2                     
                        selectCity.onSelectCity(citys.get(pos), myAdapter);
                    }
                    tv_city.setText(citys.get(pos).toString());
                }else if(currentPos==2){//区域
                    districtSelected = pos;
                    if(selectDistrict!=null){
                    //回调事件3
                        selectDistrict.onSelectDistrict(districts.get(pos).toString(), myAdapter);
                    }
                    tv_district.setText(districts.get(pos).toString());
                    //选完区域后结束
                    dismiss();
                }
            }
        });

5、实现透明度、从下往上的动画。

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="20"
    android:fromAlpha="0.0"
    android:toAlpha="1.0" />
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="100"
    android:fromYDelta="100%"
    android:interpolator="@android:anim/decelerate_interpolator"
    android:toYDelta="0" />

6、显示PopupWindow

要设置外部Activity的透明度,如下代码。

public void showPopupWindow(View parent){
        params = activity.getWindow().getAttributes();
        params.alpha = 0.7f;
        activity.getWindow().setAttributes(params);
        showAtLocation(parent, Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0);
    }

7、外部Activity调用PopupWindow

主要是实现PopupWindow 所提供的三个接口

pop = new MyPopupWindow(this, content, provinces);
pop.setSelectProvinceListener(new SelectProvince() {

            @Override
            public void onSelectProvince(String province, MyAdapter myAdapter) {
                area = province;
                bt1.setText(area);
                //查询对应的城市
                pop.setCitys(citys);
                myAdapter.setDatas(citys);
                myAdapter.notifyDataSetChanged();
            }
        });
        pop.setSelectCityListener(new SelectCity() {
            @Override
            public void onSelectCity(String city, MyAdapter myAdapter) {
                area += city;
                bt1.setText(area);
                //查询对应的区
                pop.setDistricts(districts);
                myAdapter.setDatas(districts);
                myAdapter.notifyDataSetChanged();
            }
        });
        pop.setSelectDistrictListener(new SelectDistrict() {

            @Override
            public void onSelectDistrict(String district, MyAdapter myAdapter) {
                area += district;
                bt1.setText(area);
            }
        });

8、其它的一下方法

/**
     * 获取屏幕高度
     * 
     * @return
     */
    public int getScreenHeight() {
        int screenHeight = 0;
        DisplayMetrics dm = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
        if (dm != null) {
            int screenWidth = dm.widthPixels;// 屏幕宽度
            int height = dm.heightPixels;// 全屏幕高度
            int statusBarHeight = getStatusBarHeight(activity);// 状态栏高度
            screenHeight = height - statusBarHeight;// 屏幕高度
        }
        return screenHeight;
    }

    /**
     * 获取状态栏高度
     * 
     * @param activity
     * @return
     */
    public int getStatusBarHeight(Activity activity) {
        int result = 0;
        int resourceId = activity.getResources().getIdentifier(
                "status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = activity.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

三、总结

总体上实现这个控件还是比较简单的,主要是比较繁琐而已,其它的一些基础代码如布局文件,适配器等就不贴出来了。

源码

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值