Android支持库23.4.0:android.support.v7.widget.TintContextWrapper不能转换为Activity

所以我更新到最新的支持库,并得到了一个崩溃,我无法修复。 我的build.gradle现在有这些依赖关系:

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... } 

我有一个工作监听器,用来捕捉点击并启动一个新的活动。 这在支持库v。23.1.0中工作正常,但在23.4.0(和23.3.0)中没有。

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

这个监听器简单地连接到一个ImageButton ,然后Button的颜色被着色,如下所示:

 Ingredient ingredient = getIngredient(); myImageButton.setOnClickListener(new IngredientItemOnClickListener(ingredient)); Drawable drawable = Tinting.tint(myActivity, R.drawable.my_icon, R.color.red); myImageButton.setImageDrawable(drawable); 

Tinting.tint()是我自己的着色function:

 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; } } 

以前,当我点击button一切按预期工作,但现在的视图的上下文似乎已经改变到TintContextWrapper ,我可以find一点信息。 我发现这个问题 ,但项目成员build议在这里问StackOverflow,所以在这里。

我试过了什么?

由于Google问题中的项目成员声明您将需要从包装的上下文中获取活动。 我试图铸造到TintContextWrapper而不是MyActivity ,这工作正常,但我不知道如何从TintContextWrapper获得TintContextWrapper

所以我的问题是:

  1. 我怎样才能从TintContextWrapper获得TintContextWrapper
  2. 为什么我的ImageButton突然包装在TintContextWrapper
  3. 这种行为应该是真的吗?

ImageButton在xml中的定义很简单:

 <ImageButton android:id="@+id/my_id" android:src="@drawable/my_icon" /> 

堆栈跟踪:

 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) 

Solutions Collecting From Web of "Android支持库23.4.0:android.support.v7.widget.TintContextWrapper不能转换为Activity"

  1. 两个活动n TintContextWRapper来自ContextWrapperContextWrapper有一个方法getBaseContext() 。 创build一个检查instanceof WrapContext ,获取基本上下文,然后检查instanceof Activity的循环方法应该很容易。 (如果你在这里有这方法评论的问题,我会挖掘我的一些项目,并粘贴到这里)

  2. 因为AppCompat包装你的上下文能够注入“compat”视图和“compat”着色和其他“compat”的东西。 这很正常。

  3. 是。 AppCompat就是这样做的。

@Krøllebølle

Android支持库23.4.0:android.support.v7.widget.TintContextWrapper不能转换为Activity

回答你的问题是:首先你的点击事件代码应该是这样的:

 @Override public void onClick(View view) { MyActivity myActivity = getRequiredActivity(view); myActivity.showIngredientActivity(mIngredient); } 

然后编写函数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; 

}

和你的崩溃/例外是固定的:)

我的build议是将您的活动的引用传递到TintContextWrapper以避免与TintContextWrapper的问题。 给你的课一个MyActivity的参考很简单,避免了可能的转换问题。

你可以试试

 Activity activity = (Activity) view.getRootView().getContext() 

获取包含此视图的上下文,而不包含android.support.v7.widget.TintContextWrapper的包装。

  1. 我怎样才能从TintContextWrapper获得MyActivity?

你真的不应该。 不保证视图的上下文将是一个活动 – 绝对不是一个具体的活动。 你在哪里设置你的OnClickListener? 我假设在你设置监听器的地方,你将有权访问活动。 例如,如果您正在从一个Activity设置侦听器:

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

它在更新Android支持库后为我工作。

我面临同样的问题,并与解决
– Android支持库,修订版24.2.1(2016年9月)
– compileSdkVersion 24
– buildToolsVersion“24.0.3”