Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 自定義標簽布局(流布局)

自定義標簽布局(流布局)

編輯:關於Android編程

[TOC]
剛好項目中要實現這個布局效果,做完後在這裡分享出來給大家學習~

效果圖:

pic01pic02pic03這裡寫圖片描述

實現的功能:

1、單行多行切換顯示
2、單選和取消選擇

源碼

/**
 * 
 * @author jhone
 * @time  2016/08/08
 *
 */
public class LabelView extends ViewGroup{  

        private Context context;
        //當前是否是打開狀態
        private boolean isOpen=false;
        //用來疊加每一行的view
        private List> mAllChildViews = new ArrayList>();  
        //用來疊加每一行的高度
        private List mLineHeight = new ArrayList();  

        public LabelView(Context context) {  
            this(context, null);  
            // TODO Auto-generated constructor stub  
        }  
        public LabelView(Context context, AttributeSet attrs) {  
            this(context, attrs, 0);  
            // TODO Auto-generated constructor stub  
        }  
        public LabelView(Context context, AttributeSet attrs, int defStyle) {  
            super(context, attrs, defStyle);  
            this.context=context;
        }  
        @Override  
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
            // TODO Auto-generated method stub  
            int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);  
            int modeWidth = MeasureSpec.getMode(widthMeasureSpec);  
            int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);  
            int modeHeight = MeasureSpec.getMode(heightMeasureSpec);  

            //記錄每行的最大寬度和高度  
            int width = 0;
            int height = 0;
            //記錄每行的寬度和高度  
            int lineWidth = 0;  
            int lineHeight = 0;  

            int childCount = getChildCount();  
            for(int i = 0;i < childCount; i ++){  
                View child = getChildAt(i);  
                measureChild(child, widthMeasureSpec, heightMeasureSpec);  
                MarginLayoutParams lp = (MarginLayoutParams)child.getLayoutParams();  
                int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;  
                int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;

                if (isOpen) {
                     //當疊加的子view寬度大於行寬時進行換行
                    if(lineWidth + childWidth > sizeWidth){  
                        //對比得到最大的寬度,最終最大的寬度可能用來設置為控件的寬度  
                        width = Math.max(width, lineWidth);  
                        //重置lineWidth  
                        lineWidth = childWidth;  
                        //記錄行高  
                        lineHeight = childHeight;  
                        height += lineHeight;  
                    }else{//不換行情況  
                        //疊加行寬  
                        lineWidth += childWidth;  
                        //得到最大行高  
                        lineHeight = Math.max(lineHeight, childHeight);  
                    }  
                    //處理最後一行,因為上面的邏輯沒有算上最後一行的,這裡通過最後一個子view來做一次判斷,執行最後一行的高度與寬度疊加與對比
                    if(i == childCount -1){  
                        width = Math.max(width, lineWidth);  
                        height += lineHeight;  
                    }
                }else{//只顯示第一行
                    if(lineWidth + childWidth > sizeWidth){  
                        width = Math.max(width, lineWidth);  
                        height = lineHeight;  
                        break;
                    }else{
                        lineWidth += childWidth;  
                        lineHeight = Math.max(lineHeight, childHeight);  
                    }  
                }
            }  
            setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width,  
                    modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height);  
        }  

        @Override  
        protected void onLayout(boolean changed, int l, int t, int r, int b) {  
            // TODO Auto-generated method stub  
            mAllChildViews.clear();  
            mLineHeight.clear();  
            //獲取當前ViewGroup的寬度  
            int width = getWidth();  

            int lineWidth = 0;  
            int lineHeight = 0;  
            //記錄當前行的view  
            List lineViews = new ArrayList();  
            int childCount = getChildCount();  
            for(int i = 0;i < childCount; i ++){  
                View child = getChildAt(i);   
                MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();  
                int childWidth = child.getMeasuredWidth();  
                int childHeight = child.getMeasuredHeight();  

                //如果需要換行  
                if(childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width){  
                    //記錄LineHeight  
                    mLineHeight.add(lineHeight);  
                    //記錄當前行的Views  
                    mAllChildViews.add(lineViews);  
                    //重置行的寬高  
                    lineWidth = 0;  
                    lineHeight = childHeight + lp.topMargin + lp.bottomMargin;  
                    lineViews = new ArrayList();  
                }  
                lineWidth += childWidth + lp.leftMargin + lp.rightMargin;  
                lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin);  
                lineViews.add(child);  
            }  
            //處理最後一行  
            mLineHeight.add(lineHeight);  
            mAllChildViews.add(lineViews);  

            //設置子View的位置  
            int left = 0;  
            int top = 0;  
            //獲取行數  
            int lineCount = mAllChildViews.size();  
            for(int i = 0; i < lineCount; i ++){  
                //當前行的views和高度  
                lineViews = mAllChildViews.get(i);  
                lineHeight = mLineHeight.get(i);  
                for(int j = 0; j < lineViews.size(); j ++){  
                    View child = lineViews.get(j);  
                    //判斷是否顯示  
                    if(child.getVisibility() == View.GONE){  
                        continue;  
                    }  
                    MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();  
                    int cLeft = left + lp.leftMargin;  
                    int cTop = top + lp.topMargin;  
                    int cRight = cLeft + child.getMeasuredWidth();  
                    int cBottom = cTop + child.getMeasuredHeight();  
                    //進行子View布局  
                    child.layout(cLeft, cTop, cRight, cBottom);  
                    left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;  
                }  
                left = 0;  
                top += lineHeight;  

                if (!isOpen) {//如果只顯示一行,就跳出
                    break;
                }
            }  

        }  
        @Override  
        public LayoutParams generateLayoutParams(AttributeSet attrs) {  
            // TODO Auto-generated method stub  
            return new MarginLayoutParams(getContext(), attrs);  
        }  

        //記錄點過的位置
        private TextView mask;

        public void addLabels(ArrayList labels){
            MarginLayoutParams lp = new MarginLayoutParams(  
                    LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); 
            int paddingTop = (int) ScreenUtils.dpToPxInt(context, 6);
            int paddingLeft = (int) ScreenUtils.dpToPxInt(context, 10);
            lp.leftMargin = (int) ScreenUtils.dpToPxInt(context, 4);  
            lp.rightMargin = (int) ScreenUtils.dpToPxInt(context, 4);  
            lp.topMargin = (int) ScreenUtils.dpToPxInt(context, 5);  
            lp.bottomMargin = (int) ScreenUtils.dpToPxInt(context, 5);  
            for (String label:labels) {
                TextView view = new TextView(context);  
                view.setPadding(paddingLeft, paddingTop, paddingLeft, paddingTop);
                view.setText(label);  
                view.setTextSize(12);
                view.setTextColor(Color.parseColor("#797671"));  
                view.setBackgroundResource(R.drawable.bg_round_black_stroken);
                view.setLayoutParams(lp);
                view.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        // TODO Auto-generated method stub
                        if (view==mask) {//如果當前是選中狀態,再次點擊取消選中狀態,並且回調參數返回null
                            ((TextView)view).setTextColor(Color.parseColor("#797671"));  
                            ((TextView)view).setBackgroundResource(R.drawable.bg_round_black_stroken);
                            mask=null;
                            if (l!=null) {
                                l.onLabelChange(null);
                            }
                        }else{//點擊取消上一個選中view,也就是說只能單選,多選邏輯也簡單,在這裡記錄後回調,這裡我就不實現 了
                            if (mask!=null) {
                                mask.setTextColor(Color.parseColor("#797671"));  
                                mask.setBackgroundResource(R.drawable.bg_round_black_stroken);
                            }

                            ((TextView)view).setTextColor(Color.parseColor("#06BE6A"));
                            ((TextView)view).setBackgroundResource(R.drawable.bg_round_green_stroken);

                            mask=(TextView) view;
                            if (l!=null) {
                                l.onLabelChange((TextView)view);
                            }
                        }

                    }
                });
                addView(view,lp);  
            }
        }

        private OnLabelChangeListener l;
        public void setOnLabelChangeListener(OnLabelChangeListener l){
            this.l=l;
        }

        public interface OnLabelChangeListener{
            void onLabelChange(TextView textView);
        }
        /**
         * 切換操作
         */
        public void toggle() {
            if (!isOpen) {
                isOpen = true;
                requestLayout();
            } else {
                isOpen = false;
                requestLayout();
            }
        }
}

實現這個還是比較簡單的,注釋也算詳細吧,就不多講了~

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved