做项目时有时我们会需要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代码都在这里了