简体   繁体   中英

Change a view margins programmatically

So I have a RecyclerView that has 250dp bottom margin And I need to set the bottom margin programmatically to 0dp then set it back to 250dp, I have tried this but it's working just to set it 0dp and it doesn't work setting it to 250dp back:

    ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) linearLayoutRv.getLayoutParams();
                params.setMargins(0,0,0,250); // params.setMargins(0,0,0,0); at first
                linearLayoutRv.setLayoutParams(params);

There's some unnecessary things but here's the xml file:

    <androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/linearLayoutRv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="250dp"
        android:gravity="center"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="51dp"
            android:gravity="center">
            //textview
          
        </androidx.constraintlayout.widget.ConstraintLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="51dp"
            android:orientation="horizontal">
            //some buttons
        </LinearLayout>

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginHorizontal="5dp"
            android:padding="4dp"
            android:scrollbars="vertical" />
    </LinearLayout>

The problem is that setMargins accepts values not in dp (density independent pixels) unit but in px (pixel) unit.

You must convert your value of 250 to dp before passing it to the params object.

Context context = ...; // place 'this' if you are in an Activity or 'requireContext()' if you are in a Fragment
Resources res = context.getResources();
float dp250 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 250, res.getDisplayMetrics());

ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) linearLayoutRv.getLayoutParams();
params.setMargins(0, 0, 0, dp250);
linearLayoutRv.setLayoutParams(params);

dp250 will result in a different number of pixels on different devices. It depends on the resolution and physical screen size.

When you set margins programatically, you set value in pixels, not dp. Source of LayoutParams:

         /**
         * 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) {
            leftMargin = left;
            topMargin = top;
            rightMargin = right;
            bottomMargin = bottom;
            mMarginFlags &= ~LEFT_MARGIN_UNDEFINED_MASK;
            mMarginFlags &= ~RIGHT_MARGIN_UNDEFINED_MASK;
            if (isMarginRelative()) {
                mMarginFlags |= NEED_RESOLUTION_MASK;
            } else {
                mMarginFlags &= ~NEED_RESOLUTION_MASK;
            }
        }

You need convert your dp to pixels:

Int yourDP = 250
Resources r = getResources();
float px = TypedValue.applyDimension(
    TypedValue.COMPLEX_UNIT_DIP,
    yourDP,
    r.getDisplayMetrics()
);
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) linearLayoutRv.getLayoutParams();
            params.setMargins(0,0,0,(int) px); // params.setMargins(0,0,0,0); at first
            linearLayoutRv.setLayoutParams(params);

You can easily do this with MotionLayout . Just convert parent ConstraintLayout to MotionLayout , create MotionScene and in code use transitionToEnd() and transitionToStart()

example

it was working but in pixels, so i added this method:

public static int convertDpToPixel(int dp, Context context){
    return dp * ((int) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}

and changed this:

params.setMargins(0,0,0,convertDpToPixel(250,getContext()));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM