自定義viewGroup位置擺放onLayout以及設置margin梳理

自定義viewGroup必須要實現的一個方法,實現所有子控件布局的函數,自頂向下通過計算好的尺寸放置每一個子View

首先有關getWidth()和getMeasuredWidth()的區別為:onlayout()方法內會用到

  • getMeasuredWidth()是在measure過程后就可以獲取到的,getWidth()是在layout()過程結束后才能獲得到的
  • getMeasuredWidth()中的值是子view在側來最后使用setMeasuredDimension(width, height)來設置的,getWidth()的值是在onlayout()方法之后父view動態設置的
  • setMeasuredDimension(width, height)只是先確定了給父view的一個建議寬高,子view最終的寬高還是通過childAt.layout(0,top,measuredWidth,measuredHeight+top)來設置的
  • getMeasureWidth()只有在measure()過程中才可以獲得,getWidth()只有在layout()之后才可以獲得

如下所示:

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

        int lineWidth = 0;
        int lineHeight = 0;
        int top = 0;
        int left = 0;

        int count = getChildCount();

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

            View childAt = getChildAt(i);

            MarginLayoutParams layoutParams = (MarginLayoutParams) childAt.getLayoutParams();

            //得到子view的測量建議高度
            int measuredHeight = childAt.getMeasuredHeight() + layoutParams.bottomMargin + layoutParams.topMargin;
            int measuredWidth = childAt.getMeasuredWidth() + layoutParams.leftMargin + layoutParams.rightMargin;

            //換行
            if (measuredWidth + lineWidth > getMeasuredWidth()) {

                top += lineHeight;
                left = 0;
                lineHeight = measuredHeight;
                lineWidth = measuredWidth;
            } else {

                lineHeight = Math.max(measuredHeight, lineHeight);
                lineWidth += measuredWidth;
            }

            //的到字view的當前位置
            int ll = left + layoutParams.leftMargin;
            int tt = top + layoutParams.topMargin;
            int rr = ll + childAt.getMeasuredWidth();
            int bb = tt + childAt.getMeasuredHeight();

            //設置子view的確定位置
            childAt.layout(ll, tt, rr, bb);

            left += measuredWidth;
        }

設置margin時需要重載的方法有:

 @Override
    protected LayoutParams generateLayoutParams(LayoutParams p) {
        return new MarginLayoutParams(p);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(),attrs);
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new MarginLayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
    }

設置子view的點擊事件

    /**
     * 設置點擊事件
     *
     * @param listener
     */
    public void setOnItemClickListener(final OnItemClickListener listener) {
        for (int i = 0; i < getChildCount(); i++) {
            final int index = i;
            View childAt = getChildAt(i);
            childAt.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    listener.onItemClick(index);
                }
            });
        }
    }
    
    public interface OnItemClickListener {
        void onItemClick(int position);
    }
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容