Setting limits for randomly generated positions for button
Solution 1:
Display metrics gives you the size of the whole screen, including the status bar, bottom system bar, etc. Depending on which settings the user has turned on, you may or may not have to try to find the heights of the system bars and selectively subtract them. This is very complicated and error prone.
You could get the height and width of your view, but not until after the scene has already been laid out, which hasn't happened yet in onCreate()
. Even if you do that, you also have to keep in mind the size of the button itself so you don't pick a position that crops off its right or bottom edge. So that is also messy.
Instead, I would put the Button in a ConstraintLayout and constrain all four of its edges to the parent's edges. This will center it. Then you can modify verticalBias
and horizontalBias
to put it at a random position that fits in the view.
verticalBias
and horizontalBias
are a number between 0 and 1 that shifts a view between the extremes of its relevant constraints, so you can simply choose a random number between 0 and 1 to get a random position. You can use Random.nextFloat()
to get a random number from 0 to 1.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/myButton"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
private fun randomizeButtonPosition() {
button.layoutParams = (button.layoutParams as ConstraintLayout.LayoutParams).apply {
horizontalBias = Random.nextFloat()
verticalBias = Random.nextFloat()
}
}
Note we are only modifying the existing LayoutParams instance that is set on the button, but we also have to reassign it back to the button anyway to make the ConstraintLayout aware that it needs to recompute the position.