Android打造个性十足的组件技术之复合组件

在Android中,我们可以通过继承View来打造完全如我们所愿的组件,但是,有的时候,我们需要的组件是一个由现有的几个组件的组合实现的,那么我们就可以利用组件合成技术,呵呵,这个名字我自己起的。

在Android中打造复合组件,其实只需要继承Layout或者其子类,比如LinearLayout等,然后在其中定义需要完成该功能的现有的几个组件。

然后定义一个监听器(就是一个简单的接口,暴露给用户使用,获取返回的数据,给用户使用)

本文通过使用两个Spinner来打造一个省份城市信息联动的选择控件,省份和城市信息的联动是开发中经常遇到的,这里我们看看使用组件合成技术如何简单巧妙的实现该功能。本例是雏形,强大的功能待大家完善。

闲话少说,直接上实例:

1、自定义一个CitySpinner,代码:

  1. package  org.widget.spinner;  
  2. import  java.util.ArrayList;  
  3. import  java.util.HashMap;  
  4. import  android.content.Context;  
  5. import  android.util.AttributeSet;  
  6. import  android.view.LayoutInflater;  
  7. import  android.view.View;  
  8. import  android.widget.AdapterView;  
  9. import  android.widget.ArrayAdapter;  
  10. import  android.widget.LinearLayout;  
  11. import  android.widget.Spinner;  
  12. /**  
  13.  * 自定义复合组件,实现省份城市联动Spinner组件  
  14.  * 定义复合组件通常继承自Layout,不必重写onDraw,onMesure等方法,除非有特殊的需求  
  15.  * @author Administrator  
  16.  *  
  17.  */   
  18. public   class  CitySpinner  extends  LinearLayout {  
  19.       
  20.     private  Context context;  
  21.       
  22.     private  Spinner mProvinceSpinner, mCitySpinner;  
  23.       
  24.     private  HashMap<String, ArrayList<String>> proCities;  //存放数据   
  25.       
  26.     private  ArrayList<String> provinces;  
  27.       
  28.     private  OnCitySelectListener cityListener;  
  29.       
  30.       
  31.     private  AdapterView.OnItemSelectedListener provinceSelectListener =  new  AdapterView.OnItemSelectedListener() {  
  32.         @Override   
  33.         public   void  onItemSelected(AdapterView<?> p, View v,  int  position,  
  34.                 long  id) {  
  35.             // 在选择了一个省份后,我们需要更新对应的城市列表   
  36.             String currProvince = (String)p.getItemAtPosition(position);  
  37.             switchCity(currProvince);  
  38.               
  39.         }  
  40.         @Override   
  41.         public   void  onNothingSelected(AdapterView<?> arg0) {  
  42.             // TODO Auto-generated method stub   
  43.               
  44.         }  
  45.     };  
  46.       
  47.     private  AdapterView.OnItemSelectedListener citySelectListener =  new  AdapterView.OnItemSelectedListener() {  
  48.         @Override   
  49.         public   void  onItemSelected(AdapterView<?> p, View v,  int  position,  
  50.                 long  id) {  
  51.               
  52.             if (cityListener !=  null ){  
  53.                 //这里获取当前选择的省份和城市   
  54.                 String province = (String)mProvinceSpinner.getSelectedItem();  
  55.                 String city = (String)p.getItemAtPosition(position);  
  56.                 cityListener.onCitySelected(province, city);  
  57.             }  
  58.               
  59.         }  
  60.         @Override   
  61.         public   void  onNothingSelected(AdapterView<?> arg0) {  
  62.             // TODO Auto-generated method stub   
  63.             //Do nothing;   
  64.         }  
  65.     };  
  66.       
  67.       
  68.     public  CitySpinner(Context context, HashMap<String, ArrayList<String>> data){  
  69.         super (context);  
  70.         this .context = context;   
  71.         if (data !=  null ){  
  72.             init(data);  
  73.         }  
  74.     }  
  75.       
  76.     public  CitySpinner(Context context, HashMap<String, ArrayList<String>> data, AttributeSet attrs){  
  77.         super (context, attrs);  
  78.         this .context = context;   
  79.         if (data !=  null ){  
  80.             init(data);  
  81.         }         
  82.     }     
  83.       
  84.     private   void  init(HashMap<String, ArrayList<String>> data){  
  85.         this .setOrientation(HORIZONTAL);  //水平布局   
  86.         this .setWeightSum( 0 .5f);  
  87.         //然后设置省份Spinner的数据   
  88.           
  89.         //首先,我们直接在代码中定义组件   
  90. //      mProvinceSpinner = new Spinner(context);   
  91. //      mCitySpinner = new Spinner(context);   
  92.         //我们看看从xml文件中获取   
  93.         View v = LayoutInflater.from(context).inflate(R.layout.city, null );  
  94.         mProvinceSpinner = (Spinner)v.findViewById(R.id.province);  
  95.         mCitySpinner = (Spinner)v.findViewById(R.id.city);  
  96.         //在将这两个组件添加到新的LinearLayout中时,需要首先将这两个组件从原来的Layout中删除   
  97.         LinearLayout temp = (LinearLayout)v.findViewById(R.id.layout_city);  
  98.         temp.removeAllViews();  
  99.         //添加监听   
  100.         mProvinceSpinner.setOnItemSelectedListener(provinceSelectListener);  
  101.         mCitySpinner.setOnItemSelectedListener(citySelectListener);  
  102.           
  103.         //如何对其进行定制布局格式呢??待解决   
  104.         this .proCities = data;  
  105.         initProvince();  
  106.           
  107.         this .addView(mProvinceSpinner,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);  
  108.         this .addView(mCitySpinner,LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);          
  109.     }  
  110.       
  111.     //初始化省份信息   
  112.     private   void  initProvince(){  
  113.         provinces = new  ArrayList<String>();  
  114.         Object[] temps = proCities.keySet().toArray();  
  115.         for ( int  i= 0 ; i<temps.length; i++){  
  116.             provinces.add((String)temps[i]);  
  117.         }  
  118.         ArrayAdapter<String> adapter = new  ArrayAdapter<String>(context, android.R.layout.simple_spinner_item,provinces);  
  119.         adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);  
  120.         mProvinceSpinner.setAdapter(adapter);         
  121.     }  
  122.       
  123.     //根据当前指定的省份更新对应的城市信息   
  124.     private   void  switchCity(String currProvince){  
  125.           
  126.         ArrayList<String> cities = proCities.get(currProvince);  
  127.           
  128.         ArrayAdapter<String> adapter = new  ArrayAdapter<String>(context, android.R.layout.simple_spinner_item,cities);  
  129.         adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);  
  130.         mCitySpinner.setAdapter(adapter);         
  131.     }  
  132.     public  Spinner getmProvinceSpinner() {  
  133.         return  mProvinceSpinner;  
  134.     }  
  135.     public   void  setmProvinceSpinner(Spinner mProvinceSpinner) {  
  136.         this .mProvinceSpinner = mProvinceSpinner;  
  137.     }  
  138.     public  Spinner getmCitySpinner() {  
  139.         return  mCitySpinner;  
  140.     }  
  141.     public   void  setmCitySpinner(Spinner mCitySpinner) {  
  142.         this .mCitySpinner = mCitySpinner;  
  143.     }  
  144.       
  145.     public   void  setOnCitySelectListener(OnCitySelectListener listener){  
  146.         this .cityListener = listener;  
  147.     }  
  148. }  

