NullPointerException en el método de mutación de Drawable Android 1.6

Cuando se usa mutate en Android 1.6 con estado de lista Drawable tengo siempre una excepción Null Pointer. Funciona perfectamente en versiones superiores de Android. Estoy usando el android predeterminado list_selector_background como el dibujable para mutar, y necesito mutar de lo contrario fondos presionados obtener bastante desordenado -> todos o algunos de ellos están recibiendo resaltar cuando se presiona.

El proyecto está aquí:

http://code.google.com/p/tree-view-list-android/

Y la pieza de código relevante aquí: http://code.google.com/p/tree-view-list-android/source/browse/src/pl/polidea/treeview/AbstractTreeViewAdapter.java#205

return activity.getResources() .getDrawable(android.R.drawable.list_selector_background) .mutate(); 

Pila de seguimiento a continuación:

 3-11 11:37:39.973: ERROR/AndroidRuntime(5304): java.lang.NullPointerException 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.graphics.drawable.StateListDrawable.mutate(StateListDrawable.java:227) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at pl.polidea.treeview.AbstractTreeViewAdapter.getDrawableOrDefaultBackground(AbstractTreeViewAdapter.java:201) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at pl.polidea.treeview.AbstractTreeViewAdapter.populateTreeItem(AbstractTreeViewAdapter.java:210) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at pl.polidea.treeview.AbstractTreeViewAdapter.getView(AbstractTreeViewAdapter.java:153) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.AbsListView.obtainView(AbsListView.java:1273) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.ListView.makeAndAddView(ListView.java:1658) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.ListView.fillDown(ListView.java:637) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.ListView.fillFromTop(ListView.java:694) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.ListView.layoutChildren(ListView.java:1516) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.AbsListView.onLayout(AbsListView.java:1112) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.view.View.layout(View.java:6569) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:998) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.LinearLayout.onLayout(LinearLayout.java:918) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.view.View.layout(View.java:6569) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.FrameLayout.onLayout(FrameLayout.java:333) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.view.View.layout(View.java:6569) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:998) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.LinearLayout.onLayout(LinearLayout.java:918) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.view.View.layout(View.java:6569) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.widget.FrameLayout.onLayout(FrameLayout.java:333) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.view.View.layout(View.java:6569) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.view.ViewRoot.performTraversals(ViewRoot.java:979) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.view.ViewRoot.handleMessage(ViewRoot.java:1613) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.os.Handler.dispatchMessage(Handler.java:99) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.os.Looper.loop(Looper.java:123) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at android.app.ActivityThread.main(ActivityThread.java:4203) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at java.lang.reflect.Method.invokeNative(Native Method) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at java.lang.reflect.Method.invoke(Method.java:521) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549) 03-11 11:37:39.973: ERROR/AndroidRuntime(5304): at dalvik.system.NativeStart.main(Native Method) 

Parece que hay un error en Android 1.6. Cuando se sumerge en fuentes de Android 1.6, puede encontrar el código siguiente:

 android.graphics.drawable.StateListDrawable.java: ... public Drawable mutate() { if (!mMutated && super.mutate() == this) { final int[][] sets = mStateListState.mStateSets; final int count = sets.length; mStateListState.mStateSets = new int[count][]; for (int i = 0; i < count; i++) { mStateListState.mStateSets[i] = sets[i].clone(); //NPE causing line } mMutated = true; } return this; } ... 

en línea

 mStateListState.mStateSets[i] = sets[i].clone(); //NPE causing line 

El método clone () a veces se llama al objeto null y causa NullPointerException

en Android> 1.6 se ha solucionado:

 public Drawable mutate() { if (!mMutated && super.mutate() == this) { final int[][] sets = mStateListState.mStateSets; final int count = sets.length; mStateListState.mStateSets = new int[count][]; for (int i = 0; i < count; i++) { final int[] set = sets[i]; if (set != null) { mStateListState.mStateSets[i] = set.clone(); } } mMutated = true; } return this; } 

pero en Android 1.6 necesitamos hacer alguna solución. Vamos a ver por qué mStateSets [i] a veces contiene nulos:

 android.graphics.drawable.DrawableContainer.DrowableContainerState: ... public final int addChild(Drawable dr) { final int pos = mNumChildren; if (pos >= mDrawables.length) { growArray(pos, pos+10); //Interesting line } dr.setVisible(false, true); dr.setCallback(mOwner); mDrawables[pos] = dr; mNumChildren++; mChildrenChangingConfigurations |= dr.getChangingConfigurations(); mHaveOpacity = false; mHaveStateful = false; mConstantPadding = null; mPaddingChecked = false; mComputedConstantSize = false; return pos; } ... 

se llama al método anterior durante el inflado de xml. Así que el tamaño de mStateListState.mStateSets es N * 10.

Ahora vamos a ver el cuerpo de list_selector_background.xml que está tratando de inflar de los recursos que se refieren por android.R.drawable.list_selector_background:

 <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2008 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_window_focused="false" android:drawable="@color/transparent" /> <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. --> <item android:state_focused="true" android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/list_selector_background_disabled" /> <item android:state_focused="true" android:state_enabled="false" android:drawable="@drawable/list_selector_background_disabled" /> <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition" /> <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition" /> <item android:state_focused="true" android:drawable="@drawable/list_selector_background_focus" /> </selector> 

este archivo contiene sólo 6 elementos! Entonces, ¿cómo podemos resolver el problema? 1. Crea list_selector_background.xml en {Project} / res / drowable / puedes copiar uno solo y cambiar una sola línea:

 <item android:state_window_focused="false" android:drawable="@color/transparent" /> 

a

 <item android:state_window_focused="false" android:drawable="@android:color/transparent" /> 
  1. Copia Android o crea tus propios archivos:

    list_selector_background_disabled.9.png list_selector_background_focus.9.png list_selector_background_longpress.9.png list_selector_background_pressed.9.png list_selector_background_transition.xml

  2. Modifique list_selector_background.xml agregando elementos ficticios para que coincidan exactamente (6 + 4 = 10) items condidtion:

     <item android:animationCache="true" android:drawable="@android:color/transparent" /> <item android:animationCache="false" android:drawable="@android:color/transparent" /> <item android:alwaysDrawnWithCache="false" android:drawable="@android:color/transparent" /> <item android:alwaysDrawnWithCache="true" android:drawable="@android:color/transparent" /> 

Voilà. Compilar y ejecutar. Debería funcionar ahora.

  • Android linearlayout selector de fondo
  • Android - barra de búsqueda de estilo
  • Cómo establecer el color de fila alternativo de Listview y el color de fondo del elemento seleccionado
  • Selección de un número del usuario con varios números cuando se utiliza el selector de contactos
  • ListView Sombra de artículo + selector personalizado
  • Deshabilitar el resaltado de GridView de Android completamente (deshabilitar la selección)
  • Cómo cambiar textColor de un botón de XML en Android?
  • Cambio de relleno en el selector
  • Archivo XML válido da un error "no se pudo analizar" en Android ADT
  • Android: Cómo hacer un selector desplegable
  • Android Selector Drawable no funciona con atributos
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.