Edit
As explained in the comments, the form previously proposed does not meet.
Soon I’m proposing another, using custom states, I believe a cleaner and more correct way.
The steps are as follows:
First we need to create a Custom View
extend any one you use to represent your square in the crossword. In my case, it’s a subclass of TextView
.
public class PalavraCruzadaTextView extends TextView {
private static final int[] ERRADO_STATE_SET = {R.attr.state_errado};
private static final int[] CORRETO_STATE_SET = {R.attr.state_correto};
private static final int[] PALAVRA_STATE_SET = {R.attr.state_palavra};
boolean correto, errado, palavra;
public RobotoTextView(Context context) {
super(context);
}
public RobotoTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RobotoTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected int[] onCreateDrawableState(int extraSpace) {
// Chama o metodo da superclasse para tratar os estados comuns
// Passando o espaco + 3, por causa dos nossos estados customizados
final int[] drawableState = super.onCreateDrawableState(extraSpace + 3);
if (isCorreto()) {
mergeDrawableStates(drawableState, CORRETO_STATE_SET);
}
if (isErrado()) {
mergeDrawableStates(drawableState, ERRADO_STATE_SET);
}
if (isPalavra()) {
mergeDrawableStates(drawableState, PALAVRA_STATE_SET);
}
return drawableState;
}
public boolean isCorreto() {
return correto;
}
public boolean isErrado() {
return errado;
}
public boolean isPalavra() {
return palavra;
}
public void setCorreto(boolean correto) {
this.correto = correto;
// Atualiza o estado do drawable
refreshDrawableState();
}
public void setErrado(boolean errado) {
this.errado = errado;
// Atualiza o estado do drawable
refreshDrawableState();
}
public void setPalavra(boolean palavra) {
this.palavra = palavra;
// Atualiza o estado do drawable
refreshDrawableState();
}
}
With this it is necessary to define the states that the PalavraCruzadaTextView
can have in terms of xml. Put in your file /res/values/attrs.xml
(or create) the following statement:
<declare-styleable name="PalavraCruzadaTextView">
<attr name="state_errado" format="boolean" />
<attr name="state_correto" format="boolean" />
<attr name="state_palavra" format="boolean" />
</declare-styleable>
This defines the 3 possible custom states that the PalavraCruzadaTextView
may have.
To set a background for the PalavraCruzadaTextView
, taking into account the states, just do:
<nome.do.pacote.PalavraCruzadaTextView
android:id="@+id/palavra_cruzada_text_view"
android:width="wrap_content"
android:height="wrap_content"
android:background="@drawable/background_palavra_cruzada" />
The background_crossword definition.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item app:state_correto="true">
<!-- Define o Drawable para o estado correto -->
<shape android:shape="rectangle">
<solid android:color="@color/green" />
</shape>
</item>
<item app:state_errado="true">
<!-- Define o Drawable para o estado errado -->
<shape android:shape="rectangle">
<solid android:color="@color/red" />
</shape>
</item>
<!-- Como temos outro estado combinando esses dois,
eh preciso forçar o false para nao sobrepor -->
<item app:state_palavra="true" android:state_pressed="false">
<!-- Define o Drawable para o estado palavra -->
<shape android:shape="rectangle">
<solid android:color="@color/orange" />
</shape>
</item>
<!-- Pode-se combinar com outros estados -->
<item app:state_palavra="true" android:state_pressed="true">
<!-- Define o Drawable para o estado palavra -->
<shape android:shape="rectangle">
<solid android:color="@color/orange" />
</shape>
</item>
</selector>
And to change the states:
PalavraCruzadaTextView pl = (PalavraCruzadaTextView) findViewById(R.id.palavra_cruzada_text_view);
pl.setCorreto(...);
pl.setErrado(...);
pl.setPalavra(...);
// E para saber o estado atual:
pl.isCorreto();
pl.isErrado();
pl.isPalavra();
References:
- Custom Drawing States possible?
Another solution could be:
When using the attribute @color/back_corDoFundo
You created a reference. From the moment your Layout has been inflated, the reference is "solved" and turns a color value of 4 bytes that has no identifier.
The background of a View
is a Drawable
, depending on the subclass there is a different way to get the color.
The fact of using the attribute background="@color/...
the LayoutInflater
creates a ColorDrawable
representing this colour, each type of Drawable
for this attribute will generate a different subclass. And in this subclass it is possible to get color easily.
What you can do is:
// Pego o background da View
Drawable background = suaView.getBackground();
// Pego a cor na representação em 4 bytes relativa a sua cor no resource
int corDoFundo = getResources().getColor(R.color.back_corDoFundo);
// Como voce usou o @color/back_corDoFundo, a subclasse eh ColorDrawable
ColorDrawable = cBackground = (ColorDrawable) background;
// Comparo as duas cores
if(corDoFundo == cBackground.getColor()) {
// A cor do fundo da View e back_corDoFundo
}
Watch out!! Any change in this attribute can generate a different subclass. And so the approach should be different!
If you use a Drawable State List
, being xml for example:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@color/red" />
<item android:drawable="@color/blue" />
</selector>
In that case the LayoutInflater
will create a Drawable
whose subclass is StateListDrawable
, where it has two states. Where each state is one ColorDrawable
.
And so on and so forth...
Probably not possible. What you could achieve would be Resource ID (a numeric constant in the class
R
) corresponding to the background file, but the only information available is theDrawable
used in the background (viagetBackground()
), and I believe that the system has no need to preserve that information along with theDrawable
, so much so that the classDrawable
doesn’t have agetResourceId()
or anything like that.– Piovezan
Another way would be to save the string in the file
strins.xml
and then capture with the methodfindViewById(R.string.string_background)
, and uses it to define the background of textView.– Gustavo Cinque