启动画面使用全屏拉伸的向量图形

52

我用这个教程做了我的启动画面,效果很好:

基本上,我是通过主题设置了一个启动画面:

<style name="ThemeSplash" parent="Theme.AppCompat.NoActionBar">
    <item name="android:windowBackground">@drawable/drawable_splashcreen</item>
</style>

我想把一个向量图像放在里面,就像这样:(drawable_splashcreen)

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/color_background_splash_screen" />
    <item android:drawable="@drawable/vector_najdiflet_logo" />
</layer-list>
图像将会占满整个屏幕。在API 23上,它能正常工作。但是在旧设备上,图像只会被拉伸。我尝试了宽度、高度,甚至玩弄了视口,但都没有成功。

图片将会被拉伸至全屏显示,API 23以上版本可以正常工作,但在老版本设备上只会被拉伸。我已经尝试使用宽度、高度以及视口的设置,但均未成功。


1
尝试在项目标签中设置所需的宽度和高度。 - MrOnyszko
1
已经尝试过了,但在旧设备上无法运行。 - WinterChilly
查看矢量图形内部。那里有一个宽度和高度属性。在任何特定屏幕上显示之前,将以该尺寸呈现矢量图形为位图。问题是:您无法指定任何值表示“与屏幕一样大”。因此,对于小屏幕的任何值,尽管它最初是矢量图形,但在平板电脑上看起来会模糊不清。 - Marcus Wolschon
你好,我现在也遇到了同样的问题,你找到解决方案了吗? - Viktor Sinelnikov
7个回答

41

我遇到了同样的问题。 不幸的是,在API 23之前,似乎没有办法只使用矢量图形来使启动画面正常工作。

问题在于,不能在进程外部加载VectorDrawableCompat,例如在您的主题android:windowBackground中。所以在这种情况下,可能发生的情况是,在API 21上,矢量图被转换为PNG以实现兼容性。 因此,在<layered-list>中,转换后的PNG被插入到<item>元素中,导致位图向所有边缘拉伸,因为它缺少<bitmap>元素。

因此我的解决方案如下:在文件夹drawables-v23中创建一个名为drawable_splashscreen.xml的文件,其内容如下所示:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" 
android:opacity="opaque">
    <item android:drawable="?attr/colorPrimary"/>
    <item android:drawable="@drawable/ic_splashscreen" android:gravity="center"/>
</layer-list>

然后在常规的drawables文件夹内创建另一个drawable_splashscreen.xml

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

注意<bitmap>元素。因此,在预API 23的设备上使用PNG时,它将被正确显示,并且不会被拉伸到整个背景。

不幸的是,你还必须为旧API提供PNG格式的启动画面才能使其正常工作。

但对于每个API 23+的设备,将使用矢量可绘制对象。


你的代码不是反过来了吗?第二个应该放在drawable-v23里,而第一个则应该放在drawable和drawable-v24文件夹中,这样对我来说就可以了。 - quealegriamasalegre

12

要实现全屏闪屏,请尝试使用:

android:gravity="fill_horizontal|fill_vertical"

如果无法解决,也许解决方案是为每个分辨率大小创建单独的图像。

最常见的分辨率:

  • Small = 240 x 320px (ldpi)
  • Medium = 320 x 480px (mdpi)
  • Large = 480 x 800px (hdpi)
  • xLarge = 640 x 960px (xhdpi)

纵向格式:

  • ldpi = 240 x 360px (0.75 x mdpi)
  • mdpi = 320 x 480px (基准密度)
  • hdpi = 480 x 720px (1.5 x mdpi)
  • xhdpi = 640 x 960px (2 x mdpi)
  • xxhdpi = 960 x 1440px (3 x mdpi)
  • xxxhdpi = 1080 x 1920px (4 x mdpi)

横向格式 (倒置的纵向格式):

ldpi = 360 x 240像素 (0.75倍 mdpi) mdpi = 480 x 320像素 (基础密度) hdpi = 720 x 480像素 (1.5倍 mdpi) xhdpi = 960 x 640像素 (2倍 mdpi) xxhdpi = 1440 x 960像素 (3倍 mdpi) xxxhdpi = 1920 x 1080像素 (4倍 mdpi)

更多关于您的信息可以在这里找到:

  1. https://design.google.com/devices/(链接1)

  2. 适合所有设备的Android启动画面图片尺寸(链接2)

  3. 来自开发者的设计师技巧(链接3)


我希望Logo保持原始尺寸,但它只是在全屏幕中拉伸。这不是期望的效果。 - WinterChilly
WinterChilly,你可以尝试创建一个与你的设备分辨率完全相同的新图像,并将标志放置在中心位置,而不改变其原始大小。图像的背景可以是白色或黑色,作为放置在中心的标志的基础。有了正确分辨率的图像和原始标志位于中心,也许你可以获得所需的效果。祝你好运! - ℛɑƒæĿᴿᴹᴿ

5

编辑后的解决方案,可以让您的启动屏在包括API21到API23在内的所有API上看起来很棒

首先阅读此文,并遵循良好的启动屏制作方式。

如果您的Logo变形或无法适应,并且您只针对API24+进行目标定位,则可以直接在其XML文件中缩小矢量图形,方法如下:

