您的位置:首页 > 移动开发 > Android开发

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

2011-04-23 12:01 351 查看
在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();
			}
		});
        
    }
}





可以看到,组件合成技术,如此简单而已!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: