简单记录一下自定义ViewGroup中的margin问题,此demo自定义了MyViewGroup达到部分LinearLayout中的horizontal中的情况。
目前只适用于wrap_content的情况
public class MyViewGroup extends ViewGroup {
private static final String TAG = "MyViewGroup";
public MyViewGroup(Context context) {
this(context, null);
}
public MyViewGroup(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MyViewGroupLayoutParams(getContext(), attrs);
}
@Override
protected LayoutParams generateLayoutParams(LayoutParams p) {
return new MyViewGroupLayoutParams(p);
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new MyViewGroupLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int totalWidth = 0;
int totalHeight = 0;
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
//测量子view尺寸
measureChild(childView, widthMeasureSpec, heightMeasureSpec);
// measureChildren(widthMeasureSpec, heightMeasureSpec);
totalWidth = childView.getMeasuredWidth() + totalWidth;
ViewGroup.MarginLayoutParams layoutParams = (MarginLayoutParams) childView.getLayoutParams();
totalWidth = totalWidth + layoutParams.leftMargin + layoutParams.rightMargin;
totalHeight = Math.max(childView.getMeasuredHeight(), totalHeight);
}
setMeasuredDimension(totalWidth, totalHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childCount = getChildCount();
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
int measuredWidth = childView.getMeasuredWidth();
int measuredHeight = childView.getMeasuredHeight();
Log.d(TAG, "measuredWidth: " + measuredWidth + ",measuredHeight:" + measuredHeight);
ViewGroup.MarginLayoutParams layoutParams = (MarginLayoutParams) childView.getLayoutParams();
Log.d(TAG, "layoutParams.leftMargin: " + layoutParams.getMarginStart() + ",layoutParams.rightMargin:" + layoutParams.getMarginEnd());
if (i >= 1) {
ViewGroup.MarginLayoutParams layoutParams1 = (MarginLayoutParams) getChildAt(i - 1).getLayoutParams();
left += getChildAt(i - 1).getMeasuredWidth() + layoutParams1.getMarginEnd() + layoutParams.getMarginStart();
} else {
left += layoutParams.getMarginStart();
}
right = left + measuredWidth;
bottom = top + measuredHeight;
childView.layout(left, top, right, bottom);
}
}
/**
* 为每一个子view添加MarginLayoutParams
*/
public class MyViewGroupLayoutParams extends MarginLayoutParams {
public MyViewGroupLayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
}
public MyViewGroupLayoutParams(int width, int height) {
super(width, height);
}
public MyViewGroupLayoutParams(MarginLayoutParams source) {
super(source);
}
public MyViewGroupLayoutParams(LayoutParams source) {
super(source);
}
}
}
布局样式,参考LinearLayoutCompat
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat 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=".MainActivity">
<com.example.demotest.MyViewGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_marginStart="10dp"
android:layout_marginEnd="20dp"
android:background="@color/teal_700"
android:layout_width="100dp"
android:layout_height="100dp"/>
<ImageView
android:background="@color/purple_200"
android:layout_width="50dp"
android:layout_marginEnd="20dp"
android:layout_height="50dp"/>
<ImageView
android:background="@color/black"
android:layout_width="150dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_height="150dp"/>
</com.example.demotest.MyViewGroup>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_marginStart="10dp"
android:layout_marginEnd="20dp"
android:background="@color/teal_700"
android:layout_width="100dp"
android:layout_height="100dp"/>
<ImageView
android:background="@color/purple_200"
android:layout_width="50dp"
android:layout_marginEnd="20dp"
android:layout_height="50dp"/>
<ImageView
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:background="@color/black"
android:layout_width="150dp"
android:layout_height="150dp"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
参考下面的截图,基本上达到了LinearLayout的效果
后续要添加match_parent,padding,vertial的等效果...