最近使用APP的时候经常看到有
这种流式布局 ,今天我就跟大家一起来动手撸一个这种自定义控件.
首先说一下自定义控件的流程:
自定义控件一般要么继承View要么继承ViewGroup
View的自定义流程:
继承一个View-->重写onMeasure方法-->重写onDraw方法-->定义自定义属性-->处理手势操作
ViewGroup的自定义流程:
继承一个ViewGroup-->重写onMeasure方法-->重写onLayout-->重写onDraw方法->定义自定义属性-->处理手势操作
我们可以看到自定义View和自定义ViewGroup略微有些不同,自定义ViewGroup多了个onlayout方法,那么这些方法都有什么作用呢?这里由于篇幅的问题不做过多的描述,简单的说
onMeasure:用来计算,计算自身显示在页面上的大小
onLayout:用来计算子View摆放的位置,因为View已经是最小单元了,所以没有字View,所以没有onLayout方法
onDraw:用来绘制你想展示的东西
定义自定义属性就是暴露一些属性给外部调用
好了,了解了自定义View的基本自定义流程,我们可以知道我们应该需要自定义一个ViewGroup就可以满足该需求.
首先自定义一个View命名为FlowLayout继承ViewGroup
public class FlowLayout extends ViewGroup {
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);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).layout(l,t,r,b);
}
}
}
可以看到onLayout是必须重写的,不然系统不知道你这个ViewGroup的子View摆放的位置.
然后XML中引用
<test.hxy.com.testflowlayout.FlowLayout 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:id="@+id/mFlowLayout"
android:layout_margin="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Activity中设置数据
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FlowLayout mFlowLayout = (FlowLayout) findViewById(R.id.mFlowLayout);
List<String> list = new ArrayList<>();
list.add("java");
list.add("javaEE");
list.add("javaME");
list.add("c");
list.add("php");
list.add("ios");
list.add("c++");
list.add("c#");
list.add("Android");
for (int i = 0; i < list.size(); i++) {
View inflate = LayoutInflater.from(this).inflate(R.layout.item_personal_flow_labels, null);
TextView label = (TextView) inflate.findViewById(R.id.tv_label_name);
label.setText(list.get(i));
mFlowLayout.addView(inflate);
}
}
运行一下:
咦!!!这时候发现我们添加的