Search code examples
androidxmlkotlinbuttononcreate

change programmatically view propieties


i'm new to kotlin.

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val btnDivide : Button = findViewById(R.id.divideInputButton)
    val btnCancel : Button = findViewById(R.id.cancelInputButton)

I'm trying to change the btnCancel dinamically, just for fun, because i see (i'm new also to xml so i'm wrong maybe) that in xml file i can't do something like android:layout_width="wrap_content*2" or similar dinamic stuff based on the display.

So i was trying to do it in MainActivity.kt right after the setContentView(R.layout.activity_main)

Most likley do something like

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val btnDivide : Button = findViewById(R.id.divideInputButton)
    val btnCancel : Button = findViewById(R.id.cancelInputButton)

    var paramsCancel : LinearLayout.LayoutParams = btnCancel.layoutParams as LinearLayout.LayoutParams
    var paramsDivide : LinearLayout.LayoutParams = btnDivide.layoutParams as LinearLayout.LayoutParams
    paramsCancel.width = paramsDivide.width

is a very bad practice imo, because i'm setting the xml layout -> displaying it on the device-> do some math and operation-> change the values and display the canges; so if the app has a lot of todos after setContentView(R.layout.activity_main) and before paramsCancel.width = paramsDivide.width the user will see in 2 types of UI during his use of the app.

So, is there a better method to change some params (like btn.width) in programmatically way? if yes, is that the right way or should i change my mind completely ?

In this example i was trying to set the btnCncel width to the width of an other button, but is not working (in the image seems ok but is because i've changed the width manually using dp in the xml file after all the depression). If i set the width to paramsCancel.width = 100works( works with Integers in general)

enter image description here


Solution

  • Your comment about why this would be bad practice:

    "...the user will see in 2 types of UI during his use of the app"

    is incorrect.

    The way UI layout works is that there is a main thread Looper that handles all tasks that are sent to it. Every time there is an event that affects the UI, a function call is sent to that Looper and it runs through to completion before anything is redrawn to the screen.

    So, for instance, if a button is pressed, the OnClickListener for that button will be called on the main thread and run through to completion before anything is redrawn on the screen. It doesn't matter how many actions you take by the end of your listener's function. That's why you're not supposed to do any blocking (time-consuming) actions on the main thread like writing to a file. That would freeze the UI while the file is being written.

    So even if you modify 100 different buttons' layout params and colors sequentially, the user will not see any changes until after the function returns.

    The same is true for onCreate(). The user will not see anything from your Activity until after onCreate() returns.

    If your calculator does some calculation that takes so long that you're afraid it will freeze the UI noticeably, correct practice would be to first lock the buttons (disable them or set some Boolean property that all their listeners check to determine if they should work), then show some progress indicator, then launch a background thread or coroutine to do the work, and then when the calculation is done, unlock everything and show the result.

    Realistically, you don't need to do that for a simple calculator. It's not like you're manipulating a huge data set.

    View sizes set in Kotlin must be done in integer pixel units. You can search for other questions on here about how to convert dp units into pixel units.