最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android自定義ViewGroup實(shí)現(xiàn)選擇面板

 更新時間:2022年07月22日 09:36:27   作者:豬飛啦~  
ViewGroup是上面提到的所有的父控件的父類;但ViewGroup是一個抽象類,它里面有一個抽象方法onLayout,這個方法的作用就是擺放它所有的子控件(安排位置),因為是抽象類,不能直接new對象,所以我們在布局文件中不能直接使用 ViewGroup

背景

在做社交類平臺開發(fā)的小伙伴都躲不開選擇社交個性標(biāo)簽的業(yè)務(wù)需求,那么實(shí)現(xiàn)這個UI效果我想大伙第一時間想到的必定是RecycleView或GridView,其實(shí)這兩者都可以實(shí)現(xiàn)需求,但我們的標(biāo)簽長度是不固定的,有可能是4個字符也有可能是10個字符,這時使用這兩者就很能實(shí)現(xiàn)根據(jù)每個標(biāo)簽的寬度來自適應(yīng)換行顯示,那么這時就離不開自定義ViewGroup

效果

至于我這里的效果為什么不根據(jù)字體的數(shù)量進(jìn)行自適應(yīng)寬度的問題,是因為我這邊的產(chǎn)品要求每行顯示四個且寬高一致,所以我在每個item外面加了一層RelativeLayout,需要自適應(yīng)寬度的朋友可以在創(chuàng)建item時不要在item外面多加一層

思路

1,我們先把每一行的標(biāo)簽看作一個對象

2,在onMeasure()方法中獲取ViewGroup寬度,減去padding值便是ViewGroup的可用寬度

3,獲取所有的子View進(jìn)行遍歷,創(chuàng)建一個對象來存儲每一行的標(biāo)簽view,每次添加一個標(biāo)簽view先判斷剩余空間能否存放得下這個標(biāo)簽view,如果不能則換行

4,在onLayout()方法中進(jìn)行布局,循環(huán)子view并調(diào)用其layout()方法進(jìn)行布局,每布局一個子view就計算出下一個子view的x坐標(biāo),y坐標(biāo)

完整代碼

/**
 * create by lijianhui
 * on 2022-7-6
 * <p>
 * description: 自定義標(biāo)簽選擇面板
 */
