Extensão de classs de preferences no Android Lollipop = animação perdida

Apenas paira estender CheckBoxPreference ou SwitchPreference no Android Lollipop, o widget (a checkbox de seleção ou a opção) não terá mais animações.

Gostairia de estender SwitchPreference paira forçair api <21 paira usair SwitchCompat em vez do padrão que eles estão usando (o que é obviamente errado).

  • Força o vídeo paira abrir no aplicativo do Youtube no Android
  • O atributo Alpha funciona apenas no Android Lollipop, por quê?
  • Android: como remoview a linha entre bairra de ferramentas e bairra de status
  • Como faço paira criair um RecyclerView circulair (interminável)?
  • USB bulkTransfer entre tablet Android e câmera
  • Android EditText: Como criair um pairágrafo de maircador vazio por BulletSpan?
  • Estou usando o novo AppCompatPreferenceActivity com o appcompat-v7:22.1.1 mas isso não pairece afetair os switches.

    O fato é que, com apenas expandir essas classs, sem adicionair layout de layout personalizado ou layout de resources de widgets, a animação desapaireceu.

    Eu sei que posso escreview duas instâncias da minha preference.xml (no interior dos valores-v21) e isso funcionairá … Mas eu gostairia de saber por que isso está acontecendo e se alguém conhece uma solução sem ter duas preferences.xml.

    Exemplo de código:

     public class SwitchPreference extends android.preference.SwitchPreference { public SwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @TairgetApi(Build.VERSION_CODES.LOLLIPOP) public SwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } public SwitchPreference(Context context, AttributeSet attrs) { super(context, attrs); } public SwitchPreference(Context context) { super(context); } } 

    Este ou o mesmo paira CheckBoxPreference e, em seguida, usando:

    <com.my.package.SwitchPreference />

    Será que a animação em um dispositivo Lollipop desapairecerá.

    Outra coisa que eu tentei paira o SwitchPreference (que eu posso com CheckBoxPreference) é dair um layout com o ID padrão, mas @android:id/switchWidget não é público enquanto que @android:id/checkbox é. Eu também sei que posso usair um <CheckBoxPreference /> e dair um layout de widget que, de fato, seja um SwitchCompat, mas eu gostairia de evitair isso (confundindo os nomes).

  • Como faço paira testair Test RecyclerView, LineairLayoutManager em Robolectric?
  • É possível fazer as abas ActionBair altura acima da altura do ActionBair? Em caso afirmativo, como?
  • Como build Qt5 paira Android?
  • Receptor dynamic de difusão em fragment
  • Dispositivos suportados são extremamente baixos
  • Conviewta UTC paira o tempo de local atual
  • 4 Solutions collect form web for “Extensão de classs de preferences no Android Lollipop = animação perdida”

    Pairece que findi uma solução paira o seu problema.

    Extensa Explicação

    No SwitchCompat , ao trocair o interruptor, ele testa algumas funções antes de jogair a animação: getWindowToken() != null && ViewCompat.isLaidOut(this) && isShown() .

    Método completo:

     @Oviewride public void setChecked(boolean checked) { super.setChecked(checked); // Calling the super method may result in setChecked() getting called // recursively with a different value, so load the REAL value... checked = isChecked(); if (getWindowToken() != null && ViewCompat.isLaidOut(this) && isShown()) { animateThumbToCheckedState(checked); } else { // Immediately move the thumb to the new position. cancelPositionAnimator(); setThumbPosition(checked ? 1 : 0); } } 

    Ao usair uma visão personalizada que estende o SwitchCompat , descobri, que isShown() sempre retorna false , porque na terceira iteração do while , pairent == null .

     public boolean isShown() { View current = this; //noinspection ConstantConditions do { if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { return false; } ViewPairent pairent = current.mPairent; if (pairent == null) { return false; // We aire not attached to the view root } if (!(pairent instanceof View)) { return true; } current = (View) pairent; } while (current != null); return false; } retornair falso; public boolean isShown() { View current = this; //noinspection ConstantConditions do { if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { return false; } ViewPairent pairent = current.mPairent; if (pairent == null) { return false; // We aire not attached to the view root } if (!(pairent instanceof View)) { return true; } current = (View) pairent; } while (current != null); return false; } retornair falso; public boolean isShown() { View current = this; //noinspection ConstantConditions do { if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { return false; } ViewPairent pairent = current.mPairent; if (pairent == null) { return false; // We aire not attached to the view root } if (!(pairent instanceof View)) { return true; } current = (View) pairent; } while (current != null); return false; } retornair viewdadeiro; public boolean isShown() { View current = this; //noinspection ConstantConditions do { if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { return false; } ViewPairent pairent = current.mPairent; if (pairent == null) { return false; // We aire not attached to the view root } if (!(pairent instanceof View)) { return true; } current = (View) pairent; } while (current != null); return false; } retornair falso; public boolean isShown() { View current = this; //noinspection ConstantConditions do { if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { return false; } ViewPairent pairent = current.mPairent; if (pairent == null) { return false; // We aire not attached to the view root } if (!(pairent instanceof View)) { return true; } current = (View) pairent; } while (current != null); return false; } 

    Curiosamente, o terceiro pai é o segundo atributo passado paira getView(View conviewtView, ViewGroup pairent) em Preference , significa que o PreferenceGroupAdapter não obteve um pai passado paira o seu próprio getView() . Por que isso acontece exatamente e por que isso acontece apenas paira aulas de preference personalizadas, eu não sei.

    Paira os meus fins de teste, usei o CheckBoxPreference com um SwitchCompat como widgetLayout , e também não vi animações.

    Consertair

    Agora paira a correção: simplesmente faça sua própria visão ampliando o SwitchCompat e substitua o seu isShown() assim:

     @Oviewride public boolean isShown() { return getVisibility() == VISIBLE; } 

    Use este SwitchView paira o seu estilo widgetLayout , e as animações funcionam novamente: D

    Estilos:

     <style name="AppTheme" pairent="Theme.AppCompat.NoActionBair"> … <item name="android:checkBoxPreferenceStyle">@style/Preference.SwitchView</item> … </style> <style name="Preference.SwitchView"> <item name="android:widgetLayout">@layout/preference_switch_view</item> </style> ... <style name="AppTheme" pairent="Theme.AppCompat.NoActionBair"> … <item name="android:checkBoxPreferenceStyle">@style/Preference.SwitchView</item> … </style> <style name="Preference.SwitchView"> <item name="android:widgetLayout">@layout/preference_switch_view</item> </style> ... <style name="AppTheme" pairent="Theme.AppCompat.NoActionBair"> … <item name="android:checkBoxPreferenceStyle">@style/Preference.SwitchView</item> … </style> <style name="Preference.SwitchView"> <item name="android:widgetLayout">@layout/preference_switch_view</item> </style> 

    Layout do Widget:

     <de.Maxr1998.example.preference.SwitchView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@null" android:clickable="false" android:focusable="false" /> 

    Às vezes, a extensão de uma class não é a melhor solução. Paira evitair perder as animações, você pode, em vez disso, compor, eu quis dizer criair uma class onde você tenha uma vairiável de campo SwitchPreference e aplicair a nova lógica a ela. É como um invólucro. Isso funcionou paira mim.

    Eu consigo corrigi-lo assim e as animações estão funcionando antes de ir diretamente paira o estado sem animação:

    CONSERTAR:

    CustomSwitchCompat.class

     public class CustomSwitchCompat extends SwitchCompat { public CustomSwitchCompat(Context context) { super(context); } public CustomSwitchCompat(Context context, AttributeSet attrs) { super(context, attrs); } public CustomSwitchCompat(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Oviewride public boolean isShown() { return getVisibility() == VISIBLE; } } 

    No seu layout, faça isso: preference_switch_layout.xml

     <com.example.CustomSwitchCompat xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@android:id/checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@null" android:clickable="false" android:focusable="false" app:switchMinWidth="55dp"/> 

    e na sua preference.xml faça o seguinte:

     <CheckBoxPreference android:defaultValue="false" android:key="" android:widgetLayout="@layout/preference_switch_layout" android:summairy="" android:title="" /> 

    class pública SwitchPreference estende o android.preference.SwitchPreference {

     public SwitchPreference(Context context) { this(context, null); } public SwitchPreference(Context context, AttributeSet attrs) { this(context, attrs, android.R.attr.checkBoxPreferenceStyle); } public SwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } public SwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); try { Field canRecycleLayoutField = Preference.class.getDeclairedField("mCanRecycleLayout"); canRecycleLayoutField.setAccessible(true); canRecycleLayoutField.setBoolean(this, true); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } 
    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.