<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
android:viewportWidth="640"
android:viewportHeight="640"
android:width="240dp"
android:height="240dp">
<path
    android:pathData="M320.96 55.9L477.14 345L161.67 345L320.96 55.9Z"
    android:strokeColor="#292929"
    android:strokeWidth="24" />
</vector>

在上面的代码中,我正在将我在 640x640 画布上绘制的可绘制对象重新缩放为 240x240。然后,我只需像这样将其放入我的闪屏可绘制对象中,它就能正常工作:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque"
android:paddingBottom="20dp" android:paddingRight="20dp" android:paddingLeft="20dp" android:paddingTop="20dp">

<!-- The background color, preferably the same as your normal theme -->
<item>
    <shape>
        <size android:height="120dp" android:width="120dp"/>
        <solid android:color="@android:color/white"/>
    </shape>
</item>

<!-- Your product logo - 144dp color version of your app icon -->
<item
    android:drawable="@drawable/logo_vect"
    android:gravity="center">

</item>
</layer-list>

我的代码实际上只在底部的图片中绘制三角形,但你可以看到用它可以实现什么。分辨率最终很棒,与使用位图时得到的像素化边缘相反。所以一定要使用矢量可绘制(有一个名为Vectr的网站,我用它创建自己的文件而不必下载专业软件)。

编辑以使其在API21-22-23上也能正常工作

虽然上面的解决方案适用于运行API24+的设备,但在安装了我的应用程序后,在运行API22的设备上,我感到非常失望。我注意到启动画面再次尝试填充整个视图并看起来很糟糕。在折磨了半天后,我终于通过纯粹的毅力 brute-forced 找到了解决方案。

你需要创建第二个文件,命名为和启动画面xml完全相同(比如说splash_screen.xml),并将其放置在两个文件夹中,这两个文件夹称为 drawable-v22 和 drawable-v21,你需要在 res/ 文件夹中创建它们(为了查看它们,你需要将项目视图从 Android 更改为 Project)。这是为了告诉手机在相关设备运行与 drawable 文件夹中的-vXX 后缀对应的API时,将重定向到放置在这些文件夹中的文件,请参见此链接。 将以下代码放入在 splash_screen.xml 文件的 Layer-list 中,你需要在这些文件夹中创建它:

<item>
<shape>
    <size android:height="120dp" android:width="120dp"/>
    <solid android:color="@android:color/white"/>
</shape>
</item>

<!-- Your product logo - 144dp color version of your app icon -->
<item android:gravity="center">
    <bitmap android:gravity="center"
        android:src="logo_vect"/>

</item>

这是文件夹的外观

由于某些API的原因,您必须将可绘制对象包装在位图中才能使其正常工作,最终结果看起来相同。问题在于,您必须使用额外的drawable文件夹的方法,因为第二个版本的splash_screen.xml文件会导致在运行API大于23的设备上根本不显示闪屏。您还可能需要将第一个版本的splash_screen.xml放入drawable-v24中,因为Android会默认使用它可以找到的最接近的drawable-vXX文件夹来查找资源。

我的启动画面


2

我认为对于API 23以下的设备,使用向量图标来实现这一需求是不可能的,因为在drawable上无法设置android:height和android:width属性。

为了实现我的启动屏幕并使其中的图标居中,我不得不将我的标志的向量文件导出到每个屏幕尺寸的 .png 文件中,并在layer-list中嵌入一个位图:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:opacity="opaque">
    <item android:drawable="@drawable/splash_screen_background" />

    <item
        android:left="20dp"
        android:right="20dp">
        <bitmap
            android:gravity="center"
            android:scaleType="centerInside"
            android:src="@drawable/logo_rasterised" />
    </item>

</layer-list>

理想情况下,我不希望在我的资源中使用任何位图图像,但至少启动画面是我必须使用位图的唯一地方。


1
android:scaleType 不适用于 <bitmap>,可能会被静默忽略(它只能与 ImageView 一起使用)。 - mikep

0

我发现解决这个问题最简单的方法是使用矢量图像。这将确保apk大小也不会太大。如果您没有为您的标志文件提供SVG文件,或者没有使用此方法,请手动更改图片的DP强度并手动添加它们。您还可以使用自动执行此操作的插件。

如果您选择使用矢量文件,但仍然出现缩放图像的情况,请添加android:top、left、right和bottom以使您的标志大小正确。


0
使用位图并在src中定义您的图像。将重力设置为居中。
    <?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:opacity="opaque">

    <item android:drawable="@color/color_background_splash_screen"/>
    <item>
        <bitmap
            android:gravity="center"
            android:src="@drawable/ic_logo_splash"/>
    </item>
</layer-list>

splash screen


4
不适用于矢量图,因为矢量图不是位图。 - Softlion
5
OP明确要求使用矢量图形:“我想把一个矢量图像放在里面,就像这样。” - Geek Stocks

-4
不要将您的图像放在window:Background中,而是将其作为SplashScreenActivity布局的imageview的android:src添加。

4
不想创建另一个活动。在这里查看文章... https://www.bignerdranch.com/blog/splash-screens-the-right-way/图片/可绘制项可以使用,但矢量图像不行。 - Harshit Choudhary

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