Добро пожаловать в Kotlin!
Итак, у вас есть анимация Губки Боба, теперь вам нужно немного c logi для управления этой анимацией. Проблема здесь в том, что вы не всегда хотите, чтобы происходила полная анимация, верно? Если он слишком близко к краю экрана, вы хотите, чтобы кнопка перемещала его только до этой невидимой стены (и если он прямо напротив нее, это означает, что движения вообще нет).
Анимация и Системы рисования не накладывают никаких ограничений на то, где вы можете разместить View, поэтому вам решать, как это делать самостоятельно. В основном вам нужно сделать это при нажатии кнопки:
- получить координаты положения Губки Боба (это X, который вам действительно важен прямо сейчас)
- выработать положение края вас заботит (координаты представления описывают, где находится верхний левый угол, поэтому, если вы смотрите на правый край, вам нужна эта координата X + ширина представления)
- выработайте координату X край экрана (или родительский макет, что бы вы ни хотели, чтобы Губка Боб содержался внутри)
- если расстояние между краем Губки Боба и краем экрана меньше, чем ваше обычное движение анимации, вам необходимо изменить его до этого оставшегося расстояния
- вы также захотите определить соответствующую продолжительность, если он перемещается на половину обычного расстояния, анимация должна длиться вдвое меньше
это много для работать, и есть несколько способов сделать это, но вот один из подходов, просто используя края экрана в качестве границ
import android.os.Bundle
import android.view.View
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import kotlin.math.abs
import kotlin.math.min
private const val MOVE_DISTANCE = 100
private const val MOVE_TIME = 90
class MainActivity : AppCompatActivity() {
private var screenWidth = 0
private lateinit var spongeBob : View
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.spongebob)
// store this when the Activity is created, if the device is rotated the Activity
// will be recreated and this method gets run again
screenWidth = applicationContext.resources.displayMetrics.widthPixels
//val picture = findViewById<ImageView>(R.id.SpongeBob)
val right_button = findViewById<Button>(R.id.right)
val left_button = findViewById<Button>(R.id.left)
spongeBob = findViewById(R.id.spongeBob)
right_button.setOnClickListener()
{
// two possible values - the distance to the edge, and the normal amount we move
// we want the smaller of the two (i.e. always move the normal amount, unless
// the edge is closer than that
val distance = min(distanceToEdge(left = false), MOVE_DISTANCE)
moveSpongeBob(distance)
}
left_button.setOnClickListener()
{
val distance = min(distanceToEdge(left = true), MOVE_DISTANCE)
// we're moving left so we need to use a negative distance
moveSpongeBob (-distance)
}
}
private fun distanceToEdge(left: Boolean): Int {
// Get the Spongebob's top-left position - the call is a method on the View class,
// I'm assuming SpongeBob is a View, and you need to pass an array in because
// that's just how it works for whatever reason...
val location = IntArray(2)
spongeBob.getLocationOnScreen(location)
val x = location[0]
// I'm just using the View.getWidth() call here (Kotlin style) but I don't know
// what the SpongeBob class is, so you'll need to handle this
// You could set this once, like when we get the screen width, but width will be 0 until
// the View is laid out - so you can't do it in #onCreate, #onViewCreated should work
val spongeBobWidth = spongeBob.width
// the left edge is just the x position, however far that is from zero
return if (left) x
// the right edge is the x position plus the width of the bob
else screenWidth - (x + spongeBobWidth)
}
// Actually move the view, by the given distance (negative values to move left)
private fun moveSpongeBob(distance: Int) {
// work out how much this distance relates to our standard move amount, so we can
// adjust the time by the same proportion - converting to float so we don't get
// integer division (where it's rounded to a whole number)
val fraction = distance.toFloat() / MOVE_DISTANCE
// distance can be negative (i.e. moving left) so we need to use the abs function
// to make the duration a postitive number
val duration = abs(MOVE_TIME * fraction).toLong()
spongeBob.animate().setDuration(duration).translationXBy(distance.toFloat())
}
}
Th Есть более приятные вещи, которые вы можете сделать (и SpongeBob
следует называть spongeBob
и быть View
), но это основы. Эта статья о системе координат может вам тоже помочь.