Eu gostaria de saber o que difere esses estados. Não encontrei nenhuma página da web esclarecendo isso.
Eu gostaria de saber o que difere esses estados. Não encontrei nenhuma página da web esclarecendo isso.
Respostas:
A diferença entre verificado e ativado é bastante interessante. Até mesmo a documentação do Google é apologética (ênfase adicionada):
... Por exemplo, em uma exibição de lista com seleção única ou múltipla habilitada, as exibições no conjunto de seleção atual são ativadas. (Hum, sim, lamentamos profundamente a terminologia aqui.) O estado ativado é propagado para os filhos da visualização em que está definido.
Então aqui está a diferença:
ListView (após Honeycomb) chama setChecked () OU setActivated () dependendo da versão do Android conforme abaixo (obtido do código-fonte do Android):
if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
if (child instanceof Checkable) {
((Checkable) child).setChecked(mCheckStates.get(position));
} else if (getContext().getApplicationInfo().targetSdkVersion
>= android.os.Build.VERSION_CODES.HONEYCOMB) {
child.setActivated(mCheckStates.get(position));
}
}
Observe a variável mCheckStates. Ele mantém o controle de quais posições em sua lista são verificadas / ativadas. Eles são acessíveis via, por exemplo, getCheckedItemPositions (). Observe também que uma chamada para ListView.setItemChecked () invoca o acima. Em outras palavras, ele também poderia ser chamado de setItemActivated ().
Antes do Honeycomb, tínhamos que implementar soluções alternativas para refletir state_checked em nossos itens de lista. Isso ocorre porque ListView chama setChecked () SOMENTE na View superior no layout (e os layouts não implementam verificável) ... e NÃO se propaga sem ajuda. Essas soluções alternativas tinham o seguinte formato: Estenda o layout raiz para implementar Checkable. Em seu construtor, encontre recursivamente todos os filhos que implementam Checkable. Quando setChecked () etc ... são chamados, passe a chamada para essas visualizações. Se essas visualizações implementam drawables da lista de estados (por exemplo, um CheckBox) com um drawable diferente para state_checked, então o estado verificado é refletido na IU.
Para fazer um bom plano de fundo para um item de lista após o Honeycomb, tudo que você precisa fazer é ter um drawable da lista de estados com um drawable para o estado state_activated assim (e usar setItemChecked () é claro):
<item android:state_pressed="true"
android:drawable="@drawable/list_item_bg_pressed"/>
<item android:state_activated="true"
android:drawable="@drawable/list_item_bg_activated"/>
<item android:drawable="@drawable/list_item_bg_normal"/>
Para fazer um bom pano de fundo para um item de lista antes do HoneyComb, você faria algo como o acima para state_checked e TAMBÉM precisa estender sua visão superior para implementar a interface Checkable. Dentro disso, você precisa dizer ao Android se o estado que está implementando é verdadeiro ou falso, implementando onCreateDrawableState () e chamando refreshDrawableState () sempre que o estado muda.
<item android:state_pressed="true"
android:drawable="@drawable/list_item_bg_pressed"/>
<item android:state_checked="true"
android:drawable="@drawable/list_item_bg_checked"/>
<item android:drawable="@drawable/list_item_bg_normal"/>
... e o código para implementar Checkable combinado com state_checked em um RelativeLayout poderia ser:
public class RelativeLayoutCheckable extends RelativeLayout implements Checkable {
public RelativeLayoutCheckable(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RelativeLayoutCheckable(Context context) {
super(context);
}
private boolean mChecked = false;
@Override
protected void onFinishInflate() {
super.onFinishInflate();
}
@Override
public boolean isChecked() {
return mChecked;
}
@Override
public void setChecked(boolean checked) {
mChecked = checked;
refreshDrawableState();
}
private static final int[] mCheckedStateSet = {
android.R.attr.state_checked,
};
@Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, mCheckedStateSet);
}
return drawableState;
}
@Override
public void toggle() {
setChecked(!mChecked);
}
}
Graças ao seguinte:
http://sriramramani.wordpress.com/2012/11/17/custom-states/
Stackoverflow: como adicionar um estado de botão personalizado
Stackoverflow: Visualização verificável personalizada que responde ao Seletor
http://www.charlesharley.com/2012/programming/custom-drawable-states-in-android/
http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList
http://blog.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/
Selection is a transient property, representing the view (hierarchy) the user is currently interacting with. Activation is a longer-term state that the user can move views in and out of. For example, in a list view with single or multiple selection enabled, the views in the current selection set are activated. (Um, yeah, we are deeply sorry about the terminology here.)
fonte
setItemChecked()
e usando um seletor com propriedadeandroid:state_activated="true"
De acordo com o doc :
android: booleano selecionado por estado . " true
" se este item deve ser usado quando o objeto é a seleção atual do usuário ao navegar com um controle direcional (como ao navegar por uma lista com um d-pad); " false
" se este item deve ser usado quando o objeto não está selecionado. O estado selecionado é usado quando o foco (android: state_focused) não é suficiente (como quando a exibição de lista tem foco e um item dentro dela é selecionado com um d-pad).
android: booleano state_checked . " true
" se este item deve ser usado quando o objeto é verificado; " false
" se deve ser usado quando o objeto está desmarcado.
android: booleano state_activated . " true
" se este item deve ser usado quando o objeto é ativado como a seleção persistente (como para "destacar" o item da lista selecionado anteriormente em uma visualização de navegação persistente); " false
" se deve ser usado quando o objeto não está ativado. Introduzido na API de nível 11 .
Acho que o médico é bastante claro, então qual é o problema?
Aqui está outra solução para este problema: https://github.com/jiahaoliuliu/CustomizedListRow/blob/master/src/com/jiahaoliuliu/android/customizedlistview/MainActivity.java
Substituí o método setOnItemClickListener e verifiquei casos diferentes no código. Mas definitivamente a solução do Marvin é muito melhor.
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position,
long id) {
CheckedTextView checkedTextView =
(CheckedTextView)view.findViewById(R.id.checkedTextView);
// Save the actual selected row data
boolean checked = checkedTextView.isChecked();
int choiceMode = listView.getChoiceMode();
switch (choiceMode) {
// Not choosing anything
case (ListView.CHOICE_MODE_NONE):
// Clear all selected data
clearSelection();
//printCheckedElements();
break;
// Single choice
case (ListView.CHOICE_MODE_SINGLE):
// Clear all the selected data
// Revert the actual row data
clearSelection();
toggle(checked, checkedTextView, position);
//printCheckedElements();
break;
// Multiple choice
case (ListView.CHOICE_MODE_MULTIPLE):
case (ListView.CHOICE_MODE_MULTIPLE_MODAL):
// Revert the actual selected row data
toggle(checked, checkedTextView, position);
//printCheckedElements();
break;
}
}
});