如何从视图中获取托管活动?
Posted
技术标签:
【中文标题】如何从视图中获取托管活动?【英文标题】:How to get hosting Activity from a view? 【发布时间】:2012-01-06 18:40:41 【问题描述】:我有一个 Activity
和 3 个 EditText
s 和一个自定义视图,它充当专用键盘以将信息添加到 EditText
s。
目前我将Activity
传递到视图中,以便我可以获取当前聚焦的编辑文本并从自定义键盘更新内容。
有没有一种方法可以引用父活动并获得当前关注的EditText
而无需将活动传递到视图中?
【问题讨论】:
正确答案是gomino。 【参考方案1】:我刚刚从 official support library 的 MediaRouter 中提取了该源代码,到目前为止它运行良好:
private Activity getActivity()
Context context = getContext();
while (context instanceof ContextWrapper)
if (context instanceof Activity)
return (Activity)context;
context = ((ContextWrapper)context).getBaseContext();
return null;
【讨论】:
同时?为什么? 这只是一种在所有基本上下文中冒泡的方法,直到找到活动,或者在找到根上下文时退出循环。因为根上下文会有一个空的baseContext,导致循环结束。 非常好!我用 getActivity() 替换了 ((Activity) getContext()) ,它工作正常......谢谢 如前所述,如果您的 View 不是从 Activity 上下文调用的,则 getContext() 可能并不总是代表 Activity 对象。例如。它不适用于自定义视图。 @AbhinavSaxena 你能给我们举一个这个代码会失败的例子吗?即使方法本身返回 null,它也不应该到达那里。【参考方案2】:以下方法可能对您有所帮助
Activity host = (Activity) view.getContext()
;和
view.isFocused()
【讨论】:
请不要忘记,如果您的 View 不是从 Activity 上下文调用的,getContext()
可能并不总是返回 Activity 对象。请务必提前计划并提供适当的后备方案。
@WordPressDeveloper - 如何在没有活动的情况下创建视图?你是说远程视图?是否还有其他在 Activity 之外创建视图的情况?
@kilaka Widgets、Fragments、RemoteViews、LayoutInflaters 都是您可以创建不绑定到 Activity 的视图的情况。
@WordPressDeveloper - 当您在片段中创建视图时,它的上下文仍然是活动。片段只能驻留在活动中。
这是一个非常危险的演员阵容。很有可能(如果您正在使用 appcompat)您所获得的上下文已被包装,将类似 ContextThemeWrapper
的内容转换为 Activity
将抛出 ClassCastException
。您需要一种方法来解开基本上下文(应该是一个 Activity),这本身就是危险的,因为有一个原生和 v7 版本的 ContextThemeWrapper
。【参考方案3】:
更新
tailrec fun Context.getActivity(): Activity? = this as? Activity
?: (this as? ContextWrapper)?.baseContext?.getActivity()
感谢@Westy92
用法:
context.getActivity()
【讨论】:
谢谢,非常感谢在 kotlin 上进行的这个不错的扫描活动 你也可以这样做:tailrec fun Context?.getActivity(): Activity? = this as? Activity ?: (this as? ContextWrapper)?.baseContext?.getActivity()
【参考方案4】:
我采用了Gomino 的answer 并对其进行了修改以完全适合myUtils.java,因此我可以随时随地使用它。希望有人觉得它有帮助:)
abstract class myUtils
public static Activity getActivity(View view)
Context context = view.getContext();
while (context instanceof ContextWrapper)
if (context instanceof Activity)
return (Activity)context;
context = ((ContextWrapper)context).getBaseContext();
return null;
【讨论】:
这不是有效的答案,因为有机会从这个函数返回 null。我的回答是普遍适用的,尽管通过一些努力和理解:***.com/a/51077569/787399【参考方案5】:请注意,如果您知道您的视图在 Fragment
内,您可以这样做:
FragmentManager.findFragment(this).getActivity();
从你的onAttachedToWindow
或onDraw
调用它,你不能更早调用它(例如onFinishInflate
),否则你会得到一个例外。
如果您不确定您的视图是否在 Fragment
内,请参阅其他答案,例如Gomino,只是想把它扔在那里。
【讨论】:
【参考方案6】:用于 View 检索父活动的 Kotlin 扩展属性:
val View.activity: Activity?
get()
var ctx = context
while (true)
if (!ContextWrapper::class.java.isInstance(ctx))
return null
if (Activity::class.java.isInstance(ctx))
return ctx as Activity
ctx = (ctx as ContextWrapper).baseContext
【讨论】:
您可以将两个if
替换为when
,将isInstance()
替换为!is ContextWrapper
或is Activity
根据@Gomino,根上下文将有一个空的baseContext。因此,在这种情况下,您的实现可能会抛出 ClassCastException
这是旧的解决方案。更好地使用@Vlad 的解决方案【参考方案7】:
在 android 7+ 中,视图无法再访问封闭的 Activity,因此无法再将 view.getContext()
强制转换为 Activity。
相反,以下代码适用于 Android 7+ 和 6:
private static Activity getActivity(final View view)
return (Activity) view.findViewById(android.R.id.content).getContext();
【讨论】:
“在 Android 7+ 中,视图无法再访问封闭的 Activity,因此无法将 view.getContext() 强制转换为 Activity” 有什么参考吗? @SimpleFellow 正如其他 cmets 中提到的那样,getContext
可能会返回一个 ContextThemeWrapper
,因此 View 不再可以直接访问 Activity。相反,您必须递归搜索父上下文,直到找到父 Activity 或使用我在此答案中提供的方法。【参考方案8】:
@覆盖 public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) if(request.getUrl().getHost().startsWith("pay.google.com")) Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl()); view.getContext().startActivity(intent); 返回真; ... ...
【讨论】:
嗨,欢迎来到 Stack Overflow。请解释您的答案,而不仅仅是代码示例;例如,看看其他答案。以上是关于如何从视图中获取托管活动?的主要内容,如果未能解决你的问题,请参考以下文章
如何从回收站视图 android 中传递一个 url onclick 项目并 onclick 获取位置 dipaly 在另一个活动中的 url