Làm thế nào để có được lưu trữ Hoạt động từ một khung nhìn?


186

Tôi có Activity3 EditTextgiây và chế độ xem tùy chỉnh hoạt động một bàn phím chuyên dụng để thêm thông tin vào EditTexts.

Hiện tại tôi đang chuyển qua Activitychế độ xem để tôi có thể nhận được văn bản chỉnh sửa hiện đang tập trung và cập nhật nội dung từ bàn phím tùy chỉnh.

Có cách nào để tham chiếu hoạt động của phụ huynh và nhận được sự tập trung hiện tại EditTextmà không chuyển hoạt động vào chế độ xem không?


7
Câu trả lời đúng là bởi gomino.
djunod

Câu trả lời:


300

Tôi mới lấy mã nguồn đó từ MediaRouter trong thư viện hỗ trợ chính thức và cho đến nay nó vẫn hoạt động tốt:

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

12
trong khi? tại sao trong khi
Jakob Eriksson

9
Đó chỉ là một cách để tạo ra tất cả bối cảnh cơ bản, cho đến khi tìm thấy hoạt động hoặc thoát khỏi vòng lặp khi tìm thấy bối cảnh gốc. Nguyên nhân bối cảnh gốc sẽ có một cơ sở nullContext, dẫn đến kết thúc vòng lặp.
Gomino

1
Rất tốt ! Tôi đã thay thế ((Hoạt động) getContext ()) bằng getActivity () và nó hoạt động tốt .... Cảm ơn
Christian

như đã nói, getContext () không phải lúc nào cũng đại diện cho một đối tượng Activity nếu Chế độ xem của bạn không được gọi từ ngữ cảnh Hoạt động. Ví dụ: nó không hoạt động cho các chế độ xem tùy chỉnh.
Tohid

@AbhinavSaxena Bạn có thể cho chúng tôi một ví dụ về việc mã này sẽ thất bại không? Mặc dù phương thức tự trả về null nhưng nó không bao giờ nên đến đó.
Tiago

168

phương pháp sau đây có thể giúp bạn

  1. Activity host = (Activity) view.getContext(); và
  2. view.isFocused()

34
Chỉ cần đừng quên rằng getContext()có thể không phải lúc nào cũng trả về một đối tượng Hoạt động nếu Chế độ xem của bạn không được gọi từ ngữ cảnh Hoạt động. Hãy chắc chắn lập kế hoạch này trước và cung cấp một dự phòng thích hợp.
Dzhuneyt

1
@WordPressDeveloper - Làm thế nào một khung nhìn có thể được tạo mà không có hoạt động? Ý bạn là xem từ xa? Có các trường hợp khác về chế độ xem được tạo bên ngoài Hoạt động không?
AlikElzin-kilaka

1
@kilaka Widgets, Fragment, RemoteViews, LayoutInflaters là tất cả các trường hợp bạn có thể tạo chế độ xem không gắn với Hoạt động.
Dzhuneyt

4
@WordPressDeveloper - Khi bạn tạo chế độ xem trong một đoạn, bối cảnh vẫn là hoạt động. Các mảnh vỡ chỉ có thể nằm trong Hoạt động.
AlikElzin-kilaka

24
Đây là một diễn viên khá nguy hiểm để thực hiện. Có một cơ hội tốt (nếu bạn đang sử dụng appcompat) mà bối cảnh mà bạn đã có được gói, đúc một cái gì đó giống như một ContextThemeWrapperđể Activitysẽ ném một ClassCastException. Bạn sẽ cần một cách để mở khóa bối cảnh cơ bản (sẽ là một Hoạt động), bản thân nó rất nguy hiểm vì có phiên bản gốc và v7 ContextThemeWrapper.
alex

9

Tôi thích giải pháp này được viết bằng Kotlin

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

Sử dụng trong Viewlớp

context.activity()

Mã dịch ngược:

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;
}

cảm ơn, thực sự đánh giá cao nó cho hoạt động quét tuyệt vời này trên kotlin
mochadwi

8

Tôi đã lấy câu trả lời của Gomino và sửa đổi nó để phù hợp hoàn hảo với myUtils.java để tôi có thể sử dụng nó ở bất cứ đâu và bất cứ khi nào tôi cần. Hy vọng ai đó thấy nó hữu ích :)

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;
    }
}

Đây không phải là câu trả lời hiệu quả, vì có cơ hội nhận được null khi được trả về từ chức năng này. Câu trả lời của tôi được áp dụng phổ biến, mặc dù thông qua một số công việc khó khăn và hiểu biết: stackoverflow.com/a/51077569/787399
Abhinav Saxena

-1

Trong Android 7+, chế độ xem không có quyền truy cập vào hoạt động kèm theo nữa, vì vậy view.getContext()không thể chuyển sang Hoạt động nữa.

Thay vào đó, mã dưới đây hoạt động trong Android 7+ và 6:

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

6
"Trong Android 7+, chế độ xem không có quyền truy cập vào hoạt động kèm theo nữa, vì vậy view.getContext () không thể được chuyển sang Hoạt động" Bất kỳ tham chiếu nào?
Đồng nghiệp đơn giản

@SimpleFellow như đã đề cập trong các nhận xét khác, getContextcó thể sẽ trả về một ContextThemeWrappervì vậy Chế độ xem không có quyền truy cập trực tiếp vào Hoạt động nữa. Thay vào đó, bạn phải tìm kiếm đệ quy qua ngữ cảnh cha mẹ cho đến khi bạn tìm thấy Hoạt động chính hoặc sử dụng phương pháp tôi đã cung cấp trong câu trả lời này.
Sabas LG

-1

Thuộc tính mở rộng của Kotlin cho Chế độ xem để truy xuất hoạt động chính:

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
    }
}

Bạn có thể thay thế hai ifbằng whenisInstance()bằng !is ContextWrapperhoặcis Activity
David Miguel

Theo @Gomino, bối cảnh gốc sẽ có một cơ sở nullContext. Vì vậy, việc triển khai của bạn có thể tạo ra ClassCastException trong trường hợp này
David Miguel

Đây là giải pháp cũ. Sử dụng giải pháp tốt hơn bởi
@Vlad

-1

@Override boolean công khai nênOverrideUrlLoading (Chế độ xem WebView, yêu cầu WebResourceRequest) {if (request.getUrl (). Gethost (). StartedWith ("pay.google.com")) {Ý định = ý định mới (Intent.ACTION_VIEW ()); view.getContext (). startActivity (ý định); trả lại đúng sự thật; } ... ...}


1
Xin chào, và chào mừng bạn đến với Stack Overflow. vui lòng giải thích câu trả lời của bạn không chỉ là mẫu mã; nhìn vào các câu trả lời khác chẳng hạn.
Nấm Itamar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.