The first reason I think of this control is because of an interview. I was asked how to implement the inclined layout. My first reaction is to add LayoutParams directly and control it as you want. But, the interviewer wants me to do it more thoroughly. After adding it directly to the layout, it will be inclined. I didn't say so at that time. Today I was free and wrote one directly.
/*************************************************divider*************************************************************/
My idea is relatively simple, rewriting the layout of the child control.
The code is as follows:
/** * Created by cheng on 2017/9/7. */ public class LeansLayout extends FrameLayout { /** * Default is width / length */ private float mRadioWH = 0; private float DEFAULT_RADIOWH = 0; private String TAG = "LeansLayout"; public LeansLayout(Context context) { super(context); init(context, null); } public LeansLayout(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context, attrs); } public LeansLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) { TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.LeansLayout); mRadioWH = typedArray.getFloat(R.styleable.LeansLayout_roateWH, mRadioWH); typedArray.recycle(); } /** * At the same time of obtaining width height ratio */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (DEFAULT_RADIOWH > 0) { } else { DEFAULT_RADIOWH = w * 1.0f / h; } if (mRadioWH > 0) { } else { mRadioWH = DEFAULT_RADIOWH; } Log.i(TAG, "roateWH=" + mRadioWH); } /** * Measure subview */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); measureChild(childView, widthMeasureSpec, heightMeasureSpec); } } /*** * The layout of manual Gang subclasses is inclined */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); int totalheight = 0; for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); int width = childView.getMeasuredWidth(); int height = childView.getMeasuredHeight(); totalheight = totalheight + height; //Get the margin of the child View FrameLayout.LayoutParams frameLayoutParams = (LayoutParams) childView.getLayoutParams(); int left = frameLayoutParams.leftMargin; int top = frameLayoutParams.topMargin; int bottom = frameLayoutParams.bottomMargin; //Ensure that the position of the first View is not displayed outside the layout if (i != 0) { int yPoint = totalheight - height / 2; left = left + (int) (mRadioWH * yPoint - width / 2); top = top + totalheight - height; } //Layout default top left bottom right childView.layout(left, top, left + width, top + height + bottom); } } }
/*************************************************divider*************************************************************/
Summary: Although the function is simple, it is still recorded. This code makes me familiar with the drawing of ViewGroup. The View itself inherits the ViewGroup