Android RadioGroup流式布局及动态添加RadioButton

RadioGroup流式布局

Android开发商城应用中会遇到商品属性标签的选择,可以使用自定义RadioGroup流式布局实现

public class FlowRadioGroup extends RadioGroup {

    private static final String TAG = FlowRadioGroup.class.getSimpleName();

    public FlowRadioGroup(Context context) {
        super(context);
    }

    public FlowRadioGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected LinearLayout.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
        return new LinearLayout.LayoutParams(lp);
    }

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

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

    /**
     * 负责设置子控件的测量模式和大小 根据所有子控件设置自己的宽和高
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 获得它的父容器为它设置的测量模式和大小
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);

        Log.e(TAG, sizeWidth + ", " + sizeHeight);

        // 如果是warp_content情况下,记录宽和高
        int width = 0;
        int height = 0;
        /**
         * 记录每一行的宽度,width不断取最大宽度
         */
        int lineWidth = 0;
        /**
         * 每一行的高度,累加至height
         */
        int lineHeight = 0;

        int cCount = getChildCount();
        NLog.i("yezhou", "onMeasure child count: " + cCount);

        // 遍历每个子元素
        for (int i = 0; i < cCount; i++) {
            View child = getChildAt(i);
            // 测量每一个child的宽和高
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            // 得到child的lp
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            // 当前子空间实际占据的宽度
            int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            // 当前子空间实际占据的高度
            int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;

            if (mFlowMode) {
                /**
                 * 如果加入当前child,则超出最大宽度,则的到目前最大宽度给width,类加height 然后开启新行
                 */
                if (lineWidth + childWidth > sizeWidth) {
                    width = Math.max(lineWidth, childWidth);// 取最大的
                    lineWidth = childWidth; // 重新开启新行,开始记录
                    // 叠加当前高度,
                    height += lineHeight;
                    // 开启记录下一行的高度
                    lineHeight = childHeight;
                } else
                // 否则累加值lineWidth,lineHeight取最大高度
                {
                    lineWidth += childWidth;
                    lineHeight = Math.max(lineHeight, childHeight);
                }
                // 如果是最后一个,则将当前记录的最大宽度和当前lineWidth做比较
                if (i == cCount - 1) {
                    width = Math.max(width, lineWidth);
                    height += lineHeight;
                }

            } else {
                /**
                 * 如果加入当前child,则超出最大高度,则的到目前最大高度给height,累加width 然后开启新列
                 */
                if (lineHeight + childHeight > sizeHeight) {
                    height = Math.max(lineHeight, childHeight);// 取最大的
                    lineHeight = childHeight; // 重新开启新行,开始记录
                    // 叠加当前高度,
                    width += lineWidth;
                    // 开启记录下一行的高度
                    lineWidth = childWidth;
                } else
                // 否则累加值lineHeight,lineWidth取最大高度
                {
                    lineHeight += childHeight;
                    lineWidth = Math.max(lineWidth, childWidth);
                }
                // 如果是最后一个,则将当前记录的最大高度和当前lineHeight做比较
                if (i == cCount - 1) {
                    height = Math.max(height, lineHeight);
                    width += lineWidth;
                }
            }

        }
        setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY) ? sizeWidth : width, (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight : height);
    }

    /**
     * 存储所有的View,按行记录
     */
    private List<List<View>> mAllViews = new ArrayList<List<View>>();
    /**
     * 记录每一行的最大高度
     */
    private List<Integer> mLineHeight = new ArrayList<Integer>();
    /**
     * 记录每一列的最大宽度
     */
    private List<Integer> mLineWidth = new ArrayList<Integer>();

    private void setFlowMode(boolean flowMode) {
        mFlowMode = flowMode;
    }

    boolean mFlowMode = true;

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        mAllViews.clear();
        if (mFlowMode) {
            mLineHeight.clear();
        } else {
            mLineWidth.clear();
        }

        int width = getWidth();
        int height = getHeight();

        int lineWidth = 0;
        int lineHeight = 0;
        // 存储每一行所有的childView
        List<View> lineViews = new ArrayList<View>();
        int cCount = getChildCount();
        NLog.i("yezhou", "onMeasure child count: " + cCount);

        // 遍历所有的孩子
        for (int i = 0; i < cCount; i++) {
            View child = getChildAt(i);
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            // 如果已经需要换行
            if (childWidth + lp.leftMargin + lp.rightMargin + lineWidth > width) {
                // 记录这一行所有的View以及最大高度
                mLineHeight.add(lineHeight);
                // 将当前行的childView保存,然后开启新的ArrayList保存下一行的childView
                mAllViews.add(lineViews);
                lineWidth = 0;// 重置行宽
                lineViews = new ArrayList<View>();
            }

            /**
             * 如果不需要换行,则累加
             */
            lineWidth += childWidth + lp.leftMargin + lp.rightMargin;
            lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin);
            lineViews.add(child);
        }

        // 记录最后一行
        mLineHeight.add(lineHeight);
        mAllViews.add(lineViews);
        int left = 0;
        int top = 0;
        // 得到总行数
        int lineNums = mAllViews.size();
        for (int i = 0; i < lineNums; i++) {
            // 每一行的所有的views
            lineViews = mAllViews.get(i);
            // 当前行的最大高度
            lineHeight = mLineHeight.get(i);
            // 遍历当前行所有的View
            for (int j = 0; j < lineViews.size(); j++) {
                View child = lineViews.get(j);
                if (child.getVisibility() == View.GONE) {
                    continue;
                }
                MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();

                // 计算childView的left,top,right,bottom
                int lc = left + lp.leftMargin;
                int tc = top + lp.topMargin;
                int rc = lc + child.getMeasuredWidth();
                int bc = tc + child.getMeasuredHeight();
                child.layout(lc, tc, rc, bc);

                left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            }
            left = 0;
            top += lineHeight;
        }
    }

    @Override
    public void addView(View child) {
        super.addView(child);
        requestLayout();
        invalidate();
    }

    @Override
    public void addView(View child, int index) {
        super.addView(child, index);
        requestLayout();
        invalidate();
    }
}

