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

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

2016-08-08 23:04 579 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。

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



首先,数据格式是这样的



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

直接上源码,

[java] view
plain copy

 





package cn.hnsi.android.apps.smartlife.ui.widget;  

  

import android.content.Context;  

import android.util.AttributeSet;  

import android.view.View;  

import android.view.ViewGroup;  

  

/** 

 * 显示城市名称 

 * @author LiChaofei  

 * <br/>2014-3-24 下午3:03:21 

 */  

public class CitiesLayout extends ViewGroup {  

private static final String TAG="CitiesLayout";  

private static final int COLUMN_COUNT=5;  

private static final int HORIZONTAL_SPACE=2;  

private static final int VERTICAL_SPACE=5;  

private int maxChildWidth=0;  

private int maxChildHeight=0;  

  

    public CitiesLayout(Context context) {  

        super(context);  

    }  

      

  

    public CitiesLayout(Context context, AttributeSet attrs, int defStyle) {  

        super(context, attrs, defStyle);  

        // TODO Auto-generated constructor stub  

    }  

  

  

    public CitiesLayout(Context context, AttributeSet attrs) {  

        super(context, attrs);  

        // TODO Auto-generated constructor stub  

    }  

  

  

    @Override  

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  

        int widthSize=MeasureSpec.getSize(widthMeasureSpec);  

        int heightSize=MeasureSpec.getSize(heightMeasureSpec);  

        int paddingLeft=this.getPaddingLeft();  

        int paddingRight=this.getPaddingTop();  

        int paddingTop=this.getPaddingTop();  

        int paddingBottom=this.getPaddingBottom();  

          

//      Log.d(TAG, "调用onMeasure,width="+widthSize+",height="+heightSize+",paddingLeft="+paddingLeft+",paddingRight="+paddingRight+",paddingTop="+paddingTop+",paddingBottom="+paddingBottom);  

          

          

        //类似9宫格的形式  

        maxChildHeight=maxChildWidth=(widthSize-paddingLeft-paddingRight)/COLUMN_COUNT-HORIZONTAL_SPACE*2;  

          

        int childMeasureWidthSpec=MeasureSpec.makeMeasureSpec(maxChildWidth, MeasureSpec.EXACTLY);  

        int childMeasureHeightSpec=MeasureSpec.makeMeasureSpec(maxChildHeight, MeasureSpec.EXACTLY);  

          

        int childCount = getChildCount();  

        for (int index = 0; index < childCount; index++) {  

        final View child = getChildAt(index);  

        // measure  

        child.measure(childMeasureWidthSpec, childMeasureHeightSpec);  

    }  

          

  

        int rowCount=childCount%COLUMN_COUNT==0?childCount/COLUMN_COUNT:childCount/COLUMN_COUNT+1;  

        heightSize=(maxChildHeight+VERTICAL_SPACE*2)*rowCount+paddingTop+paddingBottom;  

        heightMeasureSpec=MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);  

          

        setMeasuredDimension(  

                resolveSize(widthSize, widthMeasureSpec),   

                resolveSize(heightSize, heightMeasureSpec));  

    }  

  

  

    @Override  

    protected void onLayout(boolean changed, int l, int t, int r, int b) {  

//      Log.d(TAG, "maxChildWidth="+maxChildWidth);  

        int paddingLeft=this.getPaddingLeft();  

        int paddingTop=this.getPaddingTop();  

        int total=getChildCount();  

        for(int i=0;i<total;i++){  

            final View child=getChildAt(i);  

            int row=i/COLUMN_COUNT;  

            int colomn=i%COLUMN_COUNT;  

              

            int left =paddingLeft+(maxChildWidth+HORIZONTAL_SPACE*2)*colomn+HORIZONTAL_SPACE;  

            int top = paddingTop+(maxChildHeight+VERTICAL_SPACE*2)*row+VERTICAL_SPACE;  

//          Log.d(TAG, "left="+left+",top="+top);  

            child.layout(left, top, left+maxChildWidth, top+maxChildHeight);  

        }  

    }  

  

}  

Adapter的源码

[java] view
plain copy

 





protected class CityAdapter extends BaseAdapter {  

        Context mContext;  

        LayoutInflater inflater;  

        List<ProvinceEntity> dataList;  

//      int unitWidth;  

  

