ChatGPT解决这个技术问题 Extra ChatGPT

如何在不缩放的情况下将可绘制的矢量在图层列表中居中

我试图在 LayerList 中使用 VectorDrawable 而不缩放矢量。例如:

<layer-list>
    <item android:drawable="@color/grid_item_activated"/>
    <item android:gravity="center" android:drawable="@drawable/ic_check_white_48dp"/>
</layer-list>

可绘制的 ic_check_white_48dp id 定义为:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="48dp"
        android:height="48dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#FFFFFFFF"
        android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>

所需的效果是使复选图标位于可绘制图层的中心,而无需缩放。问题是,上面的图层列表导致检查图标被缩放以适合图层大小。

如果我用 PNG 替换每个密度的矢量可绘制对象并修改图层列表,我可以产生所需的效果:

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

有什么方法可以使用 VectorDrawable 做到这一点?

看来这可能只是 API 21/22 中的一个错误。我刚刚在 API 23 设备上进行了测试,并且矢量可绘制对象正确居中。
你应该回答你自己的问题并接受它。这样一来,它就更加明显,并且问题不会显示为未回答。
我还没有回答我的问题,因为我还没有关于在 API 21/22 上做什么的答案。我的临时解决方案是使用 PNG 而不是矢量。希望仍然找到一种方法使向量起作用。
我在这里打开了一个问题:code.google.com/p/android/issues/detail?id=219600
这已经在 API 23 中修复,所以我猜你的错误报告将被标记为已修复。

N
Nicolas Tyler

我在尝试将矢量可绘制对象集中在分层列表上时遇到了同样的问题。

我有一个解决方法,它不完全相同,但它有效,您需要为整个可绘制对象设置大小并为矢量项添加填充:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <size android:height="120dp" android:width="120dp"/>
            <solid android:color="@color/grid_item_activated"/>
        </shape>
    </item>
    <item android:top="24dp"
          android:bottom="24dp"
          android:left="24dp"
          android:right="24dp"
          android:drawable="@drawable/ic_check_white_48dp"/>
</layer-list>

上面形状的大小设置了整个可绘制对象的大小,在本例中为 120dp,第二项上的填充,在本例中为 24dp,使矢量图像居中。

它与使用 gravity="center" 不同,但它在 API 21 和 22 中使用向量的工作方式。


这听起来像是需要您知道可绘制对象的确切大小(以设置形状大小),而不是让它填充设置为的整个空间,并在其中居中检查可绘制对象。
可能不知道大小,但您不能使用此方法更改填充,您可以在图像视图中将可绘制对象分层。如上所述,API 21 和 22 中的 gravity="center" 没有完美的解决方案。
windowBackground 一起使用时不起作用。在这种情况下,显式大小不起作用。如果我将图层列表放在另一个图层列表中,它也不起作用。
F
Felipe Duarte

一直在努力解决同样的问题。我发现解决此问题并避免可绘制放大的唯一方法是设置可绘制大小并使用重力对齐它:

<layer-list>
    <item android:drawable="@color/grid_item_activated"/>
     <item
        android:gravity="center"
        android:width="48dp"
        android:height="48dp"
        android:drawable="@drawable/ic_check_white_48dp"/>
</layer-list>

希望能帮助到你!


这对 API 21-22 没有帮助,因为 width 属性在这些 API 级别上不可用。在 API 23 上,这些是不需要的,因为 bug 已修复,drawable 不再拉伸。
这不适用于 API 27,图像被拉伸到全屏
q
quealegriamasalegre

编辑的解决方案将使您的 SplashScreen 在所有 API(包括 API21 到 API23)上看起来都很棒

首先阅读this文章并按照制作启动画面的好方法。

如果您的徽标变形或不适合并且您仅针对 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 的设备后,我感到非常失望。我注意到启动画面再次试图填满整个视图并且看起来像狗屎。撕了半天的眉毛后,我终于凭借纯粹的意志力强行解决了。

您需要创建第二个文件,其名称与 splashscreen xml 完全相同(比如说 splash_screen.xml),并将其放入您将在 res/ 文件夹中创建的 2 个名为 drawable-v22 和 drawable-v21 的文件夹中(以便您查看它们必须将您的项目视图从 Android 更改为 Project)。每当相关设备运行与可绘制文件夹 see this link 中的 -vXX 后缀相对应的 API 时,这会告诉您的手机重定向到放置在这些文件夹中的文件。将以下代码放在您在这些文件夹中创建的 splash_screen.xml 文件的图层列表中:

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

<!-- The background color, preferably the same as your normal theme -->
<item
    android:gravity="center">
    <shape android:shape="rectangle">
        <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="@drawable/logo_vect"/>

</item>
</layer-list>

https://i.stack.imgur.com/hJPNc.png

由于这些 API 的某些原因,您必须将您的可绘制对象包装在位图中以使其工作并喷射最终结果看起来相同。问题是您必须使用带有附加可绘制文件夹的方法,因为 splash_screen.xml 文件的第二个版本将导致您的启动屏幕在运行 API 高于 23 的设备上根本不显示。您可能还必须放置splash_screen.xml 的第一个版本到 drawable-v24 中,因为 android 默认为它可以找到资源的最近的 drawable-vXX 文件夹。

https://i.stack.imgur.com/sSNX0.png


对于 <bitmap android:src="logo_vect"/>,您似乎建议在 API 级别 21 和 22 上可以使用可绘制矢量作为位图的源。根据我的经验,这总是会导致运行时崩溃:java.lang.RuntimeException: Unable to start activity android.content.res.Resources$NotFoundException: File res/drawable-v21/splash.xml from drawable resource ID #0x7f080305 Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #X: <bitmap> requires a valid src attribute
@Erik 从我收集到的异常中说您的 logo_vect 文件可能不存在或格式错误。你检查过吗?
你试过上面的三角形路径吗
是的,我完全按照你的指示做了。 1:创建矢量drawable(我复制了你的三角形矢量)。 2:创建/res/drawable-v21/splash.xml。 3:在其中放置带有 <bitmap ... /> 的分层列表。 4:在启动器活动主题的android:windowBackground项中使用@drawable/splash。 5:在 API 21 上构建并启动我的应用程序。 6:💥 崩溃(就像我上面说的):<bitmap> requires a valid src attribute
奇怪,您是否尝试过简单地使用不同的矢量可绘制对象?你能在android studio预览中看到三角形吗
f
fishstick

我目前正在使用水平和垂直居中的矢量可绘制的初始屏幕。这是我在 API 级别 25 上得到的:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">

<!-- background color, same as theme -->
<item android:drawable="@android:color/white"/>

<!-- app logo -->

<item
    android:drawable="@drawable/my_app_logo"
    android:gravity="center_horizontal|center_vertical"
    android:width="200dp"
    android:height="200dp"
    />
</layer-list>

如果要调整矢量drawable的尺寸,修改上面的android:widthandroid:height属性,不一定要修改原来的drawable。

另外,我的经验是不要将可绘制的矢量放在位图标签中,这对我来说永远不起作用。位图适用于 .png、.jpg 和 .gif 格式的文件,不适用于矢量绘图。

参考

https://developer.android.com/guide/topics/resources/drawable-resource#LayerList

https://developer.android.com/guide/topics/resources/more-resources.html#Dimension


关于矢量可绘制对象需要位于 标记而不是 标记内的好消息。
就我而言,它也适用于 png 图像,但正如你所说的位图标签不起作用,非常感谢:)