Я хочу создать графический интерфейс для моего приложения, который по сути является фоновым изображением с некоторыми элементами управления поверх него. Важной (и хитрой) частью является то, что фоновое изображение должно сохранять соотношение сторон и масштаб (с черными границами, если оно не идеально подходит), и что элементы управления выровнены с определенными частями фонового изображения.
Я думал о том, чтобы решить эту проблему, унаследовав AbsoluteLayout (или мою копию, поскольку она устарела), правильно масштабировав / разместив ее и заставив нарисовать мое фоновое изображение. Затем я бы разместил его дочерние элементы в соответствии с «масштабированными абсолютными позициями», используя коэффициент масштабирования [Измеренный размер макета] / [Исходный размер фонового изображения].
Мой вопрос: есть ли лучший способ сделать это? Кажется, это сложный способ сделать что-то, что, как я считаю, встречается относительно часто? (Выравнивание изображения кнопок на пикселе фонового изображения отлично). Я благодарен за все советы и предложения.
В итоге я использовал вышеуказанную стратегию. Для завершения вот что я сделал:
Я создал класс ScalingLayout, расширяющий AbsoluteLayout, и добавил два атрибута xml, которые позволяют мне указывать «виртуальные измерения» для макета. Это те измерения, по которым я размещаю свои виды, и макет обеспечивает правильное масштабирование этих относительных положений при масштабировании всего макета. Так в xml это выглядит так:
<ScalingLayout
mynamespace:virtualWidth="100"
mynamespace:virtualHeight="100"
...
>
Для получения информации о том, как определить пользовательские атрибуты xml и получить эти значения в конструкторе класса, проверьте этот вопрос: Определение пользовательских атрибутов
Более того, я переопределил «Измерить и выложить» в моем ScalingLayout.
// Overridden to retain aspect of this layout view
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
double aspect = getSize(widthMeasureSpec) / (double)getSize(heightMeasureSpec);
// Those are from XML layout
double virtualAspect = _virtualWidth / (double)_virtualHeight;
int width, height;
measureChildren(widthMeasureSpec, heightMeasureSpec);
if(aspect > virtualAspect) {
height = getSize(heightMeasureSpec);
width = height * virtualAspect;
} else {
width = getSize(widthMeasureSpec);
height = width / virtualAspect;
}
setMeasuredDimension(width, height);
}
...
protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
double factor = (right - left) / (double)_virtualWidth;
nchildren = getChildCount();
for(int i = 0; i < nchildren; i++) {
View child = getChildAt(i);
LayoutParams lp = child.getLayoutParams();
// Scale child according to given space
child.layout(lp.x * factor,
lp.y * factor,
(lp.x + child.getMeasuredWidth()) * factor,
(lp.y + child.getMeasuredHeight()) * factor );
}
}
Теперь просто добавьте представления в XML и укажите размеры и позиции так же, как для AbsoluteLayout, но подумайте о виртуальных измерениях.