É possível girar um drawable na descrição xml?

102

Estou criando um aplicativo, com recursos que podem ser reaproveitados (porque os botões são sempre os mesmos, mas espelhados ou girados). Eu quero usar o mesmo recurso, então não preciso adicionar mais 3 recursos que são exatamente como o original, mas rotacionados. Mas também não quero misturar o código com coisas que podem ser declaradas no XML ou fazer transformações com uma matriz que custará tempo de processamento.

Eu tenho um botão de dois estados declarado em um 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>

e quero reutilizar o drawable porque será o mesmo, mas girado 90º e 45º e atribuo ao botão como um drawable.

<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" />

Eu sei que posso girar com um RotateDrawableou com umMatrix mas como já expliquei, não gosto dessa abordagem.

É possível fazer isso diretamente no XML ou qual você acha que será a melhor maneira de fazer isso? Colocar todos os recursos menos girados, girá-los no código?

--- EDITAR --- A resposta de @dmaxi funciona muito bem, veja como combiná-la com uma lista de itens :)

<?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>
Goofyahead
fonte
4
Não há necessidade de se desculpar, seu inglês está bem. E bem-vindo ao SO!
PeeHaa
olhe para o mesmo problema neste tópico stackoverflow.com/questions/14727426/ ... qualquer sugestão seria ótima!
sukarno
Drawables baseados em vetor simplificam muito as questões (resposta abaixo).
samis

Respostas:

136

Eu poderia girar em 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>

O fromDegreesé importante.

Basicamente, esta é uma animação de rotação definida em XML. Com fromDegreesvocê define o estado inicial de rotação. otoDegrees é o estado girado final do drawable na sequência de animação, mas pode ser qualquer coisa se você não quiser usar animação.

Não acho que aloca recursos para animação, pois não precisa ser carregado como animação. Como drawable, ele é renderizado em seu estado inicial e deve ser colocado na drawablepasta de recursos. Para usá-lo como uma animação, você deve colocá-lo na animpasta de recursos e pode iniciar a animação assim (apenas um exemplo):

Animation rotation = AnimationUtils.loadAnimation(this, R.anim.rotation);
rotation.setRepeatCount(Animation.INFINITE);
myView.startAnimation(rotation);
dmaxi
fonte
1
Obrigado, isso é perfeito! Combinei isso com o item e é exatamente o que preciso, quero postar o código, não sei se é melhor editar sua resposta ou minha pergunta ... E para espelhar a imagem, tenho que brincar com o pivô x e y?
Goofyahead
Bem, fico feliz em poder ajudar, edite a resposta, se desejar. pivotX e pivotY definem o ponto central da rotação. Para espelhamento, não tenho ideia porque este XML só pode definir a rotação 2D.
dmaxi
1
@dmaxi Isso está girando o drawable por meio de uma animação de rotação, não é? Isso não seria um tanto ineficiente?
starkej2
Fiz isso mas de 0 a 360 graus porque quero uma rotação completa, o problema é que nas telas pequenas ele gira deformado, alguma pista?
firetrap
1
Havia um bug no Android M afetando este drawable de rotação exata, ele desaparece completamente, então se você escolher esta solução, ele será quebrado em M. Foi corrigido para N.
androidguy
34

Eu poderia girar a seta esquerda para a direita em XML como:

<?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>

Imagem anexada para referência.

insira a descrição da imagem aqui

amko0l
fonte
Estou fazendo isso, mas não consigo definir o plano de fundo para o layout, alguma ideia?
Mateen Chaudhry
18

Se drawables baseados em vetor forem usados, em conjunto com uma ImageView , uma lista de estilos e estados de cores, seu botão pode ser refatorado da seguinte maneira:

Observação: drawables vetoriais são significativamente menores do que imagens, portanto, definições extras e explícitas não geram muita sobrecarga e tornam o código claro e explícito (embora eu tenha lido que a modificação manual de ativos vetoriais deve ser evitada, prefiro lidar com a sobrecarga de atualizar alguns arquivos do que ter transformações em um):

Observação: o Android Studio é uma ótima fonte de ativos vetoriais.

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>

Details_Buttons_Top_Left_Button

<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 modificado)

<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>
Sam é
fonte
3
Boa resposta para o rotationGroupatributo, ele gira o vetor muito bem
blueware de
0

Se você quiser rotationDrawable em xmlarquivo, em seguida, simples add android:rotation="180"noImageView

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_dropdown"
    android:rotation="180"/>
Dinesh
fonte