首页 > 代码库 > 自定义PopupWindow实现3急地区联动

自定义PopupWindow实现3急地区联动

做项目时有时我们会需要3级联动,比如注册,买东西下单等,这里我在android上使用popupwindow实现3级联动功能,我实现的思路是,当程序启动时就将后台的地区JSON数据格式全部加载上来,通过SharedPreferences将获取到的数据保存,点击按钮获取SharedPreferences中的地区数据,再通过JSONObject转为List集合,具体实现如下:

布局文件:

activity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" 
    android:orientation="vertical">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="获取地区数据" 
        android:onClick="obtainRegions"/>
    <TextView 
        android:id="@+id/tv_info"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="vertical"
        android:singleLine="false"/>
</LinearLayout>

regions_popup_window.xml——>这个布局文件是PopupWindow使用

<?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="match_parent"
    android:orientation="vertical" >
    <TextView 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="选中地区"
        android:background="#3399FF"
        android:paddingLeft="10dp"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        android:textSize="18dp"
        android:textColor="#FFFFFF"
        android:layout_margin="1dp"
        />
    <ListView
        android:id="@+id/lv_regions"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

group_item.xml——>ListView使用

<?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="match_parent"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/tv_region"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:paddingLeft="10dp"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        android:textSize="16dp"/>
</LinearLayout>

地区实体类——>根据后台返回JSON数据字段封装

package com.tenghu.model;

import java.io.Serializable;
import java.util.List;

public class Regions implements Serializable{
	private int region_id;
	private Integer p_region_id;
	private String region_path;
	private int region_grade;
	private String local_name;
	private List<Regions> children;
}
省略get与set方法

RegionsAdapter类

package com.tenghu.adapter;

import java.util.List;

import com.example.popupwindow.R;
import com.tenghu.model.Regions;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class RegionsAdapter extends BaseAdapter{
	private Context context;
	private List<Regions> list;
	
	public RegionsAdapter(Context context,List<Regions> list){
		this.context=context;
		this.list=list;
	}
	@Override
	public int getCount() {
		return list.size();
	}

	@Override
	public Object getItem(int position) {
		return list.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		if(null==convertView){
			convertView=LayoutInflater.from(context).inflate(R.layout.group_item, null);
		}
		TextView tv=(TextView) convertView.findViewById(R.id.tv_region);
		tv.setText(list.get(position).getLocal_name());
		return convertView;
	}
}

HttpUtil工具类

package com.tenghu.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;


public class HttpUtil {
	/**
	 * Get请求
	 * @param urls
	 * @return
	 */
	public static String getRequest(String urls){
		try {
			//创建HttpClient对象
			HttpClient client=new DefaultHttpClient();
			//创建Get请求
			HttpGet get=new HttpGet(urls);
			//获取请求响应
			HttpResponse response=client.execute(get);
			if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
				//获取InputStream对象
				InputStream is=response.getEntity().getContent();
				//创建BufferedReader
				BufferedReader br=new BufferedReader(new InputStreamReader(is));
				String line=null;
				StringBuffer sb=new StringBuffer();
				while((line=br.readLine())!=null){
					sb.append(line);
				}
				return sb.toString();
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return "";
	}
}

MainActivity类

package com.example.popupwindow;
import java.util.List;
import com.alibaba.fastjson.JSONObject;
import com.tenghu.adapter.RegionsAdapter;
import com.tenghu.model.Regions;
import com.tenghu.util.HttpUtil;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

public class MainActivity extends Activity {
	private PopupWindow pw=null;//自定义PopupWindow提示框
	private ListView regionsLv;//ListView空间
	private List<Regions> regionsList;//地区集合
	private String selectedArea="";//选中的地区
	private TextView tvInfo;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		tvInfo=(TextView) findViewById(R.id.tv_info);
		initRegionsData();
	}
	
	/**
	 * 初始化地区数据
	 */
	private void initRegionsData(){
		final ProgressDialog pd=new ProgressDialog(this);
		pd.setMessage("正在努力的加载");
		pd.show();
		
		//获取SharedPreferences
		SharedPreferences sharedPreferences=getSharedPreferences("regions", MODE_PRIVATE);
		//获取编辑器
		final Editor editor=sharedPreferences.edit();
		//开启一个线程下载地区数据
		new Thread(){
			public void run() {
				//获取请求数据
				String regionsJson=HttpUtil.getRequest("http://192.168.1.19/ZenyCS/regions!json.do");
				if(!"".equals(regionsJson.toString())||null!=regionsJson){
					//将获取的数据写入编辑器
					editor.putString("regionsJson", regionsJson);	
					//提交数据
					editor.commit();
				}
				pd.dismiss();//关闭加载提示框
			};
		}.start();
		
	}
	
