Etendre les classes de préférences dans Android Lollipop = perdre de l'animation

Juste pour étendre CheckBoxPreference ou SwitchPreference sur Android Lollipop, le widget (la case à cocher ou le commutateur) n'a plus d'animation.

J'aimerais étendre SwitchPreference pour forcer api <21 à utiliser SwitchCompat au lieu de celui par défaut utilisé (ce qui est évidemment erroné).

  • Google n'autorise plus l'utilisation de WebView. Quelles sont les alternatives?
  • OBD2 - ELM327 simulateur bluetooth
  • Android Studio, Logcat nettoie une fois l'application terminée
  • Définir une connexion VPN par programme sur Android 4.0
  • GetActivity () ne peut pas trouver le symbol symbol: method getActivity ()
  • ActionBarDrawerToggle v7 ou v4?
  • J'utilise la nouvelle AppCompatPreferenceActivity avec appcompat-v7:22.1.1 mais cela ne semble pas affecter les commutateurs.

    La seule chose consiste à simplement étendre ces cours, sans ajouter de mise en page personnalisée ni de mise en page de la ressource de widget, mais l'animation est terminée.

    Je sais que je peux écrire deux instances de ma préférence.xml (sur les valeurs internes-v21) et ça fonctionnera … Mais j'aimerais savoir pourquoi cela se produit et si quelqu'un connaît une solution sans avoir deux preferences.xml.

    Exemple de code:

     public class SwitchPreference extends android.preference.SwitchPreference { public SwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @TargetApi(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); } } 

    Ceci ou le même pour CheckBoxPreference, puis utilisez:

    <com.my.package.SwitchPreference />

    Rendra l'animation dans un périphérique Lollipop disparue.

    Une autre chose que j'ai essayé pour le SwitchPreference (que je peux avec CheckBoxPreference) est de donner une mise en page avec l'identifiant par défaut, mais @android:id/switchWidget n'est pas public alors que @android:id/checkbox est. Je sais également que je peux utiliser un <CheckBoxPreference /> et donner une mise en page de widget qui est en fait un SwitchCompat, mais j'aimerais éviter cela (en confondant les noms).

  • Désactiver le clavier doux sur NumberPicker
  • Support GIF animé Android
  • Application Android avec plusieurs activités
  • Android Fragment transition exit animation joué ci-dessus, entrez l'animation
  • Activer les services de localisation pour Android si l'utilisateur choisit l'option Jamais
  • Comment déterminer un numéro de chaîne wifi utilisé par wifi ap / network?
  • 4 Solutions collect form web for “Etendre les classes de préférences dans Android Lollipop = perdre de l'animation”

    Il semble que j'ai trouvé un problème pour votre problème.

    Explication détaillée

    Dans SwitchCompat , lors de la modification du commutateur, il teste quelques fonctions avant de jouer l'animation: getWindowToken() != null && ViewCompat.isLaidOut(this) && isShown() .

    Méthode complète:

     @Override 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); } } 

    En utilisant une vue personnalisée étendant SwitchCompat , j'ai découvert que c'est isShown() renvoie toujours false , car à la troisième itération du while , parent == null .

     public boolean isShown() { View current = this; //noinspection ConstantConditions do { if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { return false; } ViewParent parent = current.mParent; if (parent == null) { return false; // We are not attached to the view root } if (!(parent instanceof View)) { return true; } current = (View) parent; } while (current != null); return false; } 

    Il est intéressant de noter que le troisième parent est le deuxième attribut passé à getView(View convertView, ViewGroup parent) en préférence , signifie que PreferenceGroupAdapter n'a pas eu un parent passé à son propre getView() . Pourquoi cela se produit exactement et pourquoi cela ne se produit que pour les cours de préférence personnalisés, je ne sais pas.

    À mes fins de test, j'ai utilisé CheckBoxPreference avec SwitchCompat comme widgetLayout , et je n'ai pas non plus vu d'animations.

    Réparer

    Maintenant à la correction: faites simplement votre propre vue étendant SwitchCompat , et remplacer votre isShown() comme ceci:

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

    Utilisez ce SwitchView pour votre style widgetLayout , et les animations fonctionnent à nouveau: D

    Modes:

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

    Disposition des widgets:

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

    Parfois, l'extension d'une classe n'est pas la meilleure solution. Pour éviter de perdre les animations, vous pouvez plutôt composer, je voulais créer une classe où vous avez une variable de champ SwitchPreference et y appliquer la nouvelle logique. C'est comme une enveloppe. Cela a fonctionné pour moi.

    Je parviens à le réparer comme ça et les animations fonctionnent avant d'aller directement à l'état sans animation:

    RÉPARER:

    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); } @Override public boolean isShown() { return getVisibility() == VISIBLE; } } 

    Dans votre mise en page, procédez comme suit: 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"/> 

    Et dans votre préférence.xml, procédez comme suit:

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

    Classe publique SwitchPreference extends 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.getDeclaredField("mCanRecycleLayout"); canRecycleLayoutField.setAccessible(true); canRecycleLayoutField.setBoolean(this, true); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } 
    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.