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

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

 

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

 

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

 

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

 

闲话少说,直接上实例:

 

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

 

package org.widget.spinner; import java.util.ArrayList; import java.util.HashMap; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.LinearLayout; import android.widget.Spinner; /** * 自定义复合组件,实现省份城市联动Spinner组件 * 定义复合组件通常继承自Layout,不必重写onDraw,onMesure等方法,除非有特殊的需求 * @author Administrator * */ public class CitySpinner extends LinearLayout { private Context context; private Spinner mProvinceSpinner, mCitySpinner; private HashMap<String, ArrayList<String>> proCities; //存放数据 private ArrayList<String> provinces; private OnCitySelectListener cityListener; private AdapterView.OnItemSelectedListener provinceSelectListener = new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> p, View v, int position, long id) { // 在选择了一个省份后,我们需要更新对应的城市列表 String currProvince = (String)p.getItemAtPosition(position); switchCity(currProvince); } @Override public void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub } }; private AdapterView.OnItemSelectedListener citySelectListener = new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> p, View v, int position, long id) { if(cityListener != null){ //这里获取当前选择的省份和城市 String province = (String)mProvinceSpinner.getSelectedItem(); String city = (String)p.getItemAtPosition(position); cityListener.onCitySelected(province, city); } } @Override public void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub //Do nothing; } }; public CitySpinner(Context context, HashMap<String, ArrayList<String>> data){ super(context); this.context = context; if(data != null){ init(data); } } public CitySpinner(Context context, HashMap<String, ArrayList<String>> data, AttributeSet attrs){ super(context, attrs); this.context = context; if(data != null){ init(data); } } private void init(HashMap<String, ArrayList<String>> data){ this.setOrientation(HORIZONTAL); //水平布局 this.setWeightSum(0.5f); //然后设置省份Spinner的数据 //首先,我们直接在代码中定义组件 // mProvinceSpinner = new Spinner(context); // mCitySpinner = new Spinner(context); //我们看看从xml文件中获取 View v = LayoutInflater.from(context).inflate(R.layout.city, null); mProvinceSpinner = (Spinner)v.findViewById(R.id.province); mCitySpinner = (Spinner)v.findViewById(R.id.city); //在将这两个组件添加到新的LinearLayout中时,需要首先将这两个组件从原来的Layout中删除 LinearLayout temp = (LinearLayout)v.findViewById(R.id.layout_city); temp.removeAllViews(); //添加监听 mProvinceSpinner.setOnItemSelectedListener(provinceSelectListener); mCitySpinner.setOnItemSelectedListener(citySelectListener); //如何对其进行定制布局格式呢??待解决 this.proCities = data; initProvince(); this.addView(mProvinceSpinner,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); this.addView(mCitySpinner,LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); } //初始化省份信息 private void initProvince(){ provinces = new ArrayList<String>(); Object[] temps = proCities.keySet().toArray(); for(int i=0; i<temps.length; i++){ provinces.add((String)temps[i]); } ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item,provinces); adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line); mProvinceSpinner.setAdapter(adapter); } //根据当前指定的省份更新对应的城市信息 private void switchCity(String currProvince){ ArrayList<String> cities = proCities.get(currProvince); ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item,cities); adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line); mCitySpinner.setAdapter(adapter); } public Spinner getmProvinceSpinner() { return mProvinceSpinner; } public void setmProvinceSpinner(Spinner mProvinceSpinner) { this.mProvinceSpinner = mProvinceSpinner; } public Spinner getmCitySpinner() { return mCitySpinner; } public void setmCitySpinner(Spinner mCitySpinner) { this.mCitySpinner = mCitySpinner; } public void setOnCitySelectListener(OnCitySelectListener listener){ this.cityListener = listener; } }

 

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

 

/** * 选择事件监听器 * @author Administrator * */ public interface OnCitySelectListener { public void onCitySelected(String province, String city); }

 

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

 

package demo.spinner; import java.util.ArrayList; import java.util.HashMap; import android.app.Activity; import android.os.Bundle; import android.widget.LinearLayout; import android.widget.Toast; public class DemoActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); HashMap<String, ArrayList<String>> data = new HashMap<String, ArrayList<String>>(); for(int i=0; i<5; i++){ ArrayList<String> cities = new ArrayList<String>(); for(int j=0; j<5; j++){ cities.add("cities"+i+j); } data.put("province"+i, cities); } final CitySpinner spinner = new CitySpinner(this, data); LinearLayout layout = (LinearLayout)this.findViewById(R.id.layout_demo); layout.addView(spinner); //CitySpinner spinner = (CitySpinner)this.findViewById(R.id.city_spinner);//在布局文件中加入,目前不行,待完善 spinner.setOnCitySelectListener(new OnCitySelectListener() { @Override public void onCitySelected(String province, String city) { // Toast.makeText(DemoActivity.this, "当前省市:"+province+city, Toast.LENGTH_LONG).show(); } }); } }

 

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

你可能感兴趣的:(android,String,layout,null,dropdown,interface)