你的位置:首页 > 操作系统

[操作系统]Android PopupWindow使用之地区、学校选择二级联动

  最近在做一个社交类APP时,希望用户在注册时根据地区来选择自己所在的学校,由于用户手动输入学校,可能会出现各种问题,不利于后面对用户信息的统计。于是决定在客户端做好设置,用户只要根据地区来选择就好。第一想法就是使用PopupWindow,用弹框的方式让用户来选择。让实现的效果如下:

下面就来讲一下是如何实现的(数据是从网络获取的,JSON解析使用的是Gson,网络库用的是Volley)

工程结构:

1、创建一个布局文件:view_select_province_list.

<??><LinearLayout ="http://schemas.android.com/apk/res/android"       android:layout_width="match_parent"       android:layout_height="match_parent"       android:orientation="vertical"  >  <TextView    android:id="@+id/list_title"    android:layout_width="match_parent"    android:layout_height="50dp"    android:background="#3b3b3b"    android:gravity="center"    android:text="选择地区"    android:textColor="#ffffff"    android:textSize="16sp"/>  <ListView    android:id="@+id/province"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:layout_gravity="center"    android:background="#e4e4e4"    android:divider="#aeaeae"    android:dividerHeight="1dp"></ListView>  <ListView    android:id="@+id/school"    android:visibility="gone"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:layout_gravity="center"    android:background="#e4e4e4"    android:divider="#aeaeae"    android:dividerHeight="1dp"></ListView></LinearLayout>

2、初始化PopupWindow

private void initPopView() {    parent = this.getWindow().getDecorView();    View popView = View.inflate(this, R.layout.view_select_province_list, null);    mTitle = (TextView) popView.findViewById(R.id.list_title);    mProvinceListView = (ListView) popView.findViewById(R.id.province);    mSchoolListView = (ListView) popView.findViewById(R.id.school);    mProvinceListView.setOnItemClickListener(itemListener);    mSchoolListView.setOnItemClickListener(itemListener);    mProvinceAdapter = new ProvinceAdapter(this);    mProvinceListView.setAdapter(mProvinceAdapter);    mSchoolAdapter = new SchoolAdapter(this);    mSchoolListView.setAdapter(mSchoolAdapter);    int width = getResources().getDisplayMetrics().widthPixels * 3 / 4;    int height = getResources().getDisplayMetrics().heightPixels * 3 / 5;    mPopWindow = new PopupWindow(popView, width, height);    ColorDrawable dw = new ColorDrawable(0x30000000);    mPopWindow.setBackgroundDrawable(dw);    mPopWindow.setFocusable(true);    mPopWindow.setTouchable(true);    mPopWindow.setOutsideTouchable(true);//允许在外侧点击取消    loadProvince();    mPopWindow.setOnDismissListener(listener);  }

其中,要想使PopupWindow点击空白区域取消,必须设置

ColorDrawable dw = new ColorDrawable(0x30000000);

mPopWindow.setBackgroundDrawable(dw);

mPopWindow.setOutsideTouchable(true);

3、显示PopupWindow

private void showPopWindow() 
{ mPopWindow.showAtLocation(parent, Gravity.CENTER, 0, 0);}

4、下载地区和学校数据(这里用的是volley和gson解析数据)

private void loadProvince() {    mRequestQueue = Volley.newRequestQueue(this);    GsonRequest<Province> request = new GsonRequest<Province>(Request.Method.POST, Config.PROVINCE_URL,        Province.class, new Response.Listener<Province>() {      @Override      public void onResponse(Province response) {        if (response.getData() != null && response.getError_code() == 0) {          mProvinceAdapter.setList(response.getData());          mProvinceAdapter.notifyDataSetChanged();        }      }    }, new Response.ErrorListener() {      @Override      public void onErrorResponse(VolleyError volleyError) {      }    }, this);    mRequestQueue.add(request);  }  private void loadSchool() {    mRequestQueue = Volley.newRequestQueue(this);    GsonRequest<School> request = new GsonRequest<>(Request.Method.POST, Config.SCHOOL_URL + provinceId, School.class,        new Response.Listener<School>() {          @Override          public void onResponse(School response) {            if (response.getData() != null && response.getError_code() == 0){              mSchoolAdapter.setList(response.getData());              mSchoolAdapter.notifyDataSetChanged();            }          }        }, new Response.ErrorListener() {      @Override      public void onErrorResponse(VolleyError volleyError) {      }    }, this);    mRequestQueue.add(request);  }

5、设置ListView 的Item点击事件

/**   * ListView Item点击事件   */  AdapterView.OnItemClickListener itemListener = new AdapterView.OnItemClickListener() {    @Override    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {      if (parent == mProvinceListView) {        ProvinceList provinceName = (ProvinceList) mProvinceListView.getItemAtPosition(position);        provinceId = provinceName.getProvince_id();        mTitle.setText("选择学校");        mProvinceListView.setVisibility(View.GONE);//隐藏地区        mSchoolListView.setVisibility(View.VISIBLE);//显示学校        loadSchool();      } else if (parent == mSchoolListView) {        SchoolList schoolName = (SchoolList) mSchoolListView.getItemAtPosition(position);        mSelectSchool.setText(schoolName.getSchool_name());        mPopWindow.dismiss();      }    }  };

6、PopupWindow设置OnDismissListener,目的是为了再次进入选择的时候,直接进入学校而不是地区的选择

/**   * popWindow消失监听事件   */  PopupWindow.OnDismissListener listener = new PopupWindow.OnDismissListener() {    @Override    public void onDismiss() {      mTitle.setText("选择地区");      mProvinceListView.setVisibility(View.VISIBLE);//显示地区      mSchoolAdapter.setList(new ArrayList<SchoolList>());//设置一个空的List,避免再次选择学校后弹出的还是刚才的地区对应的学校      mSchoolAdapter.notifyDataSetChanged();      mSchoolListView.setVisibility(View.GONE);//隐藏学校    }  };

7、好了,这样一个基于PopupWindow的二级联动弹框选择就完成了,其中,还有ListView的Adapter在这里我就没有贴出来了,写法和我们平常用的适配器一样。我已经把代码开源到我的GitHub上了,有需要的可以下载看看。

GitHub地址:https://github.com/tonycheng93/PopWindow