Set runtime margin to any view using Kotlin
Asked Answered
S

6

48

I am a beginner in Kotlin .I am not too much familier with this language. I am making one example and playing with code. I Just want to set runtime margin to any view. I also trying to google it but not getting any proper solution for this task.

Requirement

Set runtime margin to any View.

Description

I have taking one xml file which is contain on Button and I want to set runtime margin to this button.

Code

I also try below thing but it's not work.

class MainActivity : AppCompatActivity() {


//private lateinit var btnClickMe: Button
//var btnClickMe=Button();

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //For setting runtime text to any view.
        btnClickMe.text = "Chirag"

        //For getting runtime text to any view
        var str: String = btnClickMe.text as String;

        //For setting runtimer drawable
       btnClickMe.background=ContextCompat.getDrawable(this,R.drawable.abc_ab_share_pack_mtrl_alpha)//this.getDrawable(R.drawable.abc_ab_share_pack_mtrl_alpha)


        /*
        //For Setting Runtime Margine to any view.
        var param:GridLayout.LayoutParams
        param.setMargins(10,10,10,10);

        btnClickMe.left=10;
        btnClickMe.right=10;
        btnClickMe.top=10;
        btnClickMe.bottom=10;
        */

        // Set OnClick Listener.
        btnClickMe.setOnClickListener {
            Toast.makeText(this,str,5000).show();
        }

    }

}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
tools:context="chirag.iblazing.com.stackoverflowapp.MainActivity"
android:layout_height="match_parent">

<Button
    android:id="@+id/btnClickMe"
    android:text="Click Me"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

</LinearLayout>

How can I proceed?

Shermanshermie answered 31/7, 2017 at 9:6 Comment(3)
can you post your activity_main.xml?Rothermere
Please check Update @chandil03 I also try this same this with LinearLayoutParam but it's not work.Shermanshermie
As i can see in your commented section this is not how we should use LayoutParams. Check answer.Rothermere
R
119

You need to get the layoutParams object from button and cast it to ViewGroup.MarginLayoutParams (which is a parent class of LinearLayout.LayoutParams, RelativeLayout.LayoutParams and others and you don't have to check which is btnClickMe's actual parent) and set margins to whatever you want.

Check following code:

val param = btnClickMe.layoutParams as ViewGroup.MarginLayoutParams
param.setMargins(10,10,10,10)
btnClickMe.layoutParams = param // Tested!! - You need this line for the params to be applied.
Rothermere answered 31/7, 2017 at 10:6 Comment(3)
var params = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT ).also { it.setMargins(10, 10, 10, 10) }Caboose
I got an error, cannot be cast "ndroid.view.ViewGroup$LayoutParams cannot be cast to android.view.ViewGroup$MarginLayoutParams"Raphaelraphaela
in kotlin we also need to call dp with value. like 10.dp as we give 10dp in xmlFairchild
P
56

This is how I would like to do in Kotlin -

fun View.margin(left: Float? = null, top: Float? = null, right: Float? = null, bottom: Float? = null) {
    layoutParams<ViewGroup.MarginLayoutParams> {
        left?.run { leftMargin = dpToPx(this) }
        top?.run { topMargin = dpToPx(this) }
        right?.run { rightMargin = dpToPx(this) }
        bottom?.run { bottomMargin = dpToPx(this) }
    }
}

inline fun <reified T : ViewGroup.LayoutParams> View.layoutParams(block: T.() -> Unit) {
    if (layoutParams is T) block(layoutParams as T)
}

fun View.dpToPx(dp: Float): Int = context.dpToPx(dp)
fun Context.dpToPx(dp: Float): Int = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.displayMetrics).toInt()

now we just have to call this on a view like

textView.margin(left = 16F)
Pampuch answered 8/6, 2018 at 17:46 Comment(1)
These were super useful!Feeder
W
9

Here's a useful Kotlin extension method:

fun View.setMargins(
    left: Int = this.marginLeft,
    top: Int = this.marginTop,
    right: Int = this.marginRight,
    bottom: Int = this.marginBottom,
) {
    layoutParams = (layoutParams as ViewGroup.MarginLayoutParams).apply {
        setMargins(left, top, right, bottom)
    }
}

Use it like this:

myView.setMargins(
   top = someOtherView.height
   bottom = anotherView.height
)

EDIT: the solution is similar to the answer from Hitesh, but I'm using the (original) ViewGroup.setMargins in pixels. Of course you can make your own setMarginsDp variant based on these examples, or use Hitesh's dpToPx extension before calling my implementation. Whichever solution you choose depends on your own taste.

Also take note that my solution (re)sets all margins, although this won't be an issue in most cases.

Wholesale answered 10/5, 2021 at 13:54 Comment(0)
S
1

Here is another sample of CardView

            myCardView.elevation = 0F
            myCardView.radius = 0F
            val param = (myCardView.layoutParams as ViewGroup.MarginLayoutParams).apply {
                setMargins(0,0,0,0)
            }
            myCardView.layoutParams = param
Siemens answered 16/9, 2021 at 17:20 Comment(0)
B
1

If you want to change specific margin like top or bottom you can use below code with Data binding .

 @BindingAdapter("android:layout_marginTop")
        @JvmStatic
        fun setLayoutMarginTop(view: View, marginTop: Float) {
            val layoutParams = view.layoutParams as ViewGroup.MarginLayoutParams
            layoutParams.topMargin = marginTop.toInt()
            view.layoutParams = layoutParams
        }

and in .xml file you can write like below code

 <ImageView
        android:id="@+id/imageView3"
        android:layout_width="@dimen/_15dp"
        android:layout_height="@dimen/_15dp"
        android:layout_marginTop="@{homeViewModel.getLanguage() ? @dimen/_14dp : @dimen/_32dp }"
        android:contentDescription="@string/health_indicator"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView1"
        app:layout_constraintEnd_toStartOf="@+id/textView3"
        android:src="@{ homeViewModel.remoteStatusVisible ? @drawable/green_rectangle : @drawable/gray_rectangle}"/>
Biretta answered 23/8, 2022 at 16:4 Comment(0)
O
0

if you want to set only right margin to 0 programatically

val params: ViewGroup.MarginLayoutParams =
                  yourView!!.layoutParams as ViewGroup.MarginLayoutParams
params.rightMargin = 0  // 
binding.progressParent.layoutParams = params
Oxford answered 15/2 at 10:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.