简体   繁体   English

Android:如何使用屏幕尺寸缩放布局

[英]Android: how to scale a layout with screen size

Consider this layout (pulled from here ): 考虑这种布局(从这里拉出):

在此输入图像描述

I'd like to understand the principles behind making this layout scale with screen size. 我想了解使用屏幕尺寸进行此布局规模的原则。 For the square, a custom onMeasure function works nicely: 对于广场,自定义onMeasure功能可以很好地工作:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}

The width and height of the custom Togglebuttons and Imagebuttons below should scale to fill the remainder of the screen, minus layout_margins, and the text and images within should scale to fill the buttons, minus padding. 下面的自定义Togglebuttons和Imagebuttons的宽度和高度应缩放以填充屏幕的其余部分,减去layout_margins,并且内部的文本和图像应缩放以填充按钮,减去填充。 The outer margin should also scale. 外边距也应该缩放。

My first thought was to use a relative layout to position the buttons, and layout_margin/padding attributes to create margins. 我的第一个想法是使用相对布局来定位按钮,并使用layout_margin / padding属性来创建边距。 However, relative layouts and layout_margin/padding require fixed pixel values, so they aren't scalable. 但是,相对布局和layout_margin / padding需要固定的像素值,因此它们不可伸缩。

I then thought of using nested linear layouts with layout_weights to position the buttons, and placeholder views to create margins. 然后我考虑使用带有layout_weights的嵌套线性布局来定位按钮,并使用占位符视图来创建边距。 Although these techniques are scalable, they don't work with buttons, because buttons have many attributes (text size, image size, corner radius, etc.) that require fixed pixel values. 虽然这些技术是可扩展的,但它们不适用于按钮,因为按钮具有许多需要固定像素值的属性(文本大小,图像大小,角半径等)。 This limitation means, for example, that the following xml: 例如,此限制意味着以下xml:

<ToggleButton 
    android:layout_weight="1"
    style="@style/myButton"
    [...] />
<View 
    android:layout_weight="1"/>
<ImageButton 
    android:layout_weight="1"
    style="@style/myButton"
    [...] />

won't necessarily make the two buttons, and the space between them, all the same width. 不一定会使两个按钮和它们之间的空间宽度相同。 It all depends on the text size, image size, etc. etc. of the buttons. 这一切都取决于按钮的文字大小,图像大小等。

I've taken a look at this question but I feel there should be a simpler solution for such a simple problem, that shouldn't require resorting to too much non-XML. 我已经看过这个问题,但我觉得对于这样一个简单的问题应该有一个更简单的解决方案,不应该求助于过多的非XML。

If you build your views using "dp" it would, basically, be the same size for eack screen size. 如果使用“dp”构建视图,它基本上与eack屏幕大小的大小相同。
In most cases you will prefer that your view will resize itself proportional to the screen size. 在大多数情况下,您希望视图会根据屏幕大小调整自身大小。
Of course, in most cases you will need to build separate layouts for tablets. 当然,在大多数情况下,您需要为平板电脑构建单独的布局。
But, besides I can recommend you to do the next steps: 但是,除了我可以建议你做下一步:

1. Add this library to your project. 1. 将此库添加到项目中。

2. Now in your layout you can write views like that: 2.现在在您的布局中,您可以编写以下视图:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="I'm scalable!" 
    android:textSize="@dimen/_12sdp"/>

In this example your TextView will scale on each screen size. 在此示例中,TextView将在每个屏幕大小上缩放。

3. Preview all screen sizes to see the result. 3.预览所有屏幕尺寸以查看结果。

