自定义View实现项目中的需求

来源:互联网 发布:反编译软件为dede 编辑:程序博客网 时间:2024/06/10 14:53

今天我要说的是,在项目中遇到这种情况,就是在个人中心,购买的商品有五种状态,这五个图标将要是下面这样的排列如图:
这里写图片描述
要求:
1.位置1和位置2分别位于父容器的left和right,这是必须满足的条件
2.这5个View必须是平分父容器的
首先我先到了GrideView,然后发现无论怎么调整item布局都无法达到上述要求,位置5无法满足
然后,我用的是LinearLayout,写五个,发先还是不行,两边的确定了,中间区域和两边的区域的距离无法做到一致,本来先想弄个线程的布局写写就可以了,可是,浪费了一些时间,算了,还是自己定义吧!。
1.继承ViewGroup
2.重写OnMeasure()方法

 @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    int modeW = MeasureSpec.getMode(widthMeasureSpec);    int modeH = MeasureSpec.getMode(heightMeasureSpec);    int width = MeasureSpec.getSize(widthMeasureSpec);    int height = MeasureSpec.getSize(heightMeasureSpec);    measureChildren(widthMeasureSpec,heightMeasureSpec);    if (mDirection==HORIZONTAL&&modeW==MeasureSpec.UNSPECIFIED){        //这里没有指定大小        throw new RuntimeException("if you sure this view's weight exactly");    }    if (mDirection==VERTICAL&&modeW==MeasureSpec.UNSPECIFIED){        //这里没有指定大小        throw new RuntimeException("if you sure this view's height exactly");    }    if (modeH!=MeasureSpec.EXACTLY) {        //要测量子View的高度        switch (mDirection) {            case HORIZONTAL:                int hH = getHorizontalHeight();                setMeasuredDimension(width, hH);                break;            case VERTICAL:                int hV = getVerticalWidth();                setMeasuredDimension(width, hV);                break;        }    }else {        setMeasuredDimension(width,height);    }}

/**
* 垂直方向时,测量View的高度
* @return
*/

private int getVerticalWidth() {    int w = 0;    int count = getChildCount();    for (int i = 0; i < count; i++) {        View child = getChildAt(i);        MarginLayoutParams lp;        //获取View的MarginLayoutParams实例        if (child.getLayoutParams() instanceof ViewGroup.MarginLayoutParams){            lp = (MarginLayoutParams) child.getLayoutParams();        }else {            lp = new MarginLayoutParams(child.getLayoutParams());        }        int childW = child.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;        Math.max(w,childW);    }    return w;}

/**
* 水平方向时,View的高度
* @return
*/

 private int getHorizontalHeight() {    int h = 0;    int count = getChildCount();    for (int i = 0; i < count; i++) {        View child = getChildAt(i);        MarginLayoutParams lp;        //获取View的MarginLayoutParams实例        if (child.getLayoutParams() instanceof ViewGroup.MarginLayoutParams){            lp = (MarginLayoutParams) child.getLayoutParams();        }else {            lp = new MarginLayoutParams(child.getLayoutParams());        }        int childH = child.getMeasuredHeight()+lp.topMargin+lp.bottomMargin;        h=Math.max(h,childH);    }    return h;}

3.实现onLayout()方法

 @Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {    int count = getChildCount();    int margin;    switch (mDirection) {        case HORIZONTAL:            margin = getHorizontalMargin(count);            //layout            layoutHorizontalChild(count,margin);            break;        case VERTICAL:            margin = getVerticalMargin(count);            layoutVerticalChild(count,margin);            break;    }} private void layoutHorizontalChild(int count,int margin) {    int wNum = getPaddingLeft();    for (int i = 0; i < count; i++) {        View child = getChildAt(i);        child.layout(wNum,getTopOrDownMargin(child),wNum+child.getMeasuredWidth(),getTopOrDownMargin(child)+child.getMeasuredHeight());        wNum += child.getMeasuredWidth()+margin;    }}private void layoutVerticalChild(int count,int margin) {    int hNum = getPaddingTop();    for (int i = 0; i < count; i++) {        View child = getChildAt(i);        child.layout(getLeftOrRightMargin(child),hNum,getLeftOrRightMargin(child)+child.getMeasuredWidth(),                hNum+child.getMeasuredHeight());        hNum += child.getMeasuredHeight()+margin;    }}public int getTopOrDownMargin(View child){    int h = child.getMeasuredHeight();    return (getMeasuredHeight()-h)/2;}public int getLeftOrRightMargin(View child){    int w = child.getMeasuredWidth();    return (getMeasuredWidth()-w)/2;}private int getHorizontalMargin(int count) {    int margin = getMeasuredWidth()-getPaddingLeft()-getPaddingRight();    for (int i = 0; i < count; i++) {        View child = getChildAt(i);        margin -= child.getMeasuredWidth();    }    //真正的margin    return margin/(count-1);}private int getVerticalMargin(int count) {    int margin = getMeasuredHeight()-getPaddingTop()-getPaddingBottom();    for (int i = 0; i < count; i++) {        View child = getChildAt(i);        margin -= child.getMeasuredHeight();    }    //真正的margin    return margin/(count-1);}

好了,现在我们已经正确测量和layout了child,现在我们要设计数据的载入

public class Adapter<T>{    private List<Map<T,Object>> mList;    private @LayoutRes int mLayout;    private String[] key;    private @IdRes int id[];    /**     * 类似SimpleAdapter     * @param mList 带有数据的集合     * @param mLayout 布局id     * @param key Map中的key的数组     * @param id 与key一一对应的View的id     */    public Adapter(List<Map<T, Object>> mList, int mLayout, String[] key, int[] id) {        this.mList = mList;        this.mLayout = mLayout;        this.key = key;        this.id = id;    }    private void addView(){        removeAllViews();        for (Map<T,Object> map:mList){            View view = LayoutInflater.from(getContext()).inflate(mLayout,null);            int size = id.length;            for (int i = 0; i <size ; i++) {                Object obj = map.get(key[i]);                if (obj instanceof String){                    TextView tv = (TextView) view.findViewById(id[i]);                    tv.setText((String) obj);                }                if (obj instanceof Integer){                    ImageView img = (ImageView) view.findViewById(id[i]);                    img.setImageResource((Integer) obj);                }            }            GongGeView.this.addView(view);            invalidate();            requestLayout();        }    }}

这是一个内部类,负责将View加进父容器。

点击时间的监听

  public  interface ItemClickListener{    void click(View v,int position);}

点击时间接口抛出,留给用户

public void setOnItemClickListener(final ItemClickListener mItemClickListener){    this.mItemClickListener = mItemClickListener;    int count = getChildCount();    for (int i = 0; i < count; i++) {        View v = getChildAt(i);        final int finalI = i;        v.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                if (mItemClickListener==null){                    return;                }                mItemClickListener.click(v, finalI);            }        });    }}

好了,这就完成了,效果如下如图:
这里写图片描述

1 0
原创粉丝点击