	public void obtainRegions(View view){
		selectedArea="";//清空原来选中的地区
		if(null!=pw){
			pw.dismiss();
			pw=null;
		}else{
			//获取地区数据
			String regionsJson=getSharedPreferences("regions", MODE_PRIVATE).getString("regionsJson", "");
			Log.i("REGIONS", regionsJson);
			//获取自定义PopupWindow布局View
			final View v=LayoutInflater.from(MainActivity.this).inflate(R.layout.regions_popup_window, null);
			//获取WindowManager
			WindowManager wm=(WindowManager) getSystemService(Context.WINDOW_SERVICE);
			int windWidth=wm.getDefaultDisplay().getWidth();//获取屏幕宽度
			int windHeight=wm.getDefaultDisplay().getHeight();//获取屏幕高度
			pw=new PopupWindow(v, windWidth/2, windHeight/2);//设置PopupWindow的宽高
			pw.setFocusable(true);//使其聚集
			pw.setOutsideTouchable(true);//触摸控件以外的区域关闭控件
			//监听PopupWindow关闭,如果为关闭状态则设置为空
			pw.setOnDismissListener(new PopupWindow.OnDismissListener() {
				@Override
				public void onDismiss() {
					pw=null;
				}
			});
			//设置PopupWindow背景
			pw.setBackgroundDrawable(getResources().getDrawable(R.drawable.g_white_long_btn_normal));
			if("".equals(regionsJson.toString())||(null==regionsJson)){
				Toast.makeText(this, "地区数据未加载成功", Toast.LENGTH_SHORT).show();
			}else{
				pw.showAtLocation(view, Gravity.CENTER, 0, 0);//显示自定义PopupWindow
				//将JSON数据转为对象
				regionsList=JSONObject.parseArray(regionsJson, Regions.class);
				//获取ListView
				regionsLv=(ListView) v.findViewById(R.id.lv_regions);
				//设置Adapter
				regionsLv.setAdapter(new RegionsAdapter(this, regionsList));
				//绑定点击时间
				regionsLv.setOnItemClickListener(onItemClickListener);
			}
		}
	}
	
	/**
	 * 实现OnItemClickListener
	 */
	private OnItemClickListener onItemClickListener=new OnItemClickListener() {
		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position,
				long id) {
			selectedArea+=regionsList.get(position).getLocal_name()+"-";//获取选中的省市区
			regionsList=regionsList.get(position).getChildren();//获取子级地区
			//如果还有子级地区,则取出放入ListView,否则关闭PopupWIndow控件
			if(regionsList.size()>0){
				regionsLv.setAdapter(new RegionsAdapter(MainActivity.this, regionsList));
			}else{
				//判断拼接后的地区末尾是否以“-”结尾,如果是,将末尾的“-”截取掉
				selectedArea=selectedArea.endsWith("-")==true?selectedArea.substring(0, selectedArea.length()-1):selectedArea;
				tvInfo.setText(selectedArea);
				//关闭PopupWindow
				pw.dismiss();
			}
		}
	};
}

后台返回数据格式,部分:

[{"region_id":1,"p_region_id":0,"region_path":",1,","region_grade":1,"local_name":"北京市","children":[{"region_id":2,"p_region_id":1,"region_path":",1,2,","region_grade":2,"local_name":"北京市","children":[{"region_id":3,"p_region_id":2,"region_path":",1,2,3,","region_grade":3,"local_name":"东城区","children":[]},{"region_id":4,"p_region_id":2,"region_path":",1,2,4,","region_grade":3,"local_name":"西城区","children":[]},{"region_id":5,"p_region_id":2,"region_path":",1,2,5,","region_grade":3,"local_name":"崇文区","children":[]},{"region_id":6,"p_region_id":2,"region_path":",1,2,6,","region_grade":3,"local_name":"宣武区","children":[]},{"region_id":7,"p_region_id":2,"region_path":",1,2,7,","region_grade":3,"local_name":"朝阳区","children":[]},{"region_id":8,"p_region_id":2,"region_path":",1,2,8,","region_grade":3,"local_name":"丰台区","children":[]},{"region_id":9,"p_region_id":2,"region_path":",1,2,9,","region_grade":3,"local_name":"石景山区","children":[]},{"region_id":10,"p_region_id":2,"region_path":",1,2,10,","region_grade":3,"local_name":"海淀区","children":[]},{"region_id":11,"p_region_id":2,"region_path":",1,2,11,","region_grade":3,"local_name":"门头沟区","children":[]},{"region_id":12,"p_region_id":2,"region_path":",1,2,12,","region_grade":3,"local_name":"房山区","children":[]},{"region_id":13,"p_region_id":2,"region_path":",1,2,13,","region_grade":3,"local_name":"通州区","children":[]},{"region_id":14,"p_region_id":2,"region_path":",1,2,14,","region_grade":3,"local_name":"顺义区","children":[]},{"region_id":15,"p_region_id":2,"region_path":",1,2,15,","region_grade":3,"local_name":"昌平区","children":[]},{"region_id":16,"p_region_id":2,"region_path":",1,2,16,","region_grade":3,"local_name":"大兴区","children":[]},{"region_id":17,"p_region_id":2,"region_path":",1,2,17,","region_grade":3,"local_name":"怀柔区","children":[]},{"region_id":18,"p_region_id":2,"region_path":",1,2,18,","region_grade":3,"local_name":"平谷区","children":[]},{"region_id":19,"p_region_id":2,"region_path":",1,2,19,","region_grade":3,"local_name":"密云县","children":[]},{"region_id":20,"p_region_id":2,"region_path":",1,2,20,","region_grade":3,"local_name":"延庆县","children":[]}]}]},

整个android代码都在这里了