        public CityAdapter(Context context, List<ProvinceEntity> datas) {  

            mContext = context;  

            inflater = (LayoutInflater) context  

                    .getSystemService(LAYOUT_INFLATER_SERVICE);  

            dataList = datas;  

//          DisplayMetrics metrics = new DisplayMetrics();  

//          getWindowManager().getDefaultDisplay().getMetrics(metrics);  

//          unitWidth=(metrics.widthPixels-5*6)/5;  

        }  

  

        @Override  

        public int getCount() {  

            return dataList != null ? dataList.size() : 0;  

        }  

  

        @Override  

        public Object getItem(int position) {  

            return dataList.get(position);  

        }  

  

        @Override  

        public long getItemId(int position) {  

            return position;  

        }  

  

        @Override  

        public View getView(int position, View convertView, ViewGroup parent) {  

  

            convertView = inflater.inflate(R.layout.list_item_city, parent,false);  

  

            TextView provinceName = (TextView) convertView  

                    .findViewById(android.R.id.title);  

            ProvinceEntity province = dataList.get(position);  

            provinceName.setText(province.name);  

  

            List<CityEntity> cities = province.cities;  

            CitiesLayout container=(CitiesLayout) convertView.findViewById(R.id.city_container);  

            for (int i = 0, len = cities.size(); i < len; i++) {  

                  

                CityEntity city=cities.get(i);  

                TextView cityName=createTextView(city);  

                container.addView(cityName);  

            }  

  

            return convertView;  

        }  

  

        /** 

         * 创建一个TextView 

         * @author LiChaofei 

         * <br/>2013-12-10 下午2:48:59 

         * @param city TODO 

         * @return 

         */  

        private TextView createTextView(final CityEntity city) {  

            final TextView view=new TextView(mContext);  

            LayoutParams params=new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);  

//          params.leftMargin=2;  

//          params.rightMargin=2;  

            view.setLayoutParams(params);  

//          view.setPadding(10, 10, 10, 10);  

            view.setTextColor(Color.BLACK);  

            view.setBackgroundResource(R.drawable.bg_city_selector);  

            view.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);  

            view.setGravity(Gravity.CENTER);  

            view.setText(city.name);  

            view.setTag(city.cityId);  

            view.setOnClickListener(new View.OnClickListener() {  

                  

                @Override  

                public void onClick(View v) {  

                    intent.putExtra(WeatherActivity.CITY_ID, city.cityId);  

                    intent.putExtra(WeatherActivity.CITY_NAME, city.name);  

                    setResult(RESULT_OK, intent);  

                    finish();  

                }  

            });  

            return view;  

        }  

  

    }  

用到的bg_city_selector

[html] view
plain copy

 





<?xml version="1.0" encoding="utf-8"?>  

<selector xmlns:android="http://schemas.android.com/apk/res/android">  

  

    <item android:state_pressed="true">  

        <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >  

  

    <item>  

        <shape android:shape="rectangle" >  

            <solid android:color="@color/black" />  

  

            <corners android:radius="5dp" />  

  

            <stroke  

                android:width="1dip"  

                android:color="@color/black" />  

        </shape>  

    </item>  

    <item  

        android:bottom="2px"  

        android:left="0px"  

        android:right="0px">  

        <shape android:shape="rectangle" >  

            <gradient  

                android:angle="90"  

                android:endColor="#cccccc"  

                android:startColor="#e1e1e1" />  

  

            <corners android:radius="5dp" />  

  

            <stroke  

                android:width="0dip"  

                android:color="@color/black" />  

        </shape>  

    </item>  

  

</layer-list>  

    </item>  

    <!-- 普通状态 -->  

    <item><layer-list xmlns:android="http://schemas.android.com/apk/res/android">  

            <item><shape android:shape="rectangle">  

                    <solid android:color="@color/black" />  

  

                    <corners android:radius="5dp" />  

  

                    <stroke android:width="1dip" android:color="@color/black" />  

                </shape></item>  

            <item android:bottom="2px" android:left="0px" android:right="0px"><shape android:shape="rectangle">  

                    <gradient android:angle="90" android:endColor="#e1e1e1" android:startColor="#cccccc" />  

  

                    <corners android:radius="5dp" />  

  

                    <stroke android:width="0dip" android:color="@color/black" />  

                </shape></item>  

        </layer-list></item>  

  

</selector>  

代码比较简单,我就不多说了,如果有不对的地方,欢迎批评指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息