【问题标题】:Android splash screen without logo distortionAndroid 闪屏,无 logo 失真
【发布时间】:2017-07-28 17:21:38
【问题描述】:

是否可以创建一个带有徽标的启动画面,该徽标保持其纵横比,而背景图像可以独立调整大小?我目前正在为不同的分辨率使用几个 .png 文件,它们在大多数设备上看起来都很棒。但是,有几部手机严重扭曲了我的徽标(即三星 S8,具有移动垂直屏幕空间)。

我可以处理我的初始屏幕背景的一些失真,但窄/压扁的徽标是不可接受的。有谁知道如何做到这一点?对于新布局,矢量可绘制徽标会比 .png 更好吗?

【问题讨论】:

  • 你的图片(imageview)是否有 wrap_content 的体重和身高?
  • 不,是 match_parent。
  • 如果我理解,你有一个背景图像,然后在它上面有一个图像。并且图像(您的图标)在某些设备上失真?
  • 我发布了答案

标签: android android-layout android-imageview


【解决方案1】:

在 layout.xml 中渲染启动视图而不是作为主题背景(就像这里推荐的其他答案一样)需要更长的时间来加载。这是因为首先加载了应用程序的主题,然后构造了 Activity,最后膨胀了布局。由于启动画面的目的是在应用程序加载时显示某些内容,因此加载启动画面本身有约 0.5 秒的延迟会导致明显的延迟。将启动画面加载为主题 windowBackground 效果更好(在点击启动器图标后几乎立即呈现),但有一些限制要解决。您当前根据屏幕宽度定义多个徽标大小的方法是处理这种情况的正确方法。这是一个示例配置,用于处理 Android v21 前后的差异:

值/主题.xml:

<style name="SplashThemeCommon" parent="Theme.AppCompat.NoActionBar">
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowBackground">@drawable/splash_logo_theme</item>
</style>

<style name="SplashTheme" parent="SplashThemeCommon">
    <item name="android:windowFullscreen">true</item>
</style>

values-v21/themes.xml:

<style name="SplashTheme" parent="SplashThemeCommon">
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
</style>

可绘制/splash_logo_theme.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <bitmap
            android:gravity="center"
            android:src="@drawable/splash_logo"/>
    </item>
</layer-list>

接下来,您可以为不同的屏幕配置添加一份“splash_logo.png”副本。你有几个合理的选择。详尽的方法可能包括针对每种屏幕尺寸的不同徽标:

  • drawable-sw320dp-xxxhdpi/splash_logo.png
  • drawable-sw400dp-xxxhdpi/splash_logo.png
  • drawable-sw480dp-xxxhdpi/splash_logo.png
  • drawable-sw600dp-xxxhdpi/splash_logo.png
  • drawable-sw720dp-xxxhdpi/splash_logo.png
  • drawable-sw820dp-xxxhdpi/splash_logo.png

“swXXXdp”表示 XXX 是 dp 中最小的屏幕尺寸(宽度或高度)。 820dp 将是一个巨大的平板电脑,320dp 将是一个旧的小型设备,而今天大多数旗舰设备将属于 400dp 类别。 450dp 宽的设备将使用 400dp 图像。

我为什么要在这里定义 xxxhdpi?因为如果您不指定,Android 将假定它是 mdpi 图像并尝试为更高 dpi 的设备(当今大多数旗舰手机是 xxhdpi)进行升级/调整大小。这种放大将导致您的图像变得块状,并且比原始图像大。通过在此处指定 xxxhdpi,Android 将仅尝试缩小图像以确保图像永远不会出现块状;这是一种优化,所以我们也不需要为 ldpi、mdpi、hdpi、xhdpi 等定义单独的图像。

在 APK 中有 6 张图片有点浪费。我们可以进一步优化这种方法,以便在应用程序中包含更少的图像并确保更小的 APK 大小。相反,我们只包含以下两个图像:

  • drawable-sw600dp-xxxhdpi/splash_logo.png
  • drawable-xxxhdpi/splash_logo.png

任何 600dp 及更大尺寸的设备(平板电脑)都具有更大的图像副本以利用更大的屏幕空间,而所有其他手机都使用位于垃圾箱中的较小副本,没有屏幕宽度限定符。这里的缺点是,由于每个 bin 覆盖的屏幕宽度范围如此之大,因此 4" 设备上的徽标将占据比 6" 设备更大的屏幕部分。这是减小 APK 大小的折衷方案,只要图像从不被截断,即使在最小的设备上,大多数用户也不会注意到。

那么我们应该包含多大尺寸的 png 呢?它们需要具有特定大小才能在主题中显示,因为与 layout.xml 不同,我们无法在 XML 中指定宽度/高度(仅在 API 23 中添加了可绘制宽度/高度支持)。这意味着如果您包含非最佳 png 大小,它会显得太小或两个大;如果它太大,它实际上会被切断。获得合适尺寸的一个好计划是:

  • 创建一个 layout/test.xml 文件,其中只有默认的 LinearLayout,没有可见的内容
  • 在 Android Studio 中打开它并选择布局编辑器左下角的“设计”选项卡
  • 在布局编辑器的顶部栏中将主题更改为 SplashTheme
  • 将设备更改为“Pixel XL”
  • 在 drawable-sw400dp/splash_logo.png 下放置一张图片
  • 在 Photoshop 或 Gimp 等外部图像编辑器中打开图像,更改大小,保存,然后在 Android Studio 中检查布局(您可能需要关闭并重新打开编辑器才能使更改生效)。重复,直到图像在布局中看起来正确的大小
  • 按比例生成其他屏幕宽度的图像;例如,sw320dp 图像应为 400dp 图像大小的 320/400 或 67%,而 720dp 图像应为 400dp 图像大小的 720/400 或 180%。请记住不要将 400dp 图像放大到更大的图像,因为这样会降低质量。相反,请根据您的高质量原始副本生成所有图像
  • 将生成的图像放置在上面指定的不同可绘制目录中
  • 在布局编辑器中选择不同屏幕尺寸的设备(包括平板电脑),并确保它们的徽标足够大,但不会被截断,适用于所有屏幕尺寸

