【问题标题】:ImageButtons on different sized devices不同尺寸设备上的 ImageButtons
【发布时间】:2013-10-23 07:05:14
【问题描述】:

据我所知(如果我错了,请纠正我),如果您想在多种尺寸的设备上拥有看起来不错的图形按钮(具有良好的抗锯齿功能),您必须创建不同的一组不同大小的图像,并将图像放在不同目录的集合中。我正在寻找一个工作示例,该示例准确显示要使用的目录集以及这些目录需要的相对大小。

顺便说一句,当我说 ImageButtons 时,我的意思是包含一个图像而不是文本 - 所以 9patch 图像无法解决问题。

编辑:让我特别困惑的一件事是,我经常看到人们使用不同屏幕密度的例子(例如chuck258的回答)......但如果您制作的按钮的宽度和高度针对密度进行了调整,然后您的按钮占据的屏幕比例可能会以各种不受控制的方式变化,如果您有一个高密度但小尺寸的屏幕,那么您的按钮会过大。

编辑:在我上次编辑之后,也许我应该更具体地说明我想要什么......让我们说我想要一个大约 10% 的方形 ImageButton(我会接受(仅纵向)屏幕宽度的 8% 到 13% 的变化......我会制作多大尺寸的图像,它们会在什么目录中?

编辑:我收到的信息是,如果你有更多的屏幕空间,那么标准的做法是让图标占据屏幕的一小部分。这大概是因为允许图标变得非常大,使它们看起来更像玩具或幼稚。但问题是,我正在为儿童制作游戏应用程序!所以这正是我想要的。

【问题讨论】:

  • 这解释了一切:developer.android.com/guide/practices/screens_support.html。最重要的是了解屏幕密度和屏幕尺寸之间的差异,以及它如何影响您所需的图像资源。
  • 那份文件极其复杂,犯错的范围也很大......这就是为什么我想看一个与我的问题相对应的例子。
  • 所以你对你的问题提出了赏金,但没有将答案标记为正确以“节省”一半的赏金......

标签: android


【解决方案1】:

首先你需要了解屏幕密度和屏幕尺寸的区别。

屏幕尺寸是物理尺寸,以屏幕的对角线测量。 Android 将所有实际屏幕尺寸分为四种通用尺寸:小、普通、大和特大。 一部手机的屏幕尺寸可能为 4.9 英寸,这被认为是正常的,Nexus 7(2012 年的旧款和 2013 年的新款)的屏幕尺寸均为 7 英寸,这很大,Nexus 10 的屏幕尺寸10 英寸,这是特大号。

另一方面,屏幕密度是屏幕物理区域内的像素数量;通常称为 dpi(每英寸点数)。例如,与“正常”或“高”密度屏幕相比,“低”密度屏幕在给定物理区域内的像素较少。 为简单起见,Android 将所有实际屏幕密度分为四种通用密度:低、中、高和超高(加上新的 xxhdpi)。 旧的 Nexus 7 的屏幕尺寸与新的 Nexus 7 相同,但旧的分辨率为 1280x800,即 216 dpi 或 hdpi,而新的分辨率为 1920×1200 像素,即 323 dpi 或 xhdpi(更多像素在同一物理区域内意味着更高的像素密度(以 dpi 为单位)。

如果屏幕具有相同的屏幕密度,drawable 文件夹中的图像将在小屏幕、普通屏幕、大屏幕和超大屏幕上具有相同的物理尺寸。因为屏幕具有不同的尺寸,所以图像将占据屏幕的不同部分。在小屏幕上,它会比在大屏幕上占据更大的百分比。

如果同一图像位于屏幕尺寸文件夹之一(drawable-small、drawable-normal、drawable-large、drawable-xlarge)中,则不会发生任何变化,但您可以决定将较大版本的图像放入 drawable-超大。在这种情况下,Nexus 10 上的图像会比新 Nexus 7 上的大(两者都有 xhdpi 像素密度)。

如果屏幕具有不同的像素密度,则相同的图像看起来会有所不同。与 mdpi 屏幕相比,xhdpi 屏幕上的图像大小只有一半(因为 xhdpi 屏幕的像素密度大约是两倍):
http://developer.android.com/images/screens_support/density-test-bad.png

对于一个图标,您通常希望它在不同的屏幕上具有相同的大小。这就是为什么例如mdpi 屏幕的菜单图标为 32x32,xhdpi 屏幕的菜单图标为 64x64,两者都位于相应的可绘制文件夹(drawable-mdpi 和 drawable-xhdpi)中:
http://developer.android.com/images/screens_support/density-test-good.png

现在什么时候使用像素密度,什么时候使用屏幕大小的可绘制文件夹?

如果图像在具有不同屏幕密度的屏幕上应具有相同的物理尺寸,则使用像素密度文件夹,这通常是您想要的。如果您对旧的和新的 Nexus 7 使用相同的图像,即使屏幕具有相同的物理尺寸,它也会有不同的尺寸,这不是您想要的。所以使用密度相关的图像势在必行。

如果您希望图像在小、普通、大和超大屏幕上具有不同的物理尺寸,则使用屏幕尺寸文件夹。如果我在主屏幕上有一个带有 6 个图标的网格导航,并且我不想在大屏幕上使用额外的屏幕空间(例如通过添加更多图标),那么我会为小屏幕提供一个小图像和大屏幕的大图像。 如前所述,您仍然需要在依赖于屏幕尺寸的图像之上提供依赖于密度的图像(例如旧的 Nexus 7 与新的 Nexus 7)。

因此,理论上您需要 16 个不同的资源来处理同一张图像(4 个屏幕尺寸,4 个屏幕密度,或者使用新的 xxhdpi 密度,甚至 5 个密度 -> 20 个资源)。 现在当然没有人想创建那么多资源,尤其是如果你有很多图像。 一种方法是按照某人的建议使用仪表板: http://developer.android.com/about/dashboards/index.html#Screens
并选择最常用的组合,即 small/ldpi、normal/mdpi、normal/hdpi 和 normal/xhdpi(占所有设备的 81%)。这样您就可以将资源减少到只有 4 个。
另一种方法是为屏幕大小或屏幕密度提供资源(同样只需要 4 个资源),然后在代码中进行一些缩放。

如果您有依赖于屏幕密度的资源,那么您将使用例如这个https://stackoverflow.com/a/5016350/534471 缩小图像(从不放大)。

如果你有依赖于屏幕大小的资源,那么你会使用这个http://developer.android.com/reference/android/util/DisplayMetrics.html 缩小图像。

这里有一个很好的例子(包括源代码): https://www.captechconsulting.com/blog/steven-byle/understanding-density-independence-android

现在针对您的具体问题,您可以在可绘制文件夹中使用一张通用图像。该图像的大小应该不会被放大(因为那看起来很难看)。您可以像这样在布局中定义按钮:

<ImageButton
    android:id="@+id/myButton"
    android:src="@drawable/myDrawable"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:scaleType="centerCrop"
    android:adjustViewBounds="true"
/>

与这段代码一起,按钮缩放到屏幕的 10%:

Display display = getWindowManager().getDefaultDisplay();
Point screenSize = new Point();
display.getRealSize(screenSize);
int size = Math.min(screenSize.x, screenSize.y);
int buttonSize = Math.round(size * 0.1f);
ImageButton button = (ImageButton) findViewById(R.id.myButton);
button.setMaxWidth(buttonSize);
button.setMaxHeight(buttonSize);

原始图像应该有多大?
Nexus 10 可能是目前所有 Android 设备中屏幕分辨率最高的。 1600 像素将在其 xhdpi 显示器上转换为 3200 密度独立像素。 3200 的 10% 是 320。如果您使用 320x320 图像,那么您将在所有现有设备上获得良好的效果。
不过,这种方法有一个问题。
320x320 相当大(可能是 24/32 位色深),因此您可能会遇到内存问题。如果您在依赖密度的可绘制文件夹中提供相同的资源,则可以降低 hdpi、mdpi 和 ldpi 设备的内存占用:

  • drawable-xhdpi: 320x320
  • drawable-hdpi:240x240
  • drawable-mdpi:160x160
  • drawable-ldpi: 120x120

屏幕大小的可绘制文件夹可用于进一步改善这一点(较小的屏幕需要较小的图像),但您必须提供前面提到的 16 或 20 个资源。最后,它是一方面的内存占用/速度与另一方面的可维护性/创建资源/apk 大小的时间之间的权衡。

【讨论】:

    【解决方案2】:

    您应该始终为所有密度创建图像。大多数图像(如图标)应以 dp 为单位固定高度。非固定高度的表面图像应该是可拉伸的 9patch 图像

    更多关于 9patch 的信息在这里:http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch

    【讨论】:

    • "图标的高度应该是固定的 dp" - 这不会导致屏幕宽度百分比的巨大变化吗?
    • 我的意思是刷新图标或菜单图标之类的东西。如果您真的希望视图占屏幕的一定比例,则可以使用 9patch 图像
    • 但是 9-patch 肯定是所有关于按钮背景的中心基本上是空的?我想在按钮的中心放置一个大小合适的图标。
    • 那么就使用 ImageButton 的 fitCenter 属性来自动缩放图像,或者这有什么问题?您只需要使用合理的大图像资源即可。
    【解决方案3】:

    Android 平台通常的做法是只为不同的屏幕密度提供图像,而不是为屏幕尺寸提供图像。如果我使用平板电脑,我不想看到大图像,我想看到更多信息。所以最好不要增加视图的大小,而是为更大的屏幕提供不同的布局。

    但是,如果您有特定的原因需要提供屏幕宽度的 10% 的图像,您可以使用具有不同 qualifiers 的“可绘制”文件夹。您对“可用宽度”、“屏幕尺寸”和“屏幕像素密度”限定词感兴趣。 例如提供以下图片:

    • drawable-sw320dp-mdpi - 图片宽度 32px
    • drawable-sw320dp-hdpi - 图片宽度 48px
    • drawable-sw320dp-xhdpi - 图片宽度为 64 像素
    • drawable-sw400dp-mdpi - 图片宽度为 40 像素
    • ...为您想要支持的所有设备提供图像

    【讨论】:

    • "为您想要支持的所有设备提供图像"...但我希望支持大约 2000 台设备!但幸运的是,我不需要我的按钮 exactlty 宽度的 10%,只是大约。所以大概必须有一些较小的大小和目录可以完成这项工作。
    • 不需要提供 2000 张图像,我的意思是您可以找到最佳尺寸/密度对。查看安卓设备仪表板:developer.android.com/about/dashboards/index.html#Screens
    【解决方案4】:

    我不知道我的问题是否正确,但有关图像的相对大小,请参阅:http://developer.android.com/design/style/devices-displays.html

    您可以为要支持的最大屏幕使用足够大的图像。然后在你的图片中使用scaleType="fitCenter"。这样做的一些缺点:

    是的:ScaleType.FIT_CENTERfitCenter 属性的编程等效项。一般来说,您可以期望 XML 中的每个属性都有一个 getter 和 setter。

    【讨论】:

    • 如果我希望按钮占屏幕宽度的某个(近似)百分比,那么这个答案没有帮助。
    • 如何为最大的屏幕创建足够大的图像以支持然后使用 fitCenter。我已经在下面的答案中将此作为评论发布,但如果这是正确的方式,你没有给出提示我理解你的问题
    • 我对评论投了赞成票...我正在以编程方式对其进行试验。我认为它需要一些额外的命令,例如 setmaxwidth 和 setadjustviewbounds,并且我认为 fitCenter 的程序等效项是 setScaleType(ScaleType.FIT_CENTER)。所以你的评论确实给了我很好的线索。如果您将完整答案放在答案的主体中,我会将其标记为正确。
    • 现在我的回答中也提到了一些缺点
    • 这很尴尬...我的视力不是最好的,当我戴上近视眼镜时,我注意到生成的图像的抗锯齿质量很差.我平板电脑上的图像显示宽度约为 72 像素。然后我拿了 500 像素的原件(在我的 drawables 目录中)并在“android 资产工作室”中创建了 72pix 版本 - 在质量方面没有竞争。
    【解决方案5】:

    转到你的项目-->Ctrl+n-->Android-->Android图标集-->下一步-->输入图标名称-->下一步-->图片-->浏览-->选择来自您的 PC 的图像--> 无--> 完成。 就是这样,它将自动在 4 个名为

    的文件夹中创建 4 种不同尺寸的单个图像

    1.drawable-hdpi 2.drawable-mdpi 3.drawable-xhdpi 4.drawable-xxhdpi

    因此您可以在应用程序中使用此图像,它将根据设备屏幕尺寸获取该图像。

    【讨论】:

      【解决方案6】:

      你可以这样做:

      package com.example.test;
      
      import android.app.Activity;
      import android.graphics.Bitmap;
      import android.graphics.BitmapFactory;
      import android.graphics.Point;
      import android.os.Bundle;
      import android.view.Display;
      import android.view.Menu;
      import android.widget.ImageButton;
      
      public class MainActivity extends Activity {
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              //Get ImageButton from XML
              ImageButton ib = (ImageButton) findViewById(R.id.imageButton);
              //Get the screen size
              Display display = getWindowManager().getDefaultDisplay();
              Point size = new Point();
              display.getSize(size);
              //10% of the screen width
              int width = (int) (size.x * 0.1);
              //Get and scale the Bitmap (10% of screen width)
              Bitmap bitmap = getImage(R.drawable.ic_launcher, width, width);
              ib.setImageBitmap(bitmap);
          }
      
          @Override
          public boolean onCreateOptionsMenu(Menu menu) {
              getMenuInflater().inflate(R.menu.main, menu);
              return true;
          }
      
      
          public Bitmap getImage (int id, int width, int height) {
              Bitmap bmp = BitmapFactory.decodeResource( getResources(), id );
              Bitmap img = Bitmap.createScaledBitmap( bmp, width, height, true );
              bmp.recycle();
              return img;
          }
      }
      

      还有图像按钮:

      <ImageButton
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:id="@+id/imageButton" />
      

      【讨论】:

      • 使用 getRealSize 代替 getSize。文档说“这个值不应该用于计算布局,因为设备通常会在显示器边缘有屏幕装饰(例如状态栏),这会减少此处返回的大小可用的应用程序空间量。布局应改为使用窗口大小。”
      【解决方案7】:

      这并不能准确回答您的问题。但是,如果您只是在寻找通用图标,请查看 t IconicDroid library 它对我有很大帮助。您将能够根据需要调整图标的大小而无需查看质量,并且还可以节省大量空间,因此 apk 会更小。 google Play 上有这个库的演示。

      【讨论】:

        【解决方案8】:

        假设您为不同的屏幕尺寸设置了 10% 的 imageButotn 宽度 32 (320x480) mdpi 48 (480x800|854) hdpi 64 for(640x1024 (galaxy tab 7")) large-hdpi 72 for (720x1280 (nexus 7)) large-tvdipi 72 for(720x1280(xperia sp 等)xhdpi 80 for(800x1280 (motorola xoom 10") xlarge-mdpi 108 for(1080x1920(xperia z 等)xxhdpi 所以你制作所有这些尺寸的图像并将它们放在它们应该的文件夹中。

        【讨论】:

        • 这一切听起来都不错,除了“在他们应该在的文件夹中”的部分......你能告诉我这些文件夹的名称吗?
        • drawable-mdpi、drawable-hdpi、drawable-xhdpi、drawable-xxhdpi、drawable-large-hdpi、drawable-large-tvdpi 和 drawable-xlarge-mdpi.. 抱歉回复晚了.. .
        猜你喜欢
        • 2018-06-11
        • 1970-01-01
        • 1970-01-01
        • 2015-04-14
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        • 2016-12-19
        • 1970-01-01
        相关资源
        最近更新 更多