android自定义布局——城市选择界面

以前做的项目需要用到这样的一个界面,先发一张效果图,个人感觉还算可以,下面把我的实现过程记录一下。


首先,数据格式是这样的


很明显这个界面整体是一个listview,每个省是一个listitem,刚开始实现方法是在adapter的getview里动态的在每个listitem里添加LinearLayout,每一行城市就是一个LinearLayout,通过判断当前的城市的索引决定是否要换行,即新建一个LinearLayout。后来觉得这样实现不太好看,代码太乱了,于是就想到了用自定义View,原理跟原来的差不多,也是利用当前城市的索引决定是否换行。

直接上源码,

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package cn.hnsi.android.apps.smartlife.ui.widget;  
  2.   
  3. import android.content.Context;  
  4. import android.util.AttributeSet;  
  5. import android.view.View;  
  6. import android.view.ViewGroup;  
  7.   
  8. /** 
  9.  * 显示城市名称 
  10.  * @author LiChaofei  
  11.  * <br/>2014-3-24 下午3:03:21 
  12.  */  
  13. public class CitiesLayout extends ViewGroup {  
  14. private static final String TAG="CitiesLayout";  
  15. private static final int COLUMN_COUNT=5;  
  16. private static final int HORIZONTAL_SPACE=2;  
  17. private static final int VERTICAL_SPACE=5;  
  18. private int maxChildWidth=0;  
  19. private int maxChildHeight=0;  
  20.   
  21.     public CitiesLayout(Context context) {  
  22.         super(context);  
  23.     }  
  24.       
  25.   
  26.     public CitiesLayout(Context context, AttributeSet attrs, int defStyle) {  
  27.         super(context, attrs, defStyle);  
  28.         // TODO Auto-generated constructor stub  
  29.     }  
  30.   
  31.   
  32.     public CitiesLayout(Context context, AttributeSet attrs) {  
  33.         super(context, attrs);  
  34.         // TODO Auto-generated constructor stub  
  35.     }  
  36.   
  37.   
  38.     @Override  
  39.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  40.         int widthSize=MeasureSpec.getSize(widthMeasureSpec);  
  41.         int heightSize=MeasureSpec.getSize(heightMeasureSpec);  
  42.         int paddingLeft=this.getPaddingLeft();  
  43.         int paddingRight=this.getPaddingTop();  
  44.         int paddingTop=this.getPaddingTop();  
  45.         int paddingBottom=this.getPaddingBottom();  
  46.           
  47. //      Log.d(TAG, "调用onMeasure,width="+widthSize+",height="+heightSize+",paddingLeft="+paddingLeft+",paddingRight="+paddingRight+",paddingTop="+paddingTop+",paddingBottom="+paddingBottom);  
  48.           
  49.           
  50.         //类似9宫格的形式  
  51.         maxChildHeight=maxChildWidth=(widthSize-paddingLeft-paddingRight)/COLUMN_COUNT-HORIZONTAL_SPACE*2;  
  52.           
  53.         int childMeasureWidthSpec=MeasureSpec.makeMeasureSpec(maxChildWidth, MeasureSpec.EXACTLY);  
  54.         int childMeasureHeightSpec=MeasureSpec.makeMeasureSpec(maxChildHeight, MeasureSpec.EXACTLY);  
  55.           
  56.         int childCount = getChildCount();  
  57.         for (int index = 0; index < childCount; index++) {  
  58.         final View child = getChildAt(index);  
  59.         // measure  
  60.         child.measure(childMeasureWidthSpec, childMeasureHeightSpec);  
  61.     }  
  62.           
  63.   
  64.         int rowCount=childCount%COLUMN_COUNT==0?childCount/COLUMN_COUNT:childCount/COLUMN_COUNT+1;  
  65.         heightSize=(maxChildHeight+VERTICAL_SPACE*2)*rowCount+paddingTop+paddingBottom;  
  66.         heightMeasureSpec=MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);  
  67.           
  68.         setMeasuredDimension(  
  69.                 resolveSize(widthSize, widthMeasureSpec),   
  70.                 resolveSize(heightSize, heightMeasureSpec));  
  71.     }  
  72.   
  73.   
  74.     @Override  
  75.     protected void onLayout(boolean changed, int l, int t, int r, int b) {  
  76. //      Log.d(TAG, "maxChildWidth="+maxChildWidth);  
  77.         int paddingLeft=this.getPaddingLeft();  
  78.         int paddingTop=this.getPaddingTop();  
  79.         int total=getChildCount();  
  80.         for(int i=0;i<total;i++){  
  81.             final View child=getChildAt(i);  
  82.             int row=i/COLUMN_COUNT;  
  83.             int colomn=i%COLUMN_COUNT;  
  84.               
  85.             int left =paddingLeft+(maxChildWidth+HORIZONTAL_SPACE*2)*colomn+HORIZONTAL_SPACE;  
  86.             int top = paddingTop+(maxChildHeight+VERTICAL_SPACE*2)*row+VERTICAL_SPACE;  
  87. //          Log.d(TAG, "left="+left+",top="+top);  
  88.             child.layout(left, top, left+maxChildWidth, top+maxChildHeight);  
  89.         }  
  90.     }  
  91.   
  92. }  

