Librería de soporte de Android 23.4.0: android.support.v7.widget.TintContextWrapper no se puede publicar en Actividad
Así que me actualizé a las últimas bibliotecas de soporte, y recibí un fallo que no puedo arreglar. Mi build.gradle ahora tiene estas dependencias:
dependencies { compile 'com.android.support:appcompat-v7:23.4.0' compile 'com.android.support:gridlayout-v7:23.4.0' compile 'com.android.support:support-v4:23.4.0' compile 'com.android.support:cardview-v7:23.4.0' compile 'com.android.support:recyclerview-v7:23.4.0' compile 'com.android.support:design:23.4.0' // More stuff... }
Tuve un oyente de trabajo que se utiliza para capturar clics y comenzar una nueva actividad. Esto funcionaba bien en bibliotecas de soporte v. 23.1.0, pero no en 23.4.0 (y 23.3.0):
- Soporte para Android v7 no puede encontrar ActionBarActivity
- ¿Cómo adjunto la fuente de la Biblioteca de soporte de Android en Eclipse?
- PreferenceFragmentCompat requiere la preferenciaTheme ser fijado
- Android DialogFragment no descarta
- Obtener posición del artículo desde el adaptador personalizado
public class IngredientItemOnClickListener implements OnClickListener { private Ingredient mIngredient; public IngredientItemOnClickListener(Ingredient ingredient) { mIngredient= ingredient; } @Override public void onClick(View view) { MyActivity myActivity = (MyActivity) view.getContext(); // <-- crash here myActivity.showIngredientActivity(mIngredient); } }
Este oyente está simplemente conectado a un ImageButton
y después el color del botón está tintado, como este:
Ingredient ingredient = getIngredient(); myImageButton.setOnClickListener(new IngredientItemOnClickListener(ingredient)); Drawable drawable = Tinting.tint(myActivity, R.drawable.my_icon, R.color.red); myImageButton.setImageDrawable(drawable);
Donde Tinting.tint()
es mi propia función de teñido:
public class Tinting { @Nullable public static Drawable tint(Context context, int drawableId, int colorId) { final Drawable drawable = ContextCompat.getDrawable(context, drawableId); if (drawable != null) { final Drawable wrapped = DrawableCompat.wrap(drawable); drawable.mutate(); DrawableCompat.setTint(wrapped, ContextCompat.getColor(context, colorId)); } return drawable; } }
Anteriormente cuando hice clic en el botón todo funcionó como se esperaba, pero ahora el contexto de la vista parece haber cambiado a TintContextWrapper
que puedo encontrar poca información sobre. Encontré este problema , pero el miembro del proyecto aconseja preguntar aquí en StackOverflow, así que aquí está.
¿Qué he intentado?
Dado que el miembro del proyecto en el problema de Google declaró que tendrá que obtener la actividad del contexto envuelto. He intentado lanzar a TintContextWrapper
lugar de MyActivity
, que funciona bien, pero no puedo averiguar cómo obtener MyActivity
de TintContextWrapper
.
Así que mis preguntas son:
- ¿Cómo puedo obtener
MyActivity
deTintContextWrapper
? - ¿Por qué mi
ImageButton
repente envuelto en unTintContextWrapper
. - ¿Debería esperarse realmente este comportamiento?
Definición de ImageButton en xml es simplemente:
<ImageButton android:id="@+id/my_id" android:src="@drawable/my_icon" />
Rastro de la pila:
java.lang.ClassCastException: android.support.v7.widget.TintContextWrapper cannot be cast to com.my.app.activities.MyActivity at com.my.app.listeners.IngredientItemOnClickListener.onClick(IngredientItemOnClickListener.java:21) at android.view.View.performClick(View.java:4475) at android.view.View$PerformClick.run(View.java:18786) at android.os.Handler.handleCallback(Handler.java:730) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:176) at android.app.ActivityThread.main(ActivityThread.java:5419) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862) at dalvik.system.NativeStart.main(Native Method)
- ¿Es posible Proguard un módulo de biblioteca de Android, pero no el módulo de aplicación?
- Incluyendo list_content en el diseño de lista para conservar la funcionalidad ListFragment
- PercentRelativeLayout - falta de diseño
- Agregar un fragmento como encabezado ListView
- Android no puede cargar SupportV8 RenderScript en api <17
- Diseño del widget SearchView mediante la biblioteca de soporte v21
- Tablas de ActionBar con la biblioteca de soporte
- Parece ser un error en la biblioteca de diseño de soporte
-
Tanto la actividad n TintContextWRapper viene de
ContextWrapper
.ContextWrapper
tiene un métodogetBaseContext()
. Debería ser fácil crear un método de bucle que compruebe lainstanceof WrapContext
, obtenga el contexto base y, a continuación, compruebe lainstanceof Activity
. (Si tienes problemas con este método comentario aquí que voy a cavar en algún proyecto mío y pegar aquí a u) -
Debido a que AppCompat envuelve su contexto para poder inyectar "compat" vistas y "compat" tintado y otras cosas "compat". Eso es normal.
-
Sí. Así es como AppCompat hace su cosa.
Krøllebølle
Librería de soporte de Android 23.4.0: android.support.v7.widget.TintContextWrapper no se puede publicar en Actividad
La respuesta a usted pregunta es: primero su código del acontecimiento del tecleo debe ser como:
@Override public void onClick(View view) { MyActivity myActivity = getRequiredActivity(view); myActivity.showIngredientActivity(mIngredient); }
Y luego escribir la función getRequiredActivity ():
private Activity getRequiredActivity(View req_view) { Context context = req_view.getContext(); while (context instanceof ContextWrapper) { if (context instanceof Activity) { return (Activity)context; } context = ((ContextWrapper)context).getBaseContext(); } return null;
}
Y su Crash / Excepción es fijo 🙂
Mi sugerencia es pasar una referencia de su actividad en el onClickListener para evitar el problema con TintContextWrapper
. Dar a su clase una referencia a MyActivity
es simple y evita posibles problemas de casting.
Puedes probar
Activity activity = (Activity) view.getRootView().getContext()
Obtiene el contexto que contiene esta vista sin el contenedor de android.support.v7.widget.TintContextWrapper.
- ¿Cómo puedo obtener MyActivity de TintContextWrapper?
Realmente no deberías. No hay garantía de que el Contexto de una Vista sea una Actividad – definitivamente no es una Actividad específica. ¿Dónde está configurando su OnClickListener? Estoy asumiendo que en el lugar donde usted establece el oyente, usted tendrá acceso a la actividad. Por ejemplo, si está configurando el listener de una Actividad:
public class MainActivity extends AppCompatActivity { @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.ingredientButton).setOnClickListener( new IngredientItemOnClickListener(yourIngredient)); } void showIngredientActivity(Ingredient ingredient) { // Do your stuff } public class IngredientItemOnClickListener implements OnClickListener { private Ingredient mIngredient; public IngredientItemOnClickListener(Ingredient ingredient) { mIngredient = ingredient; } @Override public void onClick(View view) { showIngredientActivity(mIngredient); } } }
Funcionó para mí después de actualizar las bibliotecas de soporte de Android.
Me enfrenté al mismo problema y se resolvió con
– Biblioteca de soporte de Android, revisión 24.2.1 (septiembre de 2016)
– compileSdkVersion 24
– buildToolsVersion "24.0.3"
- Cómo cambiar el nombre de la aplicación en Launcher en android según el idioma seleccionado en Configuración de Teléfono?
- Tarea y proceso de Android, SingleTask y SingleInstance