public class TagSelectView extends ViewGroup implements View.OnClickListener {
    private int mMaxWidth;
    private int mHorizontalSpace = DensityUtil.dp2px(5);
    private int mVerticalSpace = DensityUtil.dp2px(10);
    private List<RowTag> mRows = new ArrayList<>();
    private TagClickCallback mTagClickCallback;
    private int mTitleHeight;
    private boolean mUpdateTabState = true;
    public TagSelectView(@NonNull Context context) {
        super(context);
    }
    public TagSelectView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    public TagSelectView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    /**
     * 測量寬高
     */
    @SuppressLint("DrawAllocation")
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mRows.clear();
        // 獲取總寬度
        int width = MeasureSpec.getSize(widthMeasureSpec);
        mMaxWidth = width - getPaddingStart() - getPaddingEnd();
        //測量子view
        int childCount = this.getChildCount();
        RowTag currentLine = null;
        for (int i = mTitleHeight > 0 ? 1 : 0; i < childCount; i++) {
            View childView = getChildAt(i);
            childView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
            childView.setOnClickListener(this);
            if (currentLine == null) {
                currentLine = new RowTag(mMaxWidth, mHorizontalSpace);
                currentLine.addTagView(childView);
                mRows.add(currentLine);
            } else {
                if (currentLine.canAddView(childView)) {
                    currentLine.addTagView(childView);
                } else {
                    currentLine = new RowTag(mMaxWidth, mHorizontalSpace);
                    currentLine.addTagView(childView);
                    mRows.add(currentLine);
                }
            }
        }
        //測量自己
        int height = getPaddingTop() + getPaddingBottom();
        for (int i = 0; i < mRows.size(); i++) {
            height += mRows.get(i).mHeight;
        }
        height += (mRows.size() - 1) * mVerticalSpace;
        height += mTitleHeight;
        setMeasuredDimension(width, height);
    }
    /**
     * 布局子view
     */
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        left = getPaddingStart();
        top = getPaddingTop() + mTitleHeight;
        for (int i = 0; i < mRows.size(); i++) {
            // 獲取行
            RowTag line = mRows.get(i);
            // 管理
            line.layoutView(top, left);
            // 更新高度
            top += line.mHeight;
            if (i != mRows.size() - 1) {
                top += mVerticalSpace;
            }
        }
    }
    /**
     * 添加標(biāo)題
     *
     * @param view 標(biāo)題
     */
    public void addTitleView(View view) {
        view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
        mTitleHeight = view.getMeasuredHeight() + DensityUtil.dp2px(15);
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        addView(view);
    }
    /**
     * 標(biāo)簽被點(diǎn)擊
     *
     * @param v 點(diǎn)擊的標(biāo)簽
     */
    @Override
    public void onClick(View v) {
        if (mUpdateTabState) {
            v.setSelected(!v.isSelected());
        }
        if (mTagClickCallback != null) {
            mTagClickCallback.tagClick(v);
        }
    }
    /**
     * 設(shè)置標(biāo)簽點(diǎn)擊回調(diào)接口
     *
     * @param tagClickCallback 點(diǎn)擊回調(diào)接口
     */
    public void setTagClickCallback(TagClickCallback tagClickCallback) {
        mTagClickCallback = tagClickCallback;
    }
    /**
     * 設(shè)置點(diǎn)擊表情是否改變狀態(tài)
     *
     * @param updateTabState true:改變
     */
    public void setUpdateTabState(boolean updateTabState) {
        this.mUpdateTabState = updateTabState;
    }
    /**
     * 設(shè)置水平間距
     *
     * @param horizontalSpace 間距
     */
    public void setHorizontalSpace(int horizontalSpace) {
        this.mHorizontalSpace = horizontalSpace;
    }
    /**
     * 標(biāo)簽點(diǎn)擊回調(diào)接口
     */
    public interface TagClickCallback {
        void tagClick(View view);
    }
    /**
     * 每一行的數(shù)據(jù)
     */
    private static class RowTag {
        private final int mMaxWidth;
        private final int mHorizontalSpace;
        private final List<View> mTagViews;
        private int mUsedWidth;
        private int mHeight;
        public RowTag(int maxWidth, int horizontalSpace) {
            this.mMaxWidth = maxWidth;
            this.mHorizontalSpace = horizontalSpace;
            this.mTagViews = new ArrayList<>();
        }
        /**
         * 添加標(biāo)簽
         *
         * @param view 標(biāo)簽view
         */
        public void addTagView(View view) {
            int childWidth = view.getMeasuredWidth();
            int childHeight = view.getMeasuredHeight();
            if (mTagViews.size() == 0) {
                if (childWidth > mMaxWidth) {
                    mUsedWidth = mMaxWidth;
                } else {
                    mUsedWidth = childWidth + mHorizontalSpace;
                }
                mHeight = childHeight;
            } else {
                mUsedWidth += childWidth + mHorizontalSpace;
                mHeight = Math.max(childHeight, mHeight);
            }
            mTagViews.add(view);
        }
        /**
         * 判斷是否可添加
         *
         * @param view 要添加的標(biāo)簽view
         * @return 如果剩余寬度可以裝下要添加的標(biāo)簽view返回true
         */
        public boolean canAddView(View view) {
            if (mTagViews.size() == 0) {
                return true;
            }
            return view.getMeasuredWidth() <= (mMaxWidth - mUsedWidth - mHorizontalSpace);
        }
        /**
         * 布局標(biāo)簽
         *
         * @param t 頭坐標(biāo)
         * @param l 左坐標(biāo)
         */
        public void layoutView(int t, int l) {
            int avg = 0;
            if (mTagViews.size() > 1) {
                avg = (mMaxWidth - mUsedWidth) / (mTagViews.size() - 1);
            }
            for (View view : mTagViews) {
                // 獲取寬高 如需填充空余空間:measuredWidth = view.getMeasuredWidth() + avg
                int measuredWidth = view.getMeasuredWidth();
                int measuredHeight = view.getMeasuredHeight();
                // 重新測量
                view.measure(MeasureSpec.makeMeasureSpec(measuredWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY));
                // 重新獲取寬度值
                measuredWidth = view.getMeasuredWidth();
                int top = t;
                int left = l;
                int right = measuredWidth + left;
                int bottom = measuredHeight + top;
                // 指定位置
                view.layout(left, top, right, bottom);
                // 更新坐標(biāo)
                l += measuredWidth + mHorizontalSpace;
            }
        }
    }
}

使用

    /**
     * 構(gòu)建標(biāo)簽
     *
     * @param tagName 標(biāo)簽名稱
     */
    private void buildTagView(String tagName, boolean social) {
        RelativeLayout relativeLayout = new RelativeLayout(getContext());
        SuperTextView superTextView = new SuperTextView(getContext());
        superTextView.setGravity(Gravity.CENTER);
        superTextView.setText(tagName.length() > 5 ? tagName.substring(0, 5) : tagName);
        superTextView.setSolid(social ? Color.parseColor("#A68CFF") : Color.TRANSPARENT);
        if (!social) {
            superTextView.setStrokeColor(Color.parseColor("#EDEDED"));
            superTextView.setStrokeWidth(DensityUtil.dp2px(1));
        }
        superTextView.setTextColor(social ? Color.WHITE : Color.parseColor("#727272"));
        superTextView.setTextSize(11);
        superTextView.setCorner(DensityUtil.dp2px(14));
        superTextView.setOnClickListener(this);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(DensityUtil.dp2px(70), DensityUtil.dp2px(28));
        relativeLayout.addView(superTextView, params);
        mBinding.tagSelectView.addView(relativeLayout);
    }

到此這篇關(guān)于Android自定義ViewGroup實(shí)現(xiàn)選擇面板的文章就介紹到這了,更多相關(guān)Android ViewGroup內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

昭通市| 深水埗区| 广元市| 红安县| 平潭县| 万全县| 八宿县| 湄潭县| 金华市| 东城区| 马龙县| 东辽县| 镇雄县| 阳曲县| 新蔡县| 蒲城县| 三门县| 双流县| 中超| 福州市| 乐业县| 墨脱县| 调兵山市| 金湖县| 吴堡县| 东山县| 梁平县| 海原县| 额敏县| 永康市| 德惠市| 阿拉善盟| 方山县| 宁波市| 万宁市| 天水市| 卓资县| 瑞金市| 武陟县| 逊克县| 集安市|