文本大小和不同的安卓屏幕尺寸

131

我知道这个问题已经讨论了1000次,但我无法调整不同屏幕大小的文本大小。我尝试在我的自定义样式中使用“sp”作为大小单位:

<style name="CustumButtonStyle" parent="@android:style/Widget.Button">
    ...
    <item name="android:textSize">30sp</item>
    ...
</style>

在2.7英寸QVGA屏幕上看起来还可以:

2.7QVGA 30sp

但在7英寸WSVGA屏幕上看起来像这样:

7in WSVGA 30sp

我尝试使用同样的结果,无论是'sp'还是'dp'。

请问如何使得这些按钮在任何屏幕上看起来都一样?

完整的自定义按钮样式

<style name="CustumButtonStyle" parent="@android:style/Widget.Button">
    <item name="android:background">@drawable/custom_button</item>
    <item name="android:layout_width">fill_parent</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:layout_margin">3dp</item>
    <item name="android:textColor">#ffffff</item>
    <item name="android:gravity">center</item>
    <item name="android:textSize">30sp</item>
    <item name="android:textStyle">bold</item>
    <item name="android:shadowColor">#000000</item>
    <item name="android:shadowDx">1</item>
    <item name="android:shadowDy">1</item>
    <item name="android:shadowRadius">2</item>
</style>

而在我的应用主题中,我有以下内容:

<item name="android:buttonStyle">@style/CustumButtonStyle</item>

这是我的布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/RelativeLayout1"
android:layout_width="fill_parent"
android:background="@drawable/grid"
android:gravity="center"
android:orientation="vertical" android:layout_height="fill_parent">

<Button
    android:id="@+id/buttonContinue"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_gravity="center"
    android:gravity="center"
    android:text="@string/continue_game" android:layout_marginTop="3dp" android:layout_marginBottom="3dp"/>



<Button
    android:id="@+id/buttonNewGame"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/buttonContinue"
    android:layout_alignRight="@+id/buttonContinue"
    android:layout_below="@+id/buttonContinue"
    android:layout_gravity="center"
    android:gravity="center"
    android:text="@string/new_game" android:layout_marginTop="3dp" android:layout_marginBottom="3dp"/>



<Button
    android:id="@+id/ButtonAbout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/buttonNewGame"
    android:layout_alignRight="@+id/buttonNewGame"
    android:layout_below="@+id/buttonNewGame"
    android:layout_gravity="center"
    android:gravity="center"
    android:text="@string/about" android:layout_marginTop="3dp" android:layout_marginBottom="3dp"/>


在您的屏幕上,它们看起来相同。请确保您的查看器缩放比例为100%。 - Dmitry Zaytsev
你可以在这里找到答案:https://dev59.com/K2Qn5IYBdhLWcg3wmILY#16910589 - Bhavesh Jethani
12个回答

172

@forcelain 我认为你需要检查这个Google IO设计PDF。在该PDF中,转到第77页,您将找到如何建议使用dimens.xml来针对Android的不同设备的示例。请参见以下结构:

res/values/dimens.xml

res/values-small/dimens.xml

res/values-normal/dimens.xml

res/values-large/dimens.xml

res/values-xlarge/dimens.xml

例如,您在values文件夹中使用了以下dimens.xml。

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <dimen name="text_size">18sp</dimen>
</resources>

在其他的值文件夹中,您需要更改文本大小的值。

注意: 如@espinchi所示,在Android 3.2中,small、normal、large和xlarge已经被弃用,换成了以下内容:

声明Android 3.2平板电脑布局

对于第一代运行 Android 3.0 的平板电脑,声明平板电脑布局的正确方法是将它们放在带有 xlarge 配置限定符的目录中(例如,res/layout-xlarge/)。为了适应其他类型的平板电脑和屏幕尺寸,特别是7英寸的平板电脑,Android 3.2 引入了一种基于布局所需空间量(例如 600dp 宽)而不是试图使布局适合广义大小组(例如大或xlarge)的新技术,从而允许您根据实际可用于应用程序布局的宽度和/或高度指定布局资源。新的配置限定符提供了更多控制您的应用程序支持的特定屏幕大小的选项。注意,使用这些新大小 API 所使用的所有数字都是密度无关像素(dp)值,并且始终应该使用 dp 单位来定义布局尺寸,因为您关心的是系统考虑屏幕密度后实际可用的屏幕空间(而不是使用原始像素分辨率)。要了解有关密度无关像素的更多信息,请参阅本文档中前面的“术语和概念”部分。新的界面配置限定符包括最小宽度(smallestWidth) (swdp)。

示例:sw600dp sw720dp

