Dynamically set the spacing of View controls

To dynamically control the distance between the TextView and the top:

1. Requirements:

RelativeLayout has a background image with a width of 1635 by 1029px, and requires the TextView to display it 150px from the top of the background image.

<RelativeLayout android:id="@+id/rlt_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:background="@mipmap/detect_bg_pic01"> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="@dimen/detect_margin_title_top" android:background="@mipmap/detect_bg_tab" android:gravity="top|center_horizontal" android:text="@{vm.currentStepTitle}"  android:textColor="@color/white" android:textSize="16sp" /> </RelativeLayout>Copy the code

2. Analysis:

1. RelativeLayout is adaptive, so it scales equally

2. Obtain the actual height of the RelativeLayout

3. Calculate the actual distance between the TextView and the top background image at 150px

4. Dynamically set the distance between the TextView and the top

3. Realization:

/ /... @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); / /... Int rltLeftHeight = rltleft.getheight (); Int topMargin = (rltLeftHeight * 150) / 1029; int Topmargin = (rltLeftHeight * 150) / 1029; / / set dynamically TextView RelativeLayout. The distance from the top of the spacing LayoutParams LayoutParams = (RelativeLayout. LayoutParams) rltLeft.getLayoutParams(); LayoutParams. The setMargins (topmargin 0, 0, 0). tvTitle.setLayoutParams(layoutParams); } / /...Copy the code

4, dynamically set margin & pading

A, padding
view.setPadding(int left, int top, int right, int bottom);
Copy the code

SetPadding is in view. class and set the unit to px. In Pixels denotes the unit px

/**
 * Sets the padding. The view may add on the space required to display
 * the scrollbars, depending on the style and visibility of the scrollbars.
 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
 * from the values set in this call.
 *
 * @attr ref android.R.styleable#View_padding
 * @attr ref android.R.styleable#View_paddingBottom
 * @attr ref android.R.styleable#View_paddingLeft
 * @attr ref android.R.styleable#View_paddingRight
 * @attr ref android.R.styleable#View_paddingTop
 * @param left the left padding in pixels
 * @param top the top padding in pixels
 * @param right the right padding in pixels
 * @param bottom the bottom padding in pixels
 */
public void setPadding(int left, int top, int right, int bottom) {
}
Copy the code
B, margin
LayoutParams lp = (LayoutParams) view.getLayoutParams();
lp.setMargins(int left, int top, int right, int bottom);
Copy the code

SetMargin is in viewgroup.class, also in pixels px, and setMargin is in the inner class of marginLayoutParams.class.

/** * Sets the margins, in pixels. A call to {@link android.view.View#requestLayout()} needs * to be done so that the new margins are taken into  account. Left and right margins may be * overridden by {@link android.view.View#requestLayout()} depending on layout direction. * Margin values should be positive. * * @param left the left margin size * @param top the top margin size * @param right the right margin size * @param bottom the bottom margin size * * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginLeft * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginRight * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom */ public void setMargins(int left, int top, int right, int bottom) { }Copy the code

When setting margin, note that view.getLayoutParams() is cast, depending on what container the view’s parent element is. TextView’s parent container is RelativeLayout, so:

RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) rltLeft.getLayoutParams(); LayoutParams. The setMargins (topmargin 0, 0, 0). tvTitle.setLayoutParams(layoutParams);Copy the code

Get the width and height of the View

1. Questions:

Based on the usage above, the width and height values in the Activity obtained from the view.getwidth () or view.getheight () lifecycle methods in onCreate() or onResume() are 0.

2. Analysis:

We know that the drawing process of a View is divided into three steps:

OnMeasure:

Measure the size of View, recursively call measure() method from top-level parent View to child View, and measure() calls onMeasure() method, and onMeasure() method completes the drawing work.

OnLayout:

Determine the position of the View, recursively call layout() method from the top parent View to the child View, the parent View will measure() method of the previous step to obtain the child View layout size and layout parameters, put the child View on the appropriate position.

Ontouch:

To draw the final view, ViewRoot first creates a Canvas object and then calls onDraw() to draw it.

The drawing process of onDraw() method is as follows:
  • ① Draw the view background.
  • 2. Draw the layers of the canvas.
  • ③ Draw the View content.
  • Draw subviews, if any.
  • ⑤ Restore the layer.
  • ⑥ Draw the scroll bar.

So, when we get the View width directly in the Activity lifecycle method, the View may not have completed the measure phase, and the result will be 0.

3, get the correct scheme of View width and height

View post(Runnable runnalbe)
view.post(new Runnable() { @Override public void run() { int width = view.getWidth(); }});Copy the code

This method adds a Runnable operation to the end of the queue, which is called when the View attachToWindow is waiting. When View attachToWindow, onMeasure() and onLayout() have been applied so the width and height can be obtained.

2. Listen for ondraw&onLayout changes in Viewde ViewTreeObserver

Use the ViewTreeObserver class to listen for the draw event

When the View is about to be drawn, it has already passed onMeasure() and onLayout(), so you can get the width and height of the View. The onPreDrawListener may be called back multiple times, so be careful to remove it.

view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { Log.e(TAG, "onCreate: "+view.getWidth()+","+view.getHeight()); Log.e(TAG, "onCreate: "+view.getMeasuredWidth()+","+view.getMeasuredHeight()); // Remove listener view.getViewTreeObserver().removeonPreDrawListener (this); return false; }});Copy the code

B, Use the ViewTreeObserver class to listen to layout events

view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (Build.VERSION.SDK_INT >= 16) { view.getViewTreeObserver().removeOnGlobalLayoutListener(this); }else { view.getViewTreeObserver().removeGlobalOnLayoutListener(this); } int width = view.getWidth(); }});Copy the code
3. Get the view width and height in the Activity’s onWindowFocusChanged(Boolean hasFocus) method

OnWindowFocusChanged (Boolean hasFocus) will call back when the Activity’s current Window focus changes. When the Activity gets focus, The layout of the View has completed the onMeasure() and onLayout() layout, you can correctly obtain the width and height of the View.

  @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        int width = view.getWidth();
        int height = view.getHeight();
    }

Copy the code

The above scheme, View. Post scheme to obtain the View of the width and height properties, compared to the ViewTreeObserver listening processing, also do not need to manually remove the observer listening event, the code is more concise, simple to use.

4. GetWidth () is distinguished from getMeasuredWidth(). GetHeight () is distinguished from getMeasuredHeight()

GetMeasuredWidth () and getMeasuredHeight() get the original size of the view, either as configured in the XML file or as set in the code.

GetWidth () and getHeight() get the final display size of the view, which may or may not be equal to the original size.

< END >

[Evolution of Android]

Scan the QR code on wechat and follow my official account.