Я пишу игру, в которой счетчики можно перетаскивать по экрану. Я хочу использовать ImageView
дочернее представление для каждого счетчика и установить абсолютные позиции внутри FrameLayout
родительского представления.
Я прочитал несколько SO-сообщений о преимуществах различных классов компоновки по сравнению с устаревшим AbsoluteLayout
, и я не хочу использовать RelativeLayout
, потому что счетчики должны перемещаться независимо друг от друга. Похоже, что ни один из этих постов не посвящен конкретной проблеме, с которой я сталкиваюсь, хотя я был бы рад, если бы кто-то мог указать мне на такой вопрос.
Вот макет XML:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_game"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff808080">
</FrameLayout>
Поскольку я не хочу делать предположения о размере экрана, я устанавливаю размер каждого дочернего элемента в виде доли от размера родителя внутри onMeasure()
:
package uk.co.fractalmaze.counterspin.widget
import android.content.Context
import android.graphics.Color
import android.util.Log
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
class CounterView(context: Context, private val label: String, private val offset: Int) : ImageView(context)
{
init
{
// Set the background color.
val color = if (offset > 0) Color.GREEN else Color.RED
setBackgroundColor(color)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int)
{
// Set the position and size.
val parentWidth = MeasureSpec.getSize(widthMeasureSpec)
val parentHeight = MeasureSpec.getSize(heightMeasureSpec)
val size = Math.min(parentWidth, parentHeight) / 2
val left = offset * size
Log.i(javaClass.simpleName, "Parent size ($parentWidth, $parentHeight) to $label child position ($left, 0) size $size")
setMeasuredDimension(size, size)
layoutParams = createLayoutParams(left, 0, size, size)
}
private fun createLayoutParams(left: Int, top: Int, width: Int, height: Int): ViewGroup.LayoutParams
{
// Create a margin params object.
val params = FrameLayout.LayoutParams(width, height)
params.leftMargin = left
params.topMargin = top
return params
}
}
Для полноты, вот где я добавляю дочерние представления к родителю:
package uk.co.fractalmaze.counterspin.activity
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.FrameLayout
import uk.co.fractalmaze.counterspin.R
import uk.co.fractalmaze.counterspin.widget.CounterView
class GameActivity : AppCompatActivity()
{
override fun onCreate(savedInstanceState: Bundle?)
{
// Call the superclass.
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_game)
// Add a left and right view to the group.
val group = findViewById<FrameLayout>(R.id.activity_game)
group.addView(CounterView(applicationContext, "left", 0))
group.addView(CounterView(applicationContext, "right", 1))
}
}
Вот скриншот с результатами:
Я ожидаю, что красный и зеленый дочерние виды появятся рядом и заполнят экран, но вместе они занимают только половину ширины. Это подтверждается выводом logcat, который показывает расшифрованную родительскую ширину MeasureSpec
как 1080, а затем 540, что дает дочернюю ширину 540, а затем 270. Это выполняется на смоделированном пикселе 3 с шириной экрана 1080 пикселей:
2019-05-09 22:06:33.493 15575-15575/uk.co.fractalmaze.counterspin I/CounterView: Parent size (1080, 1808) to left child position (0, 0) size 540
2019-05-09 22:06:33.493 15575-15575/uk.co.fractalmaze.counterspin I/CounterView: Parent size (1080, 1808) to right child position (540, 0) size 540
2019-05-09 22:06:33.560 15575-15575/uk.co.fractalmaze.counterspin I/CounterView: Parent size (540, 540) to left child position (0, 0) size 270
2019-05-09 22:06:33.561 15575-15575/uk.co.fractalmaze.counterspin I/CounterView: Parent size (540, 540) to right child position (270, 0) size 270
Может кто-нибудь сказать мне:
- Почему родительский вид изменяет размеры до ширины 540?
- Как заставить дочерние представления заполнять все 1080 пикселей?