屏幕的基本尺寸,由可用屏幕区域的最短维度表示。具体来说,设备的smallestWidth是屏幕可用高度和宽度中的最小值(您也可以认为它是屏幕的“最小可能宽度”)。您可以使用此限定符,以确保无论屏幕的当前方向如何,应用程序都具有至少一定宽度的dps可用于其UI。

例如,如果您的布局要求其屏幕区域的最小维度始终为至少600 dp,则可以使用此限定符创建布局资源res/layout-sw600dp/。系统仅在可用屏幕的最小维度至少为600dp时才会使用这些资源,而不管600dp侧是用户感知的高度还是宽度。smallestWidth是设备的固定屏幕大小特性;设备的smallestWidth在屏幕方向更改时不会更改。

设备的smallestWidth考虑了屏幕装饰和系统UI。例如,如果设备上有一些固定的UI元素显示在沿着smallestWidth轴的屏幕上,占据了一些空间,则系统将声明smallestWidth比实际屏幕大小小,因为这些是不可用于您的UI的屏幕像素。

这是通用屏幕大小限定符(small、normal、large、xlarge)的替代方案,允许您为可用于UI的有效尺寸定义离散数字。使用smallestWidth来确定一般的屏幕大小非常有用,因为宽度通常是设计布局时的关键因素。一个UI经常会垂直滚动,但在水平上具有相当硬性的约束条件。可用的宽度也是确定何时使用单窗格布局(适用于手持设备)或多窗格布局(适用于平板电脑)的关键因素。因此,您可能最关心每个设备上最小可能的宽度。可用屏幕宽度wdp

示例:w720dp w1024dp

指定以dp单位表示的应使用资源的最小可用宽度-由值定义。当屏幕的方向在横向和纵向之间切换以反映可用于您的UI的当前实际宽度时,系统对应的宽度值也会更改。

这通常很有用,可以确定是否使用多窗格布局,因为即使在平板设备上,您通常也不希望在纵向方向和横向方向上都使用相同的多窗格布局。因此,您可以使用此选项指定布局所需的最小宽度,而不是同时使用屏幕大小和方向限定符。可用屏幕高度hdp

示例:h720dp h1024dp等。

指定以dp为单位的最小屏幕高度,该资源应在其上使用-由值定义。当屏幕方向在横向和纵向之间切换以反映可用于UI的当前实际高度时,系统对应的高度值也会更改。

将其用于定义布局所需的高度与使用屏幕大小和方向限定符相比具有相同的有用性,但大多数应用程序不需要此限定符,考虑到UI通常在垂直方向上滚动,因此对可用高度的灵活性更强,而宽度则更为严格。

虽然使用这些限定符可能比使用屏幕大小组看起来更复杂,但一旦确定了UI的要求,实际上应该更简单。设计UI时,您可能最关心的是应用程序在何时从手机式UI切换为使用多个窗格的平板式UI。这种转变的确切点取决于您的特定设计-也许您需要720dp宽度来布置平板电脑界面,也许600dp足够,或者480dp,或者介于这些数字之间。使用表2中的这些限定符,您可以控制布局更改的精确大小。

有关这些大小配置限定符的更多讨论,请参见提供资源文档。配置示例。

为了帮助您针对不同类型的设备定位某些设计,这里是一些典型屏幕宽度的数字:

320dp: a typical phone screen (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc).
480dp: a tweener tablet like the Streak (480x800 mdpi).
600dp: a 7” tablet (600x1024 mdpi).
720dp: a 10” tablet (720x1280 mdpi, 800x1280 mdpi, etc).

通过表2中的尺寸限定符,您的应用程序可以使用任意宽度和/或高度号码在手机和平板电脑之间切换不同的布局资源。例如,如果600dp是平板电脑布局支持的最小可用宽度,则可以提供以下两组布局:

res/layout/main_activity.xml # 用于手机 res/layout-sw600dp/main_activity.xml # 用于平板电脑

在这种情况下,可用屏幕空间的最小宽度必须为600dp才能应用平板电脑布局。

对于其他需要进一步自定义界面以区分大小(如7英寸和10英寸平板电脑)的情况,可以定义更多的最小宽度布局:

res/layout/main_activity.xml # 用于手机(可用宽度小于600dp) res/layout-sw600dp/main_activity.xml # 用于7英寸平板电脑(宽度为600dp或更大) res/layout-sw720dp/main_activity.xml # 用于10英寸平板电脑(宽度为720dp或更大)

注意,前两个示例资源集使用“最小宽度”限定符swdp,该限定符指定屏幕的两个边缘中最小的一个,而不考虑设备的当前方向。因此,使用swdp是一种通过忽略屏幕方向来指定布局可用的整体屏幕尺寸的简单方法。