It depends a lot on the number of custom View and ViewGroup classes you want to create. 它很大程度上取决于您要创建的自定义ViewViewGroup类的数量。 An implementation with the least number of custom classes that I could think of would be something like this (very similar to what you've described): 我能想到的具有最少数量的自定义类的实现将是这样的(非常类似于您所描述的):

  • Customized FrameLayout for the largest square, with a custom onMeasure() implementation to match the height to the available width (you mentioned this one already). 自定义FrameLayout用于最大的正方形,使用自定义onMeasure()实现将高度与可用宽度相匹配(您已经提到过这个)。
  • Nested LinearLayout instances using weight to get all the grid buttons to be the same size. 嵌套的LinearLayout实例使用权重来使所有网格按钮的大小相同。

The big drawback to this approach is efficiency. 这种方法的一大缺点是效率。 You would need roughly 36 LinearLayout instances to create the small 9x9 grids inside of a larger 9x9 grid...that's 36 views of pure layout overhead. 您需要大约36个LinearLayout实例才能在更大的9x9网格内创建小的9x9网格......这是纯布局开销的36个视图。


As far as text sizing, there are a couple ways I could think of to handle this. 就文本大小而言,我可以想到几种方法来处理这个问题。 One would be to use Paint.measureTextBounds() (you can get the Paint object of any TextView to do the measurements) to determine what size you need to make the text in each button after they have been measured. 一种方法是使用Paint.measureTextBounds() (您可以获取任何TextViewPaint对象来进行测量),以确定在测量每个按钮后在每个按钮中生成文本所需的大小。 Unfortunately this would be a somewhat iterative process because the Paint measures a given text based on its current settings, so you would need to: 不幸的是,这将是一个有点迭代的过程,因为Paint根据其当前设置测量给定文本,因此您需要:

  1. Set the text size 设置文字大小
  2. Measure bounds 测量边界
  3. Check height 检查身高
  4. Repeat until the size just fits 重复直到尺寸合适

The good news is you would only need to do this once and just apply it to all the grid buttons, but you would need to wait until the grid buttons are measured. 好消息是你只需要这样做一次,然后将其应用到所有网格按钮,但是你需要等到网格按钮被测量。

Another option here would be to display an image instead of text inside of something like ImageView , which can scale the content for you to its size. 这里的另一个选择是在ImageView之类的内容中显示图像而不是文本, ImageView可以将内容缩放到其大小。 You could use something like the TextDrawable that I wrote to set text content as an image that is scalable without quality loss. 您可以使用我编写的TextDrawable之类的东西来将文本内容设置为可扩展且没有质量损失的图像。


Now back to the layout. 现在回到布局。 You could gain back a ton of efficiency by creating a custom ViewGroup to measure and lay out the grid (the name GridLayout is already taken...and it doesn't quite serve this purpose, so let's call it BlockLayout ). 你可以通过创建一个自定义的ViewGroup来测量和布局网格来获得大量的效率(名称GridLayout已经被采用......并且它不能完全用于此目的,所以我们称之为BlockLayout )。 Creating a custom BlockLayout will allow you to measure the size of each block and lay out 9 subviews in a grid with a single parent instead of 4 LinearLayout instances. 创建自定义BlockLayout将允许您测量每个块的大小,并使用单个父级而不是4个LinearLayout实例在网格中布置9个子视图。 This is basically the same way that you measure the overall square, just divided evenly. 这与您测量整体方块的方式基本相同,只是均匀划分。

You could then build the entire layout with only 10 instances of layout overhead...and even less if you can code the entire thing into a single ViewGroup . 然后,您可以使用仅10个布局开销实例构建整个布局......如果您可以将整个内容编码到单个ViewGroup更少。

Basically the more code you can write to flatten the view hierarchy, the better your application will run overall. 基本上,您可以编写的用于展平视图层次结构的代码越多,应用程序整体运行的效果就越好。

HTH HTH

To complement Devnuwired's answer, you can write a method similar to this to add his TextDrawable text to an ImageButton : 为了补充Devnuwired的答案,您可以编写一个类似于此的方法将TextDrawable文本添加到ImageButton

private void addText(String text, ImageButton button, int colour) {
    TextDrawable d = new TextDrawable(this);
    d.setText(text);
    d.setTextColor(colour);
    d.setTextAlign(Layout.Alignment.ALIGN_CENTER);
    button.setImageDrawable(d);
}

or alternately 或者

private void addText(String text, int buttonID, int colour) {
    TextDrawable d = new TextDrawable(this);
    d.setText(text);
    d.setTextColor(colour);
    d.setTextAlign(Layout.Alignment.ALIGN_CENTER);
    ((ImageButton) findViewById(buttonID)).setImageDrawable(d);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM