問題描述:
如果一個 View 繪制于某個 Activity 的 ContentView 上, 那它的 Context 一定是和這個 Activity 相關聯的. 因此我們想在 View 中直接用 Activity 方法時 (最常用的應該就是 Activity.startActivity() 方法了), 不必再向 View 中傳遞 Activity 對象.
一般在 View 中獲取這個 Activity 對象都是簡單的用下面代碼就可以了:
Activity activity = (Activity) getContext();
但在 View 繼承自 AppCompat 系的 View 時 (比如 AppCompatTextView, AppCompatImageView), 下面方法可能會得到下面異常:
View view1 = ((Activity) view.getContext()).getLayoutInflater().inflate(R.layout.date_dialog, null);
**java.lang.ClassCastException: android.support.v7.widget.TintContextWrapper cannot be cast to ...Activity**
問題解決:
知道原因就簡單了. 可以簡單的用 ContextWrapper.getBaseContext()
得到這個 Activity. 但其實一層層的從 ContextWrapper 中把 Activity 剝出來更保險:
/**
* try get host activity from view.
* views hosted on floating window like dialog and toast will sure return null.
* @return host activity; or null if not available
*/
public static Activity getActivityFromView(View view) {
Context context = view.getContext();
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
return (Activity) context;
}
context = ((ContextWrapper) context).getBaseContext();
}
return null;
}
如上方法可以通用的解決從 View 中獲取 Activity 的問題.
事實上, 谷歌 v7 包中的 Android.support.v7.app.MediaRouteButton
就是這么干的.