但是,在某些情况下,对于您的布局来说,确切的宽度或高度可能非常重要。例如,如果您具有两个并排的片段的双窗格布局,您可能希望在设备提供至少600dp宽度时使用它,无论设备处于横向还是纵向方向。在这种情况下,您的资源可能如下所示:

res/layout/main_activity.xml # 用于手机(可用宽度小于600dp) res/layout-w600dp/main_activity.xml # 多窗格布局(任何可用宽度为600dp或更多的屏幕)

请注意,第二个集合使用“可用宽度”限定符wdp。这样,一个设备实际上可能会同时使用两种布局,具体取决于屏幕的方向(如果一个方向的可用宽度至少为600dp,而另一个方向的可用宽度小于600dp)。

如果可用高度对您很重要,则可以使用hdp限定符执行相同操作。或者,如果需要非常具体,则可以组合wdp和hdp限定符。


7
目前(2014年12月)这些 small/normal/large/xlarge 已经被弃用。现在推荐的方法是使用“swxxxdp”。请参见http://developer.android.com/guide/practices/screens_support.html#range - espinchi
1
@espinchi 谢谢,你应该把这个也发表为一个答案。还有推荐的 dp 吗?例如标准是:100sw、200sw、400sw、600sw。 - Vince V.

24

我认为在这个帖子上回复已经太晚了。但是我想分享一下我的想法或方法来解决不同分辨率设备上的文本大小问题。许多Android开发者网站建议我们使用 sp 单位来处理不同分辨率设备的文本大小。但是我总是无法得到期望的结果。因此,我找到了一个解决方案,我在过去的4-5个项目中使用它,而且效果很好。根据我的建议,您必须为每个分辨率设备设置文本大小,这是有点繁琐的工作,但它将满足您的要求。每个开发人员都必须听说过比率,例如 4:6:8:12(分别表示hdpi:xhdpi:xxhdpi:xxxhdpi)。现在,在您的项目 res 文件夹中,您必须创建4个带有dimens文件的文件夹,例如:

  1. res/values-hdpi/dimens.xml
  2. res/values-xhdpi/dimens.xml
  3. res/values-xxhdpi/dimens.xml
  4. res/values-xxxhdpi/dimens.xml

现在,在dimens.xml文件中,您必须放置文本大小。我正在为values-hdpi显示代码,类似地,您必须为其他分辨率值/ dimens.xml文件放置代码。

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <dimen name="text_size">4px</dimen>
</resources>

对于其他分辨率,比如xhdpi:6px,xxhdpi:8px,xxxhdpi:12px。这是根据我上面写的比例(3:4:6:8:12)计算出来的。让我们使用上述比例来讨论其他文字大小的示例。如果你想在hdpi中使用12px的字体大小,在其他分辨率下应该是:

  1. hdpi:12px
  2. xhdpi:18px
  3. xxhdpi:24px
  4. xxxhdpi:36px

这是实现所有分辨率所需文字大小的简单解决方案。我没有考虑values-mdpi分辨率设备。如果有人想包括这个分辨率的文字大小,则比例为3:4:6:8:12。如果有任何疑问,请告诉我。希望能帮助到你们。


4
在文本大小上使用px而不是sp是不好的惯例吗?是否有一种方法可以使用sp实现以下比例? - Red M
我检查了这个程序,一切正常,但我仍然困惑,使用px而不是dp/sp作为值是一个好习惯吗? 我从官方文档中没有看到过使用px值的说明。 - shaby
1
使用sp作为字体大小,这是规定。Rahul展示的方法是正确的,只需要使用sp代替px即可。 - Mihir Patel
如果计划将应用程序字体大小与系统字体大小链接,则应使用sp。否则,此解决方案还不错。 - Irfan Ul Haq
@Rahul Sharma,我已经使用了sp而不是px,并且使用了您提到的比例,它们运行良好,谢谢! - mvsagar

15

有时候,只有三个选项才是最好的

 style="@android:style/TextAppearance.Small"

使用“小”和“大”来区分普通屏幕尺寸。

<TextView
            android:id="@+id/TextViewTopBarTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            style="@android:style/TextAppearance.Small"/>

对于普通情况,您无需指定任何内容。

<TextView
            android:id="@+id/TextViewTopBarTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

使用此功能,您可以避免测试和指定不同屏幕尺寸的尺寸。


11

大家都可以使用以下提到的Android库,这是最简单的方法使文本大小与几乎所有设备屏幕兼容。它实际上是基于新的Android 3.2中引入的屏幕尺寸配置限定符SmallestWidth swdp开发的。

https://github.com/intuit/sdp


