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
0
二维码
打赏
海报
Android RadioGroup流式布局及动态添加RadioButton
RadioGroup流式布局
Android开发商城应用中会遇到商品属性标签的选择,可以使用自定义RadioGroup流式布局实现
public class FlowRadioGroup extends RadioGro……
文章目录
关闭
共有 0 条评论