6

Bei einer SettingsActivity mit nur einer MultiSelectListPreference mit ihren Einträgen, Werten und Standardwerten in Array-Ressourcen werden einige Checkboxen nicht als aktiviert markiert, obwohl Android weiß soll überprüft werden. Wenn auf ein nicht markiertes Objekt geklickt wird, bleibt das Objekt deaktiviert (weil Android denkt, dass es ein markiertes Objekt deaktiviert).Checkboxen für MultiSelectListPreference nicht markiert, wenn sie ursprünglich nicht in der Liste sichtbar sind (API 23)

Here's a video of this happening

Projekt finden Sie hier: https://github.com/ImmersibleElf/MSLPBug

Es scheint in APIs 21 und 22 gut zu funktionieren, aber nicht in 23. Ist das vielleicht ein Fehler in der Wiederverwertung von Ansichten? Oder was könnte der Grund sein?

SettingsActivity.java

package com.immersibleelf.mslpbug; 

import android.os.Bundle; 
import android.preference.PreferenceFragment; 
import android.support.v7.app.AppCompatActivity; 

public class SettingsActivity extends AppCompatActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // Display the fragment as the main content. 
     getFragmentManager().beginTransaction() 
       .replace(android.R.id.content, new SettingsFragment()) 
       .commit(); 
    } 

    @Override 
    public void onPause() { 
     super.onPause(); 
    } 

    public static class SettingsFragment extends PreferenceFragment { 
     @Override 
     public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 

      // Load the settings from an XML resource 
      addPreferencesFromResource(R.xml.settings); 
     } 
    } 
} 

settings.xml

<?xml version="1.0" encoding="utf-8"?> 

<PreferenceScreen 
    xmlns:android="http://schemas.android.com/apk/res/android"> 

     <MultiSelectListPreference 
      android:key="mslp_key" 
      android:title="MultiSelectListPreference" 
      android:entries="@array/mslp_entries" 
      android:entryValues="@array/mslp_entry_values" 
      android:defaultValue="@array/mslp_default_value" 
      android:persistent="true" 
      /> 
</PreferenceScreen> 

arrays.xml

<?xml version="1.0" encoding="utf-8"?> 

<resources> 

    <string-array name="mslp_entries"> 
     <item>Entry 01</item> 
     <item>Entry 02</item> 
     <item>Entry 03</item> 
     <item>Entry 04</item> 
     <item>Entry 05</item> 
     <item>Entry 06</item> 
     <item>Entry 07</item> 
     <item>Entry 08</item> 
     <item>Entry 09</item> 
     <item>Entry 10</item> 
     <item>Entry 11</item> 
     <item>Entry 12</item> 
     <item>Entry 13</item> 
     <item>Entry 14</item> 
     <item>Entry 15</item> 
    </string-array> 

    <string-array name="mslp_entry_values"> 
     <item>1</item> 
     <item>2</item> 
     <item>3</item> 
     <item>4</item> 
     <item>5</item> 
     <item>6</item> 
     <item>7</item> 
     <item>8</item> 
     <item>9</item> 
     <item>10</item> 
     <item>11</item> 
     <item>12</item> 
     <item>13</item> 
     <item>14</item> 
     <item>15</item> 
    </string-array> 

    <string-array name="mslp_default_value"> 
     <item>1</item> 
     <item>2</item> 
     <item>3</item> 
     <item>4</item> 
     <item>5</item> 
     <item>6</item> 
     <item>7</item> 
     <item>8</item> 
     <item>9</item> 
     <item>10</item> 
     <item>11</item> 
     <item>12</item> 
     <item>13</item> 
     <item>14</item> 
     <item>15</item> 
    </string-array> 

</resources> 
+0

ich denke, ist ein Android-Bug auf Recycling, wenn Sie mehr Element haben, wenn Sie deaktivieren Element bewegen – Xan

+0

zufällig das gleiche Problem zu haben. Haben Sie weitere Informationen oder eine mögliche Lösung gefunden? – mdiener

+1