3
sdp 用于屏幕尺寸;使用 ssp 来调整文本大小。 - ecle
这对我来说可行,但我怀疑要添加的文件太多了,这会增加应用程序的大小。@Muhammad,你可以调整大小并仅添加所需的类。 - Kirtikumar A.
1
看起来这个库已经不再维护了。 - Luciano Brum
@KirtikumarA。经过我的测试,这些添加的文件对应用程序大小的增加可以忽略不计。 - Adam Johns
@AdamJohns 你只能添加你想要保存大小的文件。 - Kirtikumar A.

10

我用维度相同的方法,并且画了一些东西(使用 dp,但仅适用于文本并在 drawText() 中)

XML:

   <dimen name="text_size">30sp</dimen>

代码:

   Paint p =new Paint();
       p.setTextSize(getResources().getDimension(R.dimen.text_Size));

9
应该使用 sp 而不是 dp 来设置文字大小。 - Yousha Aleayoub
please use sp for text size - Thinsky
在特定情况下,当您不希望dp根据用户偏好进行调整大小时,可以使用它。 - user5832543

2

我知道现在有点晚了,但是这可能会对某些人有所帮助...

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:autoSizeTextType="uniform"
        android:gravity="center_horizontal|bottom"
        android:text="Your text goes here!"
        android:layout_centerInParent="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent="0.05"
        app:layout_constraintHorizontal_bias="0.50"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.50"
        app:layout_constraintWidth_percent="0.50" />
</androidx.constraintlayout.widget.ConstraintLayout>

此外,如果您想调整文本大小,请尝试更改。
app:layout_constraintWidth_percent="0.50" 
app:layout_constraintHeight_percent="0.05"

这就是全部。


1

1
问题在于它不能统一更改具有不同长度字符串的多个文本视图的文本大小。 - Sourabh

1
为了使所有屏幕显示相同的元素大小,包括字体大小: - 在一个屏幕大小上设计UI,并在设计过程中使用适当的大小,例如在默认屏幕大小为4'6英寸时,TextView字体大小为14dp。
  • 以编程方式计算其他手机/屏幕的物理屏幕大小,例如5'2英寸。

  • 使用公式计算两个屏幕之间的百分比差异,例如4'6和5'2之间的%差异。

  • 根据上述公式计算出两个TextView之间的像素差异。

  • 获取TextView字体大小的实际大小(以像素为单位),并将先前计算的像素差异应用于默认字体大小。

通过这种方式,您可以将动态纵横比应用于所有屏幕尺寸,效果非常好。您将在每个屏幕上拥有相同的布局和大小。

起初可能有点棘手,但一旦找到公式,就可以完全实现目标。使用此方法,您无需制作多个布局来适应不同的屏幕尺寸。


1
我不建议这样做,以英寸为单位计算屏幕尺寸非常不可靠。 - Zui0per
@Zui0per - 我已经在我的应用程序中实现了这种方法,并且在所有屏幕尺寸上看起来都很好。除非您不想要这样,否则您将在所有屏幕上拥有相同大小的UI元素,否则您应该为不同的屏幕使用不同的布局。 - Desolator
我已经尝试过了,文本大小的计算并不能正常工作。(https://www.codepile.net/pile/AX46avDn) 也许你可以快速看一下? :) 然而,以英寸为单位计算屏幕大小非常不可靠。由于xdpi和ydpi的不一致性,在某些设备上我会得到奇怪的值。此外,如果用户更改了设备分辨率,文本大小也会发生变化。 - Zui0per
@Zui0per - 当你编写公式时,你总是可以考虑到这一点。始终有一种更好的方法来增强这种方法,并且总会有一些需要考虑的特殊情况。我基本上是为了给出一个开始的想法而陈述了它。 - Desolator

0

你也可以使用weightSumlayout_weight属性来调整不同屏幕的布局。

为此,您需要将android:layout_width设置为0dp, 并将android:layout_width设置为(您想要的任何值);


0

我认为你可以通过为每个屏幕尺寸添加多个布局资源来实现这一点,例如:

res/layout/my_layout.xml             // layout for normal screen size ("default")
res/layout-small/my_layout.xml       // layout for small screen size with small text
res/layout-large/my_layout.xml       // layout for large screen size with larger text
res/layout-xlarge/my_layout.xml      // layout for extra large screen size with even larger text
res/layout-xlarge-land/my_layout.xml // layout for extra large in landscape orientation

Reference: 1.http://developer.android.com/guide/practices/screens_support.html


2
使用res/values-small可能更好。 - einverne
1
最糟糕的实现之一。我们要维护5个布局来支持不同的尺寸? - Desolator
在不同的屏幕上创建不同的布局,仅仅为了减小文本大小,这是一个非常糟糕的想法。我不建议这样做。 - Saman Salehi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接