在XML描述中旋转可绘制对象是否可能?

113

我正在创建一个应用程序,其中包含可以重复使用的资源(因为按钮始终相同,但是镜像或旋转)。 我确实想要使用相同的资源,这样我就不必添加3个完全像原始资源但旋转的资源。 但是我也不想将代码与可以在XML中声明的内容混合,或者使用矩阵进行转换,这将耗费处理时间。

我在XML中声明了一个具有两种状态的按钮。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"
          android:drawable="@drawable/and_card_details_button_down_left_onclick" /> <!-- pressed -->
    <item android:drawable="@drawable/and_card_details_button_down_left" /> <!-- default -->
</selector>

我想重复使用这个可绘制对象,因为它将是相同的,只不过旋转了90度和45度,并且我将其分配给按钮作为一个可绘制对象。

<Button android:id="@+id/Details_Buttons_Top_Left_Button"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@drawable/details_menu_large_button" />

我知道可以使用 RotateDrawable 或者 Matrix 来旋转图片,但正如我之前解释的那样,我不喜欢这种方法。

是否可以直接在XML中实现旋转?或者你认为最好的方法是什么?将所有资源都放置但未旋转,在代码中旋转它们?

--- 编辑 ---
@dmaxi 的答案非常好用,以下是如何将其与项目列表结合使用 :)

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true">
        <rotate 
        android:fromDegrees="90"
        android:toDegrees="90"
        android:pivotX="50%"
        android:pivotY="50%"
        android:drawable="@drawable/and_card_details_button_up_onclick"/>
    </item>

    <item>
        <rotate
        android:fromDegrees="90"
        android:toDegrees="90"
        android:pivotX="50%"
        android:pivotY="50%"
        android:drawable="@drawable/and_card_details_button_up_onclick"/>
    </item>

</selector>

4
不需要道歉,你的英语很好。欢迎来到SO! - PeeHaa
请查看此线程中与相同问题相关的内容:https://dev59.com/BW7Xa4cB1Zd3GeqPmSKq 任何建议都将不胜感激! - sukarno
基于向量的可绘制对象极大地简化了问题(请参见下面的答案)。 - samus
4个回答

147

我可以在XML中进行旋转

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android" 
        android:fromDegrees="90"
        android:toDegrees="90"
        android:pivotX="50%"
        android:pivotY="50%"
        android:drawable="@drawable/mainmenu_background">
</rotate>

fromDegrees很重要。

基本上,这是一个在XML中定义的旋转动画。使用fromDegrees可以定义初始旋转状态。 toDegrees是动画序列中可绘制对象的最终旋转状态,但如果您不想使用动画,则可以是任何值。

我认为它不会分配用于动画的资源,因为它不必作为动画加载。作为一个可绘制对象,它被呈现为其初始状态,并应放置在drawable资源文件夹中。 要将其用作动画,请将其放入anim资源文件夹中,并可以像这样启动动画(只是示例):

Animation rotation = AnimationUtils.loadAnimation(this, R.anim.rotation);
rotation.setRepeatCount(Animation.INFINITE);
myView.startAnimation(rotation);

1
谢谢,太完美了!我将其与该项结合使用,正是我所需要的。我想发布代码,不知道编辑您的答案还是我的问题更好... 关于镜像图像,我是否需要调整枢轴的x和y? - Goofyahead
1
@dmaxi 这是通过旋转动画旋转drawable,对吗?那不会有些低效吗? - starkej2
我制作了这个东西,但是从0到360度,因为我想要完全旋转,问题是在小屏幕上它会变形旋转,有什么线索吗? - firetrap
1
Android M 中存在一个错误,影响了这个旋转的可绘制对象,它会完全消失,因此如果您选择这个解决方案,它将在 M 版本中出现问题。已经在 N 版本中修复。 - androidguy
1
无法旋转SVG可绘制对象。有什么想法吗? - masoomyf
显示剩余5条评论

38

我可以在XML中通过以下方法将左箭头旋转为右箭头:

<rotate android:fromDegrees="180" />
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="180"
    android:toDegrees="0"
    android:drawable="@drawable/left">
</rotate>

附上参考图像。

enter image description here


我正在做这个,但是我无法将背景设置为布局。有什么想法吗? - Mateen Chaudhry

29
如果使用基于向量的可绘制对象以及样式和颜色状态列表与 ImageView 结合使用,可以将您的按钮重构为以下形式: 注意: 向量可绘制对象比图像要小得多,因此额外的、显式的定义不会产生太多开销,并且能够生成清晰明确的代码(尽管我读到过应避免手动修改向量资源,但我宁愿处理更新几个文件的开销,也不愿在一个文件上进行转换): 注意: Android Studio 是向量资源的一个很好来源。 res\values\styles.xml
<!--ImageView-->
<style name="Details_Buttons_Top_Left_Button">
  <item name="android:layout_width">match_parent</item>
  <item name="android:layout_height">match_parent</item>    
  <item name="android:tint">@color/button_csl</item>    
</style>

res\color\button_csl.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">  
  <item android:state_enabled="false" android:color="@color/grey_disabled"/>
  <item android:state_pressed="true" android:color="@color/orange_hilite"/>
  <item android:color="@color/black"/>  
</selector>

details_menu_large_button.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_pressed="true"
        android:drawable="@drawable/and_card_details_button_down_left_onclick" /> <!-- pressed -->
  <item android:drawable="@drawable/and_card_details_button_down_left" /> <!-- default -->
</selector>

详细信息_按钮_左上角_按钮

<ImageView android:id="@+id/Details_Buttons_Top_Left_Button"
           style="@style/Details_Buttons_Top_Left_Button"
           android:src="@drawable/details_menu_large_button" />

and_card_details_button_down_left.xml(ic_play_arrow_black_24dp.xml)

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">  
  <path
        android:fillColor="#FF000000"
        android:pathData="M8,5v14l11,-7z"/>

</vector>

and_card_details_button_down_left_onclick.xml(ic_play_arrow_black_24dp.xml 修改)

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
  <group android:name="rotationGroup"
         android:pivotX="12"
         android:pivotY="12"
         android:rotation="90" >
    <path
          android:fillColor="#FF000000"
          android:pathData="M8,5v14l11,-7z"/>
  </group>
</vector>

4
rotationGroup属性的答案很好,它可以很好地旋转向量。 - blueware

6
如果你想在xml文件中旋转可绘制对象,只需在ImageView中添加android:rotation="180"即可。
<ImageView
    android:id="@+id/imageview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_dropdown"
    android:rotation="180"/>

以程序方式

val image = findViewById(R.id.imageview)
image.rotation = 180f

1
谢谢!找到这个答案花了好长时间! - Kibi

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