动态添加RadioButton

public void onBindViewHolder(final ViewHolder holder, final int position) {
    final GoodsOption goodsOption = mGoodsOptionList.get(position);
    holder.tvOptionName.setText(goodsOption.getOptName());
    List<GoodsOption.OptionValue> optionValueList = goodsOption.getOptionValueList();
    if (optionValueList != null && optionValueList.size() > 0) {
        final int defaultFontColor = mContext.getResources().getColor(R.color.textPrimaryMedium);
        for (GoodsOption.OptionValue optionValue : optionValueList) {
            RadioButton radioButton = new RadioButton(mContext);
            radioButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
            RadioGroup.LayoutParams layoutParams = new RadioGroup.LayoutParams(ViewGroup.MarginLayoutParams.WRAP_CONTENT, ViewGroup.MarginLayoutParams.WRAP_CONTENT);
            layoutParams.setMargins(0, 0, DisplayUtil.dp2px(5), 0);
            radioButton.setLayoutParams(layoutParams);
            radioButton.setText(optionValue.getOptValueName());
            radioButton.setBackgroundResource(R.drawable.selector_text_rect);
            radioButton.setButtonDrawable(null);
            radioButton.setTextColor(defaultFontColor);
            radioButton.setPadding(DisplayUtil.dp2px(8), DisplayUtil.dp2px(3), DisplayUtil.dp2px(8), DisplayUtil.dp2px(3));
            holder.flowRadioGroupAttr.addView(radioButton);
        }
        holder.flowRadioGroupAttr.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int position) {
                int childCount = radioGroup.getChildCount();
                RadioButton radioButton;
                for (int i = 0; i < childCount; i++) {
                    radioButton = (RadioButton) radioGroup.getChildAt(i);
                    if (radioButton.isChecked()) {
                        radioButton.setTextColor(Color.WHITE);
                    } else {
                        radioButton.setTextColor(defaultFontColor);
                    }
                }
            }
        });
        ((RadioButton) holder.flowRadioGroupAttr.getChildAt(0)).setChecked(true);
    }
}

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/11/android-radiogroup-streaming-layout-and-dynamically-adding-radiobuttons/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
Android RadioGroup流式布局及动态添加RadioButton
RadioGroup流式布局 Android开发商城应用中会遇到商品属性标签的选择,可以使用自定义RadioGroup流式布局实现 public class FlowRadioGroup extends RadioGro……
<<上一篇
下一篇>>
文章目录
关闭
目 录