2、该代码中使用到了一个监听器OnCitySelectListener,其实就是一个简单的接口,在用户使用的时候,由用户来具体实现。

  1. /**  
  2.  * 选择事件监听器  
  3.  * @author Administrator  
  4.  *  
  5.  */   
  6. public   interface  OnCitySelectListener {  
  7.       
  8.     public   void  onCitySelected(String province, String city);  
  9. }  

3、测试代码,目前不能再配置文件中使用该控件,只能在代码中使用,如何使其能在配置文件中使用,也很简单。后期待完成。代码:

  1. package  demo.spinner;  
  2. import  java.util.ArrayList;  
  3. import  java.util.HashMap;  
  4. import  android.app.Activity;  
  5. import  android.os.Bundle;  
  6. import  android.widget.LinearLayout;  
  7. import  android.widget.Toast;  
  8. public   class  DemoActivity  extends  Activity {  
  9.     /** Called when the activity is first created. */   
  10.       
  11.     @Override   
  12.     public   void  onCreate(Bundle savedInstanceState) {  
  13.         super .onCreate(savedInstanceState);  
  14.         setContentView(R.layout.main);  
  15.         HashMap<String, ArrayList<String>> data = new  HashMap<String, ArrayList<String>>();  
  16.         for ( int  i= 0 ; i< 5 ; i++){  
  17.             ArrayList<String> cities = new  ArrayList<String>();  
  18.             for ( int  j= 0 ; j< 5 ; j++){  
  19.                 cities.add("cities" +i+j);  
  20.             }  
  21.             data.put("province" +i, cities);  
  22.         }  
  23.         final  CitySpinner spinner =  new  CitySpinner( this , data);  
  24.         LinearLayout layout = (LinearLayout)this .findViewById(R.id.layout_demo);  
  25.         layout.addView(spinner);          
  26.         //CitySpinner spinner = (CitySpinner)this.findViewById(R.id.city_spinner);//在布局文件中加入,目前不行,待完善   
  27.         spinner.setOnCitySelectListener(new  OnCitySelectListener() {  
  28.               
  29.             @Override   
  30.             public   void  onCitySelected(String province, String city) {  
  31.                 //    
  32.                 Toast.makeText(DemoActivity.this"当前省市:" +province+city, Toast.LENGTH_LONG).show();  
  33.             }  
  34.         });  
  35.           
  36.     }  
  37. }  

可以看到,组件合成技术,如此简单而已!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值