仿京东淘宝动态添加单选按钮并自动换行

xiaoxiao2021-02-28  25

效果图:

网上找了一些资料,然后经过修改终于达到想要的效果。废话不多说,直接上代码。

import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity implements OnSelectedListener { private ShoppingSelectView view; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { view = (ShoppingSelectView) findViewById(R.id.v); //设置监听需要在设置数据源之前 view.setOnSelectedListener(this); //最终数据 view.setData(getListSize()); } public List<String> getListSize() { List<String> list = new ArrayList<String>(); list.add("白色(三件装)"); list.add("古铜色(12件装)"); list.add("黑色"); list.add("咖啡色(6件装)"); list.add("橘红色(3232件装)"); list.add("玫瑰红(32件装)"); list.add("黄色(23424件装)"); return list; } @Override public void onSelected(String smallTitle) { Toast.makeText(this, smallTitle, Toast.LENGTH_SHORT).show(); } }

布局

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <com.test.dmptest.dynamicloadbutton.ShoppingSelectView android:id="@+id/v" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>

工具类

import android.content.Context; import android.util.AttributeSet; import android.view.Gravity; import android.widget.LinearLayout; import android.widget.RadioButton; import java.util.List; public class ShoppingSelectView extends LinearLayout { /** * 数据源 */ private List<String> list; /** * 上下文 */ private Context context; /** * 整个商品属性的左右间距 */ private int flowLayoutMargin = 16; /** * 属性按钮的高度 */ private int buttonHeight = 25; /** * 属性按钮之间的左边距 */ private int buttonLeftMargin = 10; /** * 属性按钮之间的上边距 */ private int buttonTopMargin = 8; /** * 文字与按钮的边距 */ private int textPadding = 10; /** * 选择后的回调监听 */ private OnSelectedListener listener; public ShoppingSelectView(Context context) { super(context); initView(context); } public ShoppingSelectView(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } private void initView(Context context) { setOrientation(LinearLayout.VERTICAL); this.context = context; } public void getView() { if (list.size() < 0) { return; } FlowLayout layout = new FlowLayout(context); layout.setPadding(dip2px(context, flowLayoutMargin), 0, dip2px(context, flowLayoutMargin), 0); //设置选择监听 if (listener != null) { layout.setListener(listener); } for (int i = 0; i < list.size(); i++) { //属性按钮 RadioButton button = new RadioButton(context); //默认选中第一个 /*if (i == 0) { button.setChecked(true); }*/ //设置按钮的参数 LayoutParams buttonParams = new LayoutParams(LayoutParams.WRAP_CONTENT, dip2px(context, buttonHeight)); //设置文字的边距 int padding = dip2px(context, textPadding); button.setPadding(padding, 0, padding, 0); //设置margin属性,需传入LayoutParams否则会丢失原有的布局参数 MarginLayoutParams marginParams = new MarginLayoutParams(buttonParams); marginParams.leftMargin = dip2px(context, buttonLeftMargin); marginParams.topMargin = dip2px(context, buttonTopMargin); button.setLayoutParams(marginParams); button.setGravity(Gravity.CENTER); button.setBackgroundResource(R.drawable.tv_sel); button.setButtonDrawable(android.R.color.transparent); button.setText(list.get(i));//设置规格内容 layout.addView(button); } addView(layout); } /** * 根据手机的分辨率从 dip 的单位 转成为 px(像素) */ private int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } public void setData(List<String> data) { list = data; getView(); } public void setOnSelectedListener(OnSelectedListener listener) { this.listener = listener; } }

自定义一个接口

/** * 选择成功回调 */ public interface OnSelectedListener { void onSelected(String smallTitle); }

设置换行的代码

import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.CompoundButton; import android.widget.RadioButton; import java.util.ArrayList; import java.util.List; public class FlowLayout extends ViewGroup implements CompoundButton.OnCheckedChangeListener { /** * 属性的标题 */ private OnSelectedListener listener; int postion; public FlowLayout(Context context) { super(context); } public FlowLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); int modeWidth = MeasureSpec.getMode(widthMeasureSpec); int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); int modeHeight = MeasureSpec.getMode(heightMeasureSpec); // 如果是warp_content情况下,记录宽和高 int width = 0; int height = 0; // 记录每一行的宽度与高度 int lineWidth = 0; int lineHeight = 0; // 得到内部元素的个数 int cCount = getChildCount(); for (int i = 0; i < cCount; i++) { // 通过索引拿到每一个子view View child = getChildAt(i); // 测量子View的宽和高,系统提供的measureChild measureChild(child, widthMeasureSpec, heightMeasureSpec); // 得到LayoutParams MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); // 子View占据的宽度 int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; // 子View占据的高度 int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; // 换行 判断 当前的宽度大于 开辟新行 if (lineWidth + childWidth > sizeWidth - getPaddingLeft() - getPaddingRight()) { // 对比得到最大的宽度 width = Math.max(width, lineWidth); // 重置lineWidth lineWidth = childWidth; // 记录行高 height += lineHeight; lineHeight = childHeight; } else { // 未换行 // 叠加行宽 lineWidth += childWidth; // 得到当前行最大的高度 lineHeight = Math.max(lineHeight, childHeight); } // 特殊情况,最后一个控件 if (i == cCount - 1) { width = Math.max(lineWidth, width); height += lineHeight; } } setMeasuredDimension( modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width + getPaddingLeft() + getPaddingRight(), modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height + getPaddingTop() + getPaddingBottom()// ); } /** * 存储所有的View */ private List<List<View>> mAllViews = new ArrayList<>(); /** * 每一行的高度 */ private List<Integer> mLineHeight = new ArrayList<>(); @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { mAllViews.clear(); mLineHeight.clear(); // 当前ViewGroup的宽度 int width = getWidth(); int lineWidth = 0; int lineHeight = 0; // 存放每一行的子view List<View> lineViews = new ArrayList<>(); int cCount = getChildCount(); 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 + lineWidth + lp.leftMargin + lp.rightMargin > width - getPaddingLeft() - getPaddingRight()) { // 记录LineHeight mLineHeight.add(lineHeight); // 记录当前行的Views mAllViews.add(lineViews); // 重置我们的行宽和行高 lineWidth = 0; lineHeight = childHeight + lp.topMargin + lp.bottomMargin; // 重置我们的View集合 lineViews = new ArrayList<>(); } lineWidth += childWidth + lp.leftMargin + lp.rightMargin; lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin); lineViews.add(child); }// for end // 处理最后一行 mLineHeight.add(lineHeight); mAllViews.add(lineViews); // 设置子View的位置 int left = getPaddingLeft(); int top = getPaddingTop(); // 行数 int lineNum = mAllViews.size(); for (int i = 0; i < lineNum; i++) { // 当前行的所有的View lineViews = mAllViews.get(i); lineHeight = mLineHeight.get(i); for (int j = 0; j < lineViews.size(); j++) { View child = lineViews.get(j); postion = j; // 判断child的状态 if (child.getVisibility() == View.GONE) { continue; } MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); int lc = left + lp.leftMargin; int tc = top + lp.topMargin; int rc = lc + child.getMeasuredWidth(); int bc = tc + child.getMeasuredHeight(); // 为子View进行布局 child.layout(lc, tc, rc, bc); left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; } left = getPaddingLeft(); top += lineHeight; } } /** * 与当前ViewGroup对应的LayoutParams */ @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } @Override public void addView(View child) { ((RadioButton) child).setOnCheckedChangeListener(this); super.addView(child); } //监听按钮的选择状态 @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { for (int i = 0; i < getChildCount(); i++) { RadioButton button = (RadioButton) getChildAt(i); button.setChecked(false); } if (isChecked) { buttonView.setChecked(true); if (listener != null) { listener.onSelected(buttonView.getText().toString()); } } } public void setListener(OnSelectedListener listener) { this.listener = listener; } }

下载demo

转载请注明原文地址: https://www.6miu.com/read-2626898.html

最新回复(0)