ビューからホスティングアクティビティを取得するにはどうすればよいですか?


186

私はActivity3つEditTextのsと、sに情報を追加するための専用キーボードとして機能するカスタムビューを持っていEditTextます。

現在Activity、ビューにを渡して、現在フォーカスされている編集テキストを取得し、カスタムキーボードから内容を更新できるようにしています。

親アクティビティを参照してEditText、アクティビティをビューに渡さずに現在フォーカスされている方法はありますか?


7
正解はgominoです。
djunod

回答:


300

私は公式のサポートライブラリの MediaRouterからそのソースコードをプルしただけで、これまでのところ正常に機能します。

private Activity getActivity() {
    Context context = getContext();
    while (context instanceof ContextWrapper) {
        if (context instanceof Activity) {
            return (Activity)context;
        }
        context = ((ContextWrapper)context).getBaseContext();
    }
    return null;
}

12
その間?なぜ?
Jakob Eriksson

9
これは、アクティビティが見つかるまですべてのベースコンテキストを介してバブルアップするか、ルートコンテキストが見つかるとループを終了する方法にすぎません。ルートコンテキストがnullのbaseContextを持ち、ループが終了する原因になります。
Gomino 2016

1
とても良い !((Activity)getContext())をgetActivity()に置き換えました。正常に動作します。ありがとう
クリスチャン

言われているように、ビューがアクティビティコンテキストから呼び出されない場合、getContext()は常にアクティビティオブジェクトを表すとは限りません。たとえば、カスタムビューでは機能しません。
Tohid

@AbhinavSaxenaこのコードが失敗する例を教えてください。メソッド自体がnullを返す場合でも、そこに到達することはありません。
ティアゴ

168

次の方法が役立つかもしれません

  1. Activity host = (Activity) view.getContext(); そして
  2. view.isFocused()

34
getContext()ビューがActivityコンテキストから呼び出されない場合、Activityオブジェクトが常に返されるとは限らないことを忘れないでください。これを前もって計画し、適切なフォールバックを提供してください。
Dzhuneyt 2013

1
@WordPressDeveloper-アクティビティなしでビューを作成するにはどうすればよいですか?リモートビューですか?アクティビティの外で作成されるビューの他のケースはありますか?
AlikElzin-kilaka 2014年

1
@kilakaウィジェット、フラグメント、RemoteViews、LayoutInflatersはすべて、アクティビティに関連付けられていないビューを作成する場合です。
Dzhuneyt 2014年

4
@WordPressDeveloper-フラグメントでビューを作成するとき、そのコンテキストはまだアクティビティです。フラグメントはアクティビティにのみ存在できます。
AlikElzin-kilaka 2014年

24
これはかなり危険なキャストです。(appcompatを使用している場合)取得したコンテキストがラップされている可能性が高く、ContextThemeWrappertoのようなものをキャストするとActivityがスローされますClassCastException。ベースコンテキスト(アクティビティである必要があります)を展開する方法が必要です。これには、ネイティブのv7バージョンのがあるため、それ自体が危険ですContextThemeWrapper
アレックス、2015

9

Kotlinで書かれたこのソリューションが好き

tailrec fun Context?.activity(): Activity? = when (this) {
    is Activity -> this
    else -> (this as? ContextWrapper)?.baseContext?.activity()
}

Viewクラスでの使用

context.activity()

逆コンパイルされたコード:

public static final Activity activity(Context context) {
    while (!(context instanceof Activity)) {
        if (!(context instanceof ContextWrapper)) {
            context = null;
        }
        ContextWrapper contextWrapper = (ContextWrapper) context;
        if (contextWrapper == null) {
            return null;
        }
        context = contextWrapper.getBaseContext();
        if (context == null) {
            return null;
        }
    }
    return (Activity) context;
}

おかげで、kotlinでのこの素晴らしいスキャンアクティビティに本当に感謝しています
mochadwi

8

Gomino回答を取り、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を取得する可能性があるため、これは効果的な答えではありません。私の答えは、いくつかのハードワークと理解を通してですが、普遍的に適用できます:stackoverflow.com/a/51077569/787399
Abhinav Saxena '29

-1

Android 7以降では、ビューは外側のアクティビティにアクセスview.getContext()できなくなったため、アクティビティにキャストできなくなりました。

代わりに、以下のコードはAndroid 7以降および6で機能します。

private static Activity getActivity(final View view) {
    return (Activity) view.findViewById(android.R.id.content).getContext();
}

6
「Android 7以降では、ビューは囲んでいるアクティビティにアクセスできなくなったため、view.getContext()をアクティビティにキャストできません」 参照はありますか?
シンプルフェロー

他のコメントで述べた@SimpleFellow getContextはおそらくaを返すContextThemeWrapperため、ビューはアクティビティに直接アクセスできなくなります。代わりに、親アクティビティが見つかるか、この回答で提供した方法を使用するまで、親コンテキストを再帰的に検索する必要があります。
Sebas LG 2019

-1

親アクティビティを取得するためのビューの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
    }
}

あなたは2置き換えることができif持つwhenisInstance()して!is ContextWrapperis Activity
デヴィッド・ミゲル

@Gominoによると、ルートコンテキストにはnullのbaseContextがあります。したがって、この場合、実装はClassCastExceptionをスローする可能性があります
David Miguel

これは古いソリューションです。@Vladによるソリューションを使用する方が良い
Fedir Tsapana

-1

@Override 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); trueを返します。} ... ...}


1
こんにちは、Stack Overflowへようこそ。コードサンプルだけでなく、あなたの答えを説明してください。たとえば、他の答えを見てください。
Itamar Mushkin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.