你怎么知道哪个设备屏幕分辨率属于哪个swXXXdp类别?这需要一个简单的计算。让我们看看 Pixel XL:

  • 屏幕尺寸为1440x2560
  • 因此最小的维度是 1440
  • 屏幕dpi为534
  • 以英寸为单位的屏幕宽度为 1440/534=2.69"
  • 打开网站:http://angrytools.com/android/pixelcalc/
  • 在英寸(“in”)框中输入 2.69
  • 左侧的绿色框之一将显示 dp,在本例中为 431
  • 对于 431 dp 宽的屏幕,如果您有全部 6 个图像类别,Pixel XL 将使用 drawable-sw400dp/splash_logo.png 图像,如果您只有两个图像类别,则使用 drawable-xxxhdpi/splash_logo.png 图像

【讨论】:

  • 很好的解释。谢谢
  • 是否有一个模板来说明每个文件夹中需要放置的图像大小
  • 2021 这不再起作用了。 Android Drawable 文件夹结构发生了变化
【解决方案2】:

如果您的初始屏幕只有纵向图像,这里有一个解决方案,它是纵向全屏,在edit: 上居中但不裁剪 肖像风景:

splash_screen.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layoutSplash"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/splash_screen_background">

    <ImageView
        android:contentDescription="@string/splash_screen_description"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        style="@style/SplashScreen" />

</LinearLayout>

值/样式.xml

<style name="SplashScreen">
    <item name="android:src">@drawable/splash</item>
    <item name="android:adjustViewBounds">true</item>
    <item name="android:scaleType">fitCenter</item>
</style>

值端口/styles.xml

<style name="SplashScreen">
    <item name="android:src">@drawable/splash</item>
    <item name="android:adjustViewBounds">true</item>
    <item name="android:scaleType">centerCrop</item>
</style>

【讨论】:

  • 如何在活动创建/启动之前通过启动画面实现这一点?您不能使用布局文件。对于徽标,我会在主题中设置&lt;item name="android:windowBackground"&gt;@drawable/splashscreen&lt;/item&gt;
  • 我只使用活动创建了启动画面。这可能是一个新的 StackOverflow 问题。
  • 您应该使用windowBackground 作为初始屏幕。使用您的解决方案,您仍然可以在活动布局膨胀之前看到白屏。 bignerdranch.com/blog/splash-screens-the-right-way/…
  • 通过将 scaleType 设置为 centerCrop 可以在屏幕上获得完整的图像覆盖。谢谢!
【解决方案3】:

您是否考虑过保持ImageView 的纵横比?这是一个相关的问题,应该为您指明正确的方向:How to scale an Image in ImageView to keep the aspect ratio

【讨论】:

    【解决方案4】:
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/bg"
        android:gravity="center">
    
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/logo"/>
    
    </RelativeLayout>
    

    这样就可以了


    这是一个关系 10

    【讨论】:

    • 您应该使用windowBackground 作为初始屏幕。使用您的解决方案,您仍然可以在活动布局膨胀之前看到白屏。 bignerdranch.com/blog/splash-screens-the-right-way/…
    • @user25 windowBackground 非常愚蠢,我花了几十个小时来解决如何保持图像的纵横比 = 不可能
    【解决方案5】:

    根本不需要使用布局,使用LayeredList,并将其设置为背景。这是一个例子;

    <?xml version="1.0" encoding="utf-8"?> 
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
        <item android:drawable="@color/gray"/> 
        <item> 
            <bitmap android:gravity="center" android:src="@drawable/splash_image"/> 
        </item> 
    </layer-list>
    

    【讨论】:

    • 重心图片不适合屏幕
    • 启动画面没有理由填满屏幕。
    • 我的意思是图片太大了,超出范围
    • @shurrok 所以添加一个低分辨率版本的图像。这是你无论如何都应该做的事情。
    • 是的,当然,我只是想知道对设计师说什么
    【解决方案6】:

    OMG.... 保持简单!!!

    1. 在Android resources/res 文件夹中,创建文件夹“drawable-xxxhdpi”和“drawable-sw600dp

    2. 在“drawable-sw600dp”文件夹中,添加分辨率为4096x4096 像素的“splash_logo.png”。这应该包括平板电脑。

    3. 在“drawable-xxxhdpi”文件夹中,添加另一个分辨率为1440x2560像素的“splash_logo.png”。这应该涵盖智能手机。

    这就是解决所有扭曲的方法!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-25
      • 2023-03-10
      • 2018-07-14
      • 2015-08-10
      • 1970-01-01
      • 1970-01-01
      • 2013-02-28
      相关资源
      最近更新 更多