Bagaimana cara mendapatkan Kegiatan hosting dari tampilan?

187

Saya memiliki Activitydengan 3 EditTextdan tampilan kustom yang bertindak keyboard khusus untuk menambahkan informasi ke dalam EditText.

Saat ini saya meneruskan Activitytampilan sehingga saya bisa mendapatkan teks edit yang saat ini difokuskan dan memperbarui konten dari keyboard khusus.

Apakah ada cara mereferensikan aktivitas orang tua dan membuat fokus saat ini EditTexttanpa meneruskan aktivitas ke tampilan?

mAndroid
sumber
7
Jawaban yang benar adalah oleh gomino.
Djunod

Jawaban:

305

Saya baru saja menarik kode sumber dari MediaRouter di perpustakaan dukungan resmi dan sejauh ini berfungsi dengan baik:

private Activity getActivity() {
    Context context = getContext();
    while (context instanceof ContextWrapper) {
        if (context instanceof Activity) {
            return (Activity)context;
        }
        context = ((ContextWrapper)context).getBaseContext();
    }
    return null;
}
Gomino
sumber
13
sementara? mengapa sementara?
Jakob Eriksson
9
Itu hanya cara untuk menggelembung melalui semua konteks dasar, sampai aktivitas ditemukan, atau keluar dari loop ketika konteks root ditemukan. Karena konteks root akan memiliki baseContext nol, yang mengarah ke akhir loop.
Gomino
1
Baik sekali ! Saya mengganti ((Aktivitas) getContext ()) dengan getActivity () dan berfungsi dengan baik .... Terima kasih
Christian
seperti yang telah diberitahukan, getContext () mungkin tidak selalu mewakili objek Activity jika View Anda tidak dipanggil dari konteks Activity. Misalnya tidak berfungsi untuk tampilan khusus.
Tohid
@AbhinavSaxena Bisakah Anda memberi kami contoh di mana kode ini akan gagal? Meskipun metode itu sendiri mengembalikan nol, seharusnya tidak pernah sampai di sana.
Tiago
168

metode berikut dapat membantu Anda

  1. Activity host = (Activity) view.getContext(); dan
  2. view.isFocused()
dira
sumber
35
Hanya saja jangan lupa bahwa getContext()mungkin tidak selalu mengembalikan objek Aktivitas jika Tampilan Anda tidak dipanggil dari konteks Aktivitas. Pastikan untuk merencanakan ini ke depan dan memberikan mundur yang tepat.
Dzhuneyt
1
@WordPressDeveloper - Bagaimana tampilan dapat dibuat tanpa aktivitas? Maksudmu remote view? Adakah kasus tampilan lain yang dibuat di luar Aktivitas?
AlikElzin-kilaka
1
@kilaka Widget, Fragmen, RemoteViews, LayoutInflaters adalah semua kasus di mana Anda dapat membuat tampilan yang tidak terkait dengan suatu Aktivitas.
Dzhuneyt
4
@ WordpressDeveloper - Ketika Anda membuat tampilan dalam sebuah fragmen, konteksnya masih merupakan aktivitas. Fragmen hanya dapat berada di Aktivitas.
AlikElzin-kilaka
24
Ini adalah pemeran yang cukup berbahaya. Ada peluang bagus (jika Anda menggunakan appcompat) bahwa konteks yang Anda miliki sudah dibungkus, melemparkan sesuatu seperti ContextThemeWrapperto Activityakan melempar ClassCastException. Anda perlu cara untuk membuka konteks dasar (yang seharusnya merupakan suatu Kegiatan), yang dengan sendirinya berbahaya karena ada versi asli dan v7 ContextThemeWrapper.
alex
12

Saya suka solusi ini ditulis dalam Kotlin

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

Penggunaan di Viewkelas

context.activity()

Kode yang didekompilasi:

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;
}
Vlad
sumber
1
terima kasih, sangat menghargainya untuk kegiatan pemindaian yang bagus ini di kotlin
mochadwi
8

Aku mengambil Gomino 's jawaban dan dimodifikasi untuk cocok dengan sempurna di myUtils.java sehingga saya dapat menggunakannya di mana pun dan kapan pun saya perlu. Semoga seseorang merasa terbantu :)

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;
    }
}
brownieGirl
sumber
Ini bukan jawaban yang efektif, karena ada peluang untuk mendapatkan null sebagaimana dikembalikan dari fungsi ini. Jawaban saya dapat diterapkan secara universal, meskipun melalui kerja keras dan pemahaman: stackoverflow.com/a/51077569/787399
Abhinav Saxena
-1

Di Android 7+ tampilan tidak lagi memiliki akses ke aktivitas terlampir, jadi view.getContext()tidak dapat lagi dilemparkan ke suatu Aktivitas.

Sebaliknya, kode di bawah ini berfungsi di Android 7+ dan 6:

private static Activity getActivity(final View view) {
    return (Activity) view.findViewById(android.R.id.content).getContext();
}
Sebas LG
sumber
6
"Di Android 7+ tampilan tidak lagi memiliki akses ke aktivitas penutup, jadi view.getContext () tidak dapat dilemparkan ke Aktivitas" Ada referensi?
Rekan Sederhana
@SimpleFellow sebagaimana disebutkan dalam komentar lain, getContextmungkin akan mengembalikan a ContextThemeWrappersehingga View tidak memiliki akses langsung ke Activity lagi. Sebagai gantinya, Anda harus mencari secara rekursif melalui konteks induk hingga Anda menemukan Aktivitas induk atau menggunakan metode yang saya berikan dalam jawaban ini.
Sebas LG
-1

Properti ekstensi Kotlin untuk View untuk mengambil aktivitas induk:

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
    }
}
Fedir Tsapana
sumber
Anda dapat mengganti keduanya ifdengan whendan isInstance()dengan !is ContextWrapperatauis Activity
David Miguel
Menurut @Gomino konteks root akan memiliki baseContext nol. Jadi implementasi Anda dapat melempar ClassCastException dalam kasus ini
David Miguel
Ini solusi lama. Lebih baik menggunakan solusi oleh @Vlad
Fedir Tsapana
-1

@Override boolean publik shouldOverrideUrlLoading (tampilan WebView, permintaan WebResourceRequest) {if (request.getUrl (). GetHost (). Dimulai dengan ("pay.google.com")) {Intent intent = new Intent (Intent.ACTION_VIEW, request.getUrl ()); view.getContext (). startActivity (intent); kembali benar; } ... ...}

Tomcolins Cox Violet CHilton c
sumber
1
Hai, dan selamat datang di Stack Overflow. tolong jelaskan jawaban Anda lebih dari sekadar contoh kode; lihat jawaban lain misalnya.
Itamar Mushkin