Adapter的源码

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. protected class CityAdapter extends BaseAdapter {  
  2.         Context mContext;  
  3.         LayoutInflater inflater;  
  4.         List<ProvinceEntity> dataList;  
  5. //      int unitWidth;  
  6.   
  7.         public CityAdapter(Context context, List<ProvinceEntity> datas) {  
  8.             mContext = context;  
  9.             inflater = (LayoutInflater) context  
  10.                     .getSystemService(LAYOUT_INFLATER_SERVICE);  
  11.             dataList = datas;  
  12. //          DisplayMetrics metrics = new DisplayMetrics();  
  13. //          getWindowManager().getDefaultDisplay().getMetrics(metrics);  
  14. //          unitWidth=(metrics.widthPixels-5*6)/5;  
  15.         }  
  16.   
  17.         @Override  
  18.         public int getCount() {  
  19.             return dataList != null ? dataList.size() : 0;  
  20.         }  
  21.   
  22.         @Override  
  23.         public Object getItem(int position) {  
  24.             return dataList.get(position);  
  25.         }  
  26.   
  27.         @Override  
  28.         public long getItemId(int position) {  
  29.             return position;  
  30.         }  
  31.   
  32.         @Override  
  33.         public View getView(int position, View convertView, ViewGroup parent) {  
  34.   
  35.             convertView = inflater.inflate(R.layout.list_item_city, parent,false);  
  36.   
  37.             TextView provinceName = (TextView) convertView  
  38.                     .findViewById(android.R.id.title);  
  39.             ProvinceEntity province = dataList.get(position);  
  40.             provinceName.setText(province.name);  
  41.   
  42.             List<CityEntity> cities = province.cities;  
  43.             CitiesLayout container=(CitiesLayout) convertView.findViewById(R.id.city_container);  
  44.             for (int i = 0, len = cities.size(); i < len; i++) {  
  45.                   
  46.                 CityEntity city=cities.get(i);  
  47.                 TextView cityName=createTextView(city);  
  48.                 container.addView(cityName);  
  49.             }  
  50.   
  51.             return convertView;  
  52.         }  
  53.   
  54.         /** 
  55.          * 创建一个TextView 
  56.          * @author LiChaofei 
  57.          * <br/>2013-12-10 下午2:48:59 
  58.          * @param city TODO 
  59.          * @return 
  60.          */  
  61.         private TextView createTextView(final CityEntity city) {  
  62.             final TextView view=new TextView(mContext);  
  63.             LayoutParams params=new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);  
  64. //          params.leftMargin=2;  
  65. //          params.rightMargin=2;  
  66.             view.setLayoutParams(params);  
  67. //          view.setPadding(10, 10, 10, 10);  
  68.             view.setTextColor(Color.BLACK);  
  69.             view.setBackgroundResource(R.drawable.bg_city_selector);  
  70.             view.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);  
  71.             view.setGravity(Gravity.CENTER);  
  72.             view.setText(city.name);  
  73.             view.setTag(city.cityId);  
  74.             view.setOnClickListener(new View.OnClickListener() {  
  75.                   
  76.                 @Override  
  77.                 public void onClick(View v) {  
  78.                     intent.putExtra(WeatherActivity.CITY_ID, city.cityId);  
  79.                     intent.putExtra(WeatherActivity.CITY_NAME, city.name);  
  80.                     setResult(RESULT_OK, intent);  
  81.                     finish();  
  82.                 }  
  83.             });  
  84.             return view;  
  85.         }  
  86.   
  87.     }  
用到的bg_city_selector

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">  
  3.   
  4.     <item android:state_pressed="true">  
  5.         <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >  
  6.   
  7.     <item>  
  8.         <shape android:shape="rectangle" >  
  9.             <solid android:color="@color/black" />  
  10.   
  11.             <corners android:radius="5dp" />  
  12.   
  13.             <stroke  
  14.                 android:width="1dip"  
  15.                 android:color="@color/black" />  
  16.         </shape>  
  17.     </item>  
  18.     <item  
  19.         android:bottom="2px"  
  20.         android:left="0px"  
  21.         android:right="0px">  
  22.         <shape android:shape="rectangle" >  
  23.             <gradient  
  24.                 android:angle="90"  
  25.                 android:endColor="#cccccc"  
  26.                 android:startColor="#e1e1e1" />  
  27.   
  28.             <corners android:radius="5dp" />  
  29.   
  30.             <stroke  
  31.                 android:width="0dip"  
  32.                 android:color="@color/black" />  
  33.         </shape>  
  34.     </item>  
  35.   
  36. </layer-list>  
  37.     </item>  
  38.     <!-- 普通状态 -->  
  39.     <item><layer-list xmlns:android="http://schemas.android.com/apk/res/android">  
  40.             <item><shape android:shape="rectangle">  
  41.                     <solid android:color="@color/black" />  
  42.   
  43.                     <corners android:radius="5dp" />  
  44.   
  45.                     <stroke android:width="1dip" android:color="@color/black" />  
  46.                 </shape></item>  
  47.             <item android:bottom="2px" android:left="0px" android:right="0px"><shape android:shape="rectangle">  
  48.                     <gradient android:angle="90" android:endColor="#e1e1e1" android:startColor="#cccccc" />  
  49.   
  50.                     <corners android:radius="5dp" />  
  51.   
  52.                     <stroke android:width="0dip" android:color="@color/black" />  
  53.                 </shape></item>  
  54.         </layer-list></item>  
  55.   
  56. </selector>  

代码比较简单,我就不多说了,如果有不对的地方,欢迎批评指正。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值