วิธีการรับโฮสต์กิจกรรมจากมุมมอง


187

ฉันมีActivity3 EditTextและมุมมองที่กำหนดเองซึ่งทำหน้าที่แป้นพิมพ์พิเศษเพื่อเพิ่มข้อมูลเข้าไปในEditTexts

ขณะนี้ฉันกำลังส่งผ่านActivityมุมมองเพื่อที่ฉันจะได้รับข้อความแก้ไขที่มุ่งเน้นในขณะนี้และอัปเดตเนื้อหาจากแป้นพิมพ์ที่กำหนดเอง

มีวิธีการอ้างอิงกิจกรรมหลักและรับการเน้นในขณะนี้EditTextโดยไม่ต้องผ่านกิจกรรมในมุมมองหรือไม่


7
คำตอบที่ถูกต้องคือโดย gomino
djunod

คำตอบ:


305

ฉันเพิ่งดึงซอร์สโค้ดนั้นจาก MediaRouter ในห้องสมุดสนับสนุนอย่างเป็นทางการและจนถึงตอนนี้ก็ใช้งานได้ดี:

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

13
ในขณะที่? ทำไมในขณะที่
Jakob Eriksson

9
มันเป็นเพียงวิธีที่จะทำให้เนื้อหาทั้งหมดที่อยู่ในร่องลึกลงไปจนกระทั่งพบกิจกรรมหรือออกจากลูปเมื่อพบบริบทรูท ทำให้บริบทรูทจะมีค่าเป็นโมฆะ baseContext ซึ่งนำไปสู่จุดสิ้นสุดของลูป
Gomino

1
ดีมาก ! ฉันแทนที่ (กิจกรรม) getContext ()) ด้วย getActivity () และใช้งานได้ดี .... ขอบคุณ
Christian

ตามที่ได้รับแจ้ง getContext () อาจไม่แสดงวัตถุกิจกรรมเสมอหากมุมมองของคุณไม่ได้ถูกเรียกจากบริบทของกิจกรรม เช่นไม่ทำงานสำหรับมุมมองที่กำหนดเอง
Tohid

@AbhinavSaxena คุณช่วยยกตัวอย่างที่รหัสนี้จะล้มเหลวได้ไหม? แม้ว่าเมธอดจะส่งคืนค่า null เอง แต่ก็ไม่ควรไปที่นั่น
Tiago

168

วิธีการต่อไปนี้อาจช่วยคุณได้

  1. Activity host = (Activity) view.getContext(); และ
  2. view.isFocused()

35
อย่าลืมว่าgetContext()อาจไม่ส่งคืนวัตถุกิจกรรมเสมอหากมุมมองของคุณไม่ได้ถูกเรียกจากบริบทของกิจกรรม ตรวจสอบให้แน่ใจว่าได้วางแผนล่วงหน้าแล้วและให้ทางเลือกที่เหมาะสม
Dzhuneyt

1
@WordPressDeveloper - สามารถสร้างมุมมองโดยไม่มีกิจกรรมได้อย่างไร คุณหมายถึงมุมมองระยะไกล? มีมุมมองอื่นที่สร้างขึ้นนอกกิจกรรมหรือไม่
AlikElzin-kilaka

1
@kilaka Widgets, Fragments, RemoteViews, LayoutInflaters เป็นทุกกรณีที่คุณอาจสร้างมุมมองที่ไม่เชื่อมโยงกับกิจกรรม
Dzhuneyt

4
@WordPressDeveloper - เมื่อคุณสร้างมุมมองในส่วนย่อยบริบทก็ยังคงเป็นกิจกรรม แฟรกเมนต์สามารถอยู่ได้เฉพาะในกิจกรรม
AlikElzin-kilaka

24
นี่เป็นนักแสดงที่อันตรายมาก มีโอกาสที่ดีคือ (ถ้าคุณกำลังใช้ AppCompat) ที่บริบทที่คุณได้เป็นห่อหล่อสิ่งที่ต้องการContextThemeWrapperเพื่อจะโยนActivity ClassCastExceptionคุณจะต้องมีวิธีการแกะบริบทฐาน (ซึ่งจะควรจะเป็นกิจกรรม) ContextThemeWrapperซึ่งในตัวเองเป็นสิ่งที่อันตรายเช่นมีรุ่นพื้นเมืองและของ
alex

12

ฉันชอบวิธีแก้ปัญหานี้เขียนใน 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;
}

1
ขอบคุณขอบคุณจริง ๆ สำหรับกิจกรรมสแกนที่ดีนี้ใน 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;
    }
}

นี่ไม่ใช่คำตอบที่มีประสิทธิภาพเนื่องจากมีโอกาสที่จะได้รับโมฆะเมื่อส่งคืนจากฟังก์ชันนี้ คำตอบของฉันสามารถนำไปใช้ได้ในระดับสากลแม้ว่าจะผ่านการทำงานหนักและความเข้าใจ: stackoverflow.com/a/51077569/787399
Abhinav Saxena

-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อาจจะกลับมาContextThemeWrapperดังนั้นมุมมองไม่สามารถเข้าถึงกิจกรรมได้โดยตรงอีกต่อไป แต่คุณจะต้องค้นหาบริบทหลักซ้ำจนกว่าคุณจะพบกิจกรรมหลักหรือใช้วิธีที่ฉันให้ไว้ในคำตอบนี้
Sebas LG

-1

คุณสมบัติส่วนขยาย Kotlin สำหรับ View เพื่อดึงกิจกรรมหลัก:

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 บริบทรูทจะมี null baseContext ดังนั้นการติดตั้งของคุณอาจทำให้ ClassCastException เกิดขึ้นในกรณีนี้
David Miguel

นี่คือทางออกเก่า ดีกว่าที่จะใช้วิธีแก้ปัญหาโดย @Vlad
Fedir Tsapana

-1

@Override บูลีนสาธารณะควรOverrideUrlLoading (มุมมอง WebView, คำขอ WebResourceRequest) {ถ้า (request.getUrl (). getHost (). getHost (). startsWith ("pay.google.com")) {เจตนาเจตนา = เจตนาใหม่ = เจตนาใหม่ (เจตนา ()); view.getContext () startActivity (เจตนา). กลับจริง } ... ... }


1
สวัสดีและยินดีต้อนรับสู่ Stack Overflow โปรดอธิบายคำตอบของคุณมากกว่าตัวอย่างโค้ด ดูคำตอบอื่น ๆ เช่น
Itamar Mushkin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.