@mdiener Ich [hier gemeldet] (https://code.google.com/p/android/issues/detail?id=205487), aber ich denke, es ist ein ziemlich niedriger Priorität Bug. Ich habe versucht, es selbst aufzuspüren, aber konnte es bisher nur auf meinen Windows-PCs in der Zeit verfolgen, die ich hatte. Wenn Sie Linux oder Mac OS haben und Lust haben, mit der Android-Quelle zu spielen, kann ich Sie möglicherweise auf die problematischen Bereiche hinweisen. Aber selbst zu wissen, was genau und wo falsch läuft, führt nicht unbedingt zu einer offensichtlichen Lösung. – Chroaster

Antwort

4

Eine Abhilfe ist eine Unterklasse von MultiSelectListPreference zu erstellen, und das Verfahren zu überschreiben möchte Showdialog dies:

@Override 
protected void showDialog(Bundle state) { 
    super.showDialog(state); 

    AlertDialog dialog = (AlertDialog)getDialog(); 
    if (dialog == null) 
     return; 

    if (Build.VERSION.SDK_INT >= 23) { 
     ListView listView = dialog.getListView(); 

     listView.setOnScrollListener(new AbsListView.OnScrollListener() { 
      @Override 
      public void onScrollStateChanged(AbsListView view, int scrollState) { 
       int size = view.getChildCount(); 
       for (int i=0; i<size; i++) { 
        View v = view.getChildAt(i); 
        if (v instanceof CheckedTextView) 
         ((CheckedTextView)v).refreshDrawableState(); 
       } 
      } 

      @Override 
      public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
       int size = view.getChildCount(); 
       for (int i=0; i<size; i++) { 
        View v = view.getChildAt(i); 
        if (v instanceof CheckedTextView) 
         ((CheckedTextView)v).refreshDrawableState(); 
       } 
      } 
     }); 
    } 
} 
+1

Die beiden Umwandlungen zu "CheckedTextView" sind redundant. Ansonsten ist das ausgezeichnet, vielen Dank. – Keelan

0

Ausgezeichnet. Dieser Code funktioniert wie mdiener erwähnt:

import android.app.AlertDialog; 
import android.content.Context; 
import android.os.Build; 
import android.os.Bundle; 
import android.preference.MultiSelectListPreference; 
import android.util.AttributeSet; 
import android.view.View; 
import android.widget.AbsListView; 
import android.widget.CheckedTextView; 
import android.widget.ListView; 

/** 
* Android bug: https://code.google.com/p/android/issues/detail?id=205487 
*/ 
public class MultiSelectWrapper extends MultiSelectListPreference { 

public MultiSelectWrapper(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 
    super(context, attrs, defStyleAttr, defStyleRes); 
} 

public MultiSelectWrapper(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
} 

public MultiSelectWrapper(Context context, AttributeSet attrs) { 
    super(context, attrs); 
} 

public MultiSelectWrapper(Context context) { 
    super(context); 
} 

@Override 
protected void showDialog(Bundle state) { 
    super.showDialog(state); 

    AlertDialog dialog = (AlertDialog)getDialog(); 
    if (dialog == null) 
     return; 

    if (Build.VERSION.SDK_INT >= 23) { 
     ListView listView = dialog.getListView(); 

     listView.setOnScrollListener(new AbsListView.OnScrollListener() { 
      @Override 
      public void onScrollStateChanged(AbsListView view, int scrollState) { 
       int size = view.getChildCount(); 
       for (int i=0; i<size; i++) { 
        View v = view.getChildAt(i); 
        if (v instanceof CheckedTextView) 
         ((CheckedTextView)v).refreshDrawableState(); 
       } 
      } 

      @Override 
      public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
       int size = view.getChildCount(); 
       for (int i=0; i<size; i++) { 
        View v = view.getChildAt(i); 
        if (v instanceof CheckedTextView) 
         ((CheckedTextView)v).refreshDrawableState(); 
       } 
      } 
     }); 
    } 
} 
} 
Verwandte Themen