我想为我的应用程序创建一个 GUI,它本质上是一个背景图像,上面有一些控件。重要(且棘手)的部分是背景图像应保持其纵横比和比例(如果不完美,则带有黑色边框),并且控件与背景图像的某些部分对齐。
我正在考虑通过继承 AbsoluteLayout (或我的副本,因为它已被弃用),正确缩放/定位它并让它绘制我的背景图像来解决这个问题。然后,我会让它根据“缩放的绝对位置”放置它的孩子,使用缩放因子[测量的布局大小]/[原始背景图像大小]。
我的问题是,有没有更好的方法来做到这一点?这似乎是一种复杂的方式来做我认为相对常见的事情?(在背景图像像素上完美对齐按钮图像)。我感谢所有的指示和建议。
我最终使用了上述策略。为了完成,这就是我所做的:
我创建了一个类 ScalingLayout,扩展了 AbsoluteLayout,并添加了两个 xml 属性,允许我为布局指定“虚拟尺寸”。这些是我放置视图的维度,布局确保在缩放整个布局时正确缩放这些相对位置。所以在xml中它看起来像:
<ScalingLayout
mynamespace:virtualWidth="100"
mynamespace:virtualHeight="100"
...
>
有关如何定义自定义 xml 属性并在类构造函数中获取这些值的信息,请查看以下问题:Defining custom attrs
此外,我在 ScalingLayout 中覆盖了 onMeasure 和 onLayout。
// 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 一样,但要考虑虚拟尺寸。