自定义组件共分为:自定义组合控件,自定义View,自定义ViewGroup
自定义ViewGroup一共七步:
1.继承ViewGroup,将统一调用第三的构造方法。重写onMeasure(),onLayout()方法,创建数据集合对象,创建孩子行列集合对象。编写常量横向外边距,纵向外边距,组件属性
2.创建孩子,设置孩子,添加孩子
3.测量孩子,测量自己,行列分布
4.布局孩子,外边距使用
5.编写逻辑
6.暴露接口
7.暴露属性
方法:
removeAllViews():删除ViewGroup所有孩子
addView(View view):添加孩子
getChild(int index):获取指定位置的孩子
measureChild(View child, int widthMeasureSpace, int heightMeasureSpace):测量孩子
MeasureSpec.getSize(int width):获取size
MeasureSpec.makeMeasureSpec(int width, MeasureSpec.AT_MOST):创建MeasureSpec
view.getMeasureWidth():测量后可调用,获取组件宽度
具体代码:
1. 工具代码SizeUtil.java,App.java
public class SizeUtils { public static int dip2px(float dpValue){ float scale = LitePalApplication.getContext().getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } }
public class App extends Application { private static Context mContext = null; @Override public void onCreate() { super.onCreate(); mContext = getApplicationContext(); } public static Context getAppContext() { return mContext; } }
2.FlowLayout.xml
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="汉堡包" android:paddingLeft="20dp" android:paddingRight="20dp" android:paddingTop="10dp" android:paddingBottom="10dp" android:textColor="@color/text_grey" android:background="@drawable/selector_flow_test"> </TextView>
3.FlowLayout.java
public class FlowLayout extends ViewGroup { private List<List<View>> allLineList = new ArrayList<>(); private List<String> dataList = new ArrayList<>(); private static final int DEFAULT_HORIZON_MARGIN = SizeUtil.dip2px(5); private static final int DEFAULT_VERTICAL_MARGIN = SizeUtil.dip2px(5); private static final int DEFAULT_CHILD_MAX_LINE = 3; private static final float DEFAULT_CHILD_TEXT_SIZE = 8; private float childTextSize; private int childMaxLine; public FlowLayout(Context context) { this(context, null); } public FlowLayout(Context context, AttributeSet attrs) { this(context, attrs,0); } public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout); childTextSize = typedArray.getDimension(R.styleable.FlowLayout_childTextSize, DEFAULT_CHILD_TEXT_SIZE); childMaxLine = typedArray.getInt(R.styleable.FlowLayout_childMaxLine, DEFAULT_CHILD_MAX_LINE); typedArray.recycle(); } // 2. 创建孩子,设置孩子,添加孩子 public void setDataList(List<String> dataList ){ removeAllViews(); this.dataList.clear(); this.dataList.addAll(dataList); for (String data : this.dataList) { TextView child = (TextView)LayoutInflater.from(getContext()).inflate(R.layout.item_flow_text, this, false); child.setText(data); child.setTextSize(childTextSize); addView(child); } } // 3.测量孩子,测量自己,行列分布 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int parentWidthSize = MeasureSpec.getSize(widthMeasureSpec); int parentHeightSize = MeasureSpec.getSize(heightMeasureSpec); int childWidthSize = MeasureSpec.makeMeasureSpec(parentWidthSize, MeasureSpec.AT_MOST); int childHeightSize = MeasureSpec.makeMeasureSpec(parentHeightSize,MeasureSpec.AT_MOST); if( getChildCount() == 0 ){ return; } allLineList.clear(); List<View> lineList = new ArrayList<>(); allLineList.add(lineList); for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); final int j = i; child.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (onItemClickListener != null) { onItemClickListener.onItemClick(child,dataList.get(j),j); } } }); measureChild(child,childWidthSize,childHeightSize); if( lineList.size() == 0 ){ lineList.add(child); }else { if( allLineList.size() == childMaxLine){ break; } int totalLineWidth = 0; for (View view : lineList) { totalLineWidth += view.getMeasuredWidth() + DEFAULT_HORIZON_MARGIN; } if( totalLineWidth + child.getMeasuredWidth() + DEFAULT_HORIZON_MARGIN <= parentWidthSize){ lineList.add(child); }else { lineList = new ArrayList<>(); lineList.add(child); allLineList.add(lineList); } } } int targetHeightSize = (getChildAt(0).getMeasuredHeight() + DEFAULT_HORIZON_MARGIN) * allLineList.size(); setMeasuredDimension(parentWidthSize,targetHeightSize); } // 4.布局孩子,外边距通过layout画出 @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if( getChildCount() == 0 ){ return; } int currentLeft = DEFAULT_HORIZON_MARGIN; int currentTop = 0; int currentRight = 0; int currentBottom = getChildAt(0).getMeasuredHeight(); for (List<View> lineList : allLineList) { for (View child : lineList) { currentRight = currentLeft + child.getMeasuredWidth(); child.layout(currentLeft,currentTop,currentRight,currentBottom); currentLeft = currentRight + DEFAULT_HORIZON_MARGIN; } currentLeft = 0; currentRight = 0; currentTop = currentBottom + DEFAULT_VERTICAL_MARGIN; currentBottom = currentTop + getChildAt(0).getMeasuredHeight(); } } public interface OnItemClickListener { public void onItemClick(View view ,String data,int position); } private OnItemClickListener onItemClickListener; public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } }
4.FlowLayoutActivity.java,FlowLayout.xml
public class FlowLayoutActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_flow_layout); List<String> data = new ArrayList<>(); data.add("键盘"); data.add("显示器"); data.add("鼠标"); data.add("ipad"); data.add("air pod"); data.add("Android手机"); data.add("mac pro"); data.add("大疆mini3 pro"); data.add("ChatGPT"); data.add("耳机"); data.add("Noval AI"); data.add("键盘"); data.add("显示器"); data.add("鼠标"); data.add("键盘"); data.add("显示器"); data.add("鼠标"); data.add("ipad"); data.add("air pod"); data.add("Android手机"); data.add("mac pro"); data.add("大疆mini3 pro"); data.add("ChatGPT"); data.add("耳机"); data.add("Noval AI"); data.add("键盘"); data.add("显示器"); data.add("鼠标"); FlowLayout flowLayout = this.findViewById(R.id.flow_layout); flowLayout.setTextList(data); flowLayout.setOnItemClickListener(new FlowLayout.OnItemClickListener() { @Override public void onItemClickListener(View v, String text) { Toast.makeText(FlowLayoutActivity.this,"text "+text,Toast.LENGTH_SHORT).show(); } }); } private static final String TAG = "FlowLayoutActivity"; }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".flow.FlowLayoutActivity"> <com.example.myandroiddemo.flow.FlowLayout android:id="@+id/flow_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" /> </LinearLayout>
标签:自定义,int,FlowLayout,add,child,组件,Android,data,public From: https://www.cnblogs.com/remix777/p/17832703.html