16

Bir Android uygulamasını yeni destek kitaplığına (support-v4: 21.0.0) yüklemeye çalışıyorum ve bir geçiş ile Fragments'tan Etkinlikler başlatma konusunda sorun yaşıyorum . Etkinlikler için çalışıyorGeçiş'i kullanarak Parçadan Etkinliği Başlat (API 21 desteği)

Bundle options = ActivityOptionsCompat.makeSceneTransitionAnimation(this).toBundle(); 
ActivityCompat.startActivityForResult(this, intent, REQUEST_SOMETHING, options); 

: Benim Etkinlikler In

, şöyle bir şey yapıyorum. Ancak, ben gibi Parçası Düşen benzer bir şey yapmak çalışırsanız:

Activity activity = getActivity(); 
Bundle options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity).toBundle(); 
ActivityCompat.startActivityForResult(activity, intent, REQUEST_SOMETHING, options); 

o onActivityResult() Fragment çağrısında olmadığını çıkıyor, ama sadece kapsayan etkinlik. Destek kütüphanesinde, Bundle öğesinin bir parametre olarak startActivityForResult() parametresini gerçek bir Fragman'a iletmek için hiçbir şey bulamadım ve bu Fragmanda onActivityResult()'a geri dönmesini sağlayın. Mümkün mü?

En basit çözüm, Etkinliğin kendisinde bulunan tüm onActivityResult() çağrılarını ele almak olacaktır, ancak bunu yapmamayı tercih ediyorum çünkü bu geribildirimi alabilen bir miktar olası Fragmanlar var.

Yardım memnuniyetle karşılanır. Teşekkürler!

cevap

14

Ne yazık ki, ActivityCompat.startActivityForResult() (Alex Lockwood'un cevaba bakınız) Fragments oldukça doğru çalışmıyor. Birkaç hafta boyunca, Google'ın Fragman'ın startActivityForResult() numaralı uygulamasına eşdeğer bir ActivityCompat yöntemini nasıl vermediğine şaşıyorum. Ne düşünüyorlardı?! Ama sonra bir fikrim vardı: Metodun gerçekte nasıl uygulandığına bakalım. Nitekim olarak

, Fragment startActivityForResult() Faaliyete birinden farklıdır ( here bakınız):

public void startActivityForResult(Intent intent, int requestCode) { 
    if (mActivity == null) { 
     throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 
    } 
    mActivity.startActivityFromFragment(this, intent, requestCode); 
} 

Şimdi startActivityFromFragment() görünüyor bu (here bakınız) gibi:

public void startActivityFromFragment(Fragment fragment, Intent intent, 
     int requestCode) { 
    if (requestCode == -1) { 
     super.startActivityForResult(intent, -1); 
     return; 
    } 
    if ((requestCode&0xffff0000) != 0) { 
     throw new IllegalArgumentException("Can only use lower 16 bits for requestCode"); 
    } 
    super.startActivityForResult(intent, 
           ((fragment.mIndex + 1) << 16) + (requestCode & 0xffff)); 
} 

hakkında Sadece çağıran Fragman'ın onActivityResult() sonradan çağrıldığından emin olmak için istek kodunda bazı garip bayt kaydırma kullanır. Artık ActivityCompat, startActivityFromFragment()'u sağladığından, tek seçenek bunu kendiniz uygulamaktır. Yansıma, paket özel alanına mIndex erişmek için gereklidir.

public static void startActivityForResult(Fragment fragment, Intent intent, 
              int requestCode, Bundle options) { 
    if (Build.VERSION.SDK_INT >= 16) { 
     if ((requestCode & 0xffff0000) != 0) { 
      throw new IllegalArgumentException("Can only use lower 16 bits" + 
               " for requestCode"); 
     } 
     if (requestCode != -1) { 
      try { 
       Field mIndex = Fragment.class.getDeclaredField("mIndex"); 
       mIndex.setAccessible(true); 
       requestCode = ((mIndex.getInt(this) + 1) << 16) + (requestCode & 0xffff); 
      } catch (NoSuchFieldException | IllegalAccessException e) { 
       throw new RuntimeException(e); 
      } 
     } 
     ActivityCompat.startActivityForResult(fragment.getActivity(), intent, 
               requestCode, options); 
    } else { 
     fragment.getActivity().startActivityFromFragment(this, intent, requestCode); 
    } 
} 

Bu yöntemi istediğiniz yere kopyalayın ve Parçanızdan kullanın. Onun onActivityResult() olması gerektiği gibi çağrılacak.

GÜNCELLEME: Destek kütüphane v23.2 yayımlanan ve startActivityFromFragment(Fragment fragment, Intent intent, int requestCode, Bundle options) şimdi iş yok gibi görünüyor edildi :)

+0

için bir faaliyet başlatmaya başladığınız son yöntemi kullanarak benim için çalıştım - tamamen temiz bulmama rağmen çözüme çok teşekkürler, öyleyse sadece Google'ın garip byte değişimi ile ilgili hiçbir şeyi değiştirmediğini umalım. – user2302510

+2

Aramanın Aktiviteden yapılması ve daha sonra etkinlikten Parçanın sonucuna geçmesi ancak aktiviteme (fragman nedeniyle) bağlı parçaların bir kısmına sahip olmak daha temiz olurdu. – user2302510

+0

@ user2302510 Tam olarak, Bunu kendi başınıza halletmek gerçekten kafa karıştırıcı olur. Memnun kaldım! – 0101100101

2

ActivityCompat#startActivityForResult() yöntemi, etkinliğin startActivityForResult(Intent, Bundle) yöntemi için yalnızca bir proxy'dir. Yöntemin bir parça sınıfının içinden çağrılması, Fragment'un onActivityResult()'un sonuçta öğrendiğinizden emin olacağı anlamına gelmez. Çerçeve, çağrının hangi sınıftan kaynaklandığını bilmenin yolunu bilmektedir ... bu durumda tek doğru davranış, Activity'un onActivityResult() yöntemini çağırmak olacaktır.

En iyi seçenek, yayınınızda önerdiğiniz gibi etkinliğin onActivityResult() yöntemindeki her şeyi işlemek gibi olacaktır.

+0

neden anlamak Bu oluyor, ama bu daha az rahatsız edici değil. Bu, Destek kütüphanesinde bulunmayan bir şey midir, yoksa yerel Fragmanlar ile de yapılamaz mı? Gelecekte bu özelliği eklemeleri umarım. –

+1

Sadece 'Fragment' '' startActivityForResult (Intent, int, Bundle) 'yöntemini denediniz mi? –

0

Bir dinleyici arabirimi veya yalnızca parçanızda bir ortak işlev oluşturabilir ve etkinliğin dinleyiciye veya parçanın genel yöntemine ilişkin aldığınız argümanları harekete geçirerek istediğiniz işi gerçekleştirebilirsiniz. Orada.

0

basit bir yolu: Fragment

:

ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(); 

this.startActivityFromFragment(this, intent, requestCode, options);