16

Android 앱을 새 지원 라이브러리 (support-v4 : 21.0.0)로 이식하려고하는데 변환으로 단편에서 활동 시작하는 데 문제가 있습니다. . 활동 잘 작동전환을 사용하여 단편에서 활동 시작 (API 21 지원)

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

: 내 활동에

는, 내가 좋아하는 일을하고 있었어요. 그러나, 나는이 같은 조각과 비슷한, 수행하려고 할 경우 :

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

onActivityResult()이 조각을 요구하지 않는 것을 알 수 있지만 바깥 쪽 활동. 지원 라이브러리에서 번들 옵션을 실제 조각의 startActivityForResult()에 대한 매개 변수로 전달하고 해당 조각에서 onActivityResult()으로 콜백해야하는 항목을 찾지 못했습니다. 이것이 가능한가?

가장 간단한 해결책은 활동 자체에서 onActivityResult() 호출을 모두 처리하는 것이지만 콜백을받을 수있는 가능한 많은 조각이 있기 때문에 그렇게하지 않을 것입니다.

도움을 주시면 감사하겠습니다. 감사!

답변

14

슬프게도 ActivityCompat.startActivityForResult()Fragments (Alex Lockwood의 답변 참조)에서 제대로 작동하지 않습니다. 몇 주 동안 나는 Flements의 구현 인 startActivityForResult()에 해당하는 ActivityCompat 메쏘드를 구글이 결코주지 않았 음을 경탄했다. 그들은 무엇을 생각하고 있었습니까?! 하지만 그때 아이디어가있었습니다. 실제로이 방법이 어떻게 구현되는지 살펴 보겠습니다. 사실

이 조각에서 startActivityForResult()이 활동의 ​​것과 다른 ( here 참조)

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

지금 startActivityFromFragment() 보이는이 (here 참조)과 같은 :

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

구글 요청 코드에서 이상한 바이트 시프 팅을 사용하여 호출하는 단편의 onActivityResult() 만 나중에 호출되도록합니다. 이제 ActivityCompatstartActivityFromFragment()을 제공하지 않으므로 남은 옵션은 직접 구현하는 것입니다. 패키지 개인 필드 mIndex에 액세스하려면 반사가 필요합니다.

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

원하는 곳 어디에서나 해당 방법을 복사하여 단편에서 사용할 수 있습니다. 그것의 onActivityResult()은 꼭 호출되어야합니다.

UPDATE : 지원 라이브러리 v23.2 출시하고 startActivityFromFragment(Fragment fragment, Intent intent, int requestCode, Bundle options) 지금 일을 보인다되었다 :

+0

당신이 제공 한 마지막 방법을 사용하여 결과에 대한 활동을 시작하는 것은 저에게 효과적이었습니다. 해결책을 찾지 못했지만 완전히 깨끗하다고는 할 수 없으므로 이상한 바이트 이동에 관해 Google이 아무 것도 변경하지 않기를 바랍니다. – user2302510

+2

Activity에서 호출 한 다음 그 결과를 Fragment에 전달하는 것이 더 낫겠지만 (뷰 페이지 때문에) 내 액티비티에 첨부 된 많은 조각이 있으면 처리하기가 매우 어렵습니다. – user2302510

+0

@ user2302510 정확히, 그것은 당신 혼자서 그것을 처리하는 것이 정말로 혼란스러워집니다. 다행히 도왔다! – 0101100101

2

ActivityCompat#startActivityForResult() 메서드는 액티비티의 startActivityForResult(Intent, Bundle) 메서드에 대한 프록시 일뿐입니다. 프래그먼트 클래스 내부에서 메서드를 호출한다고해서 결국 FragmentonActivityResult()이 호출된다는 것을 의미하지는 않습니다. 프레임 워크는 호출이 어떤 클래스에서 시작되었는지 알 수있는 방법을 알고 있습니다 ... 유일한 경우 올바른 호출은 ActivityonActivityResult() 메서드를 호출하는 것입니다.

귀하의 게시물에서 제안한대로 액티비티의 onActivityResult() 메소드의 모든 것을 처리하는 것이 가장 좋습니다.

+0

나는 이유를 이해 이런 일이 일어나고 있지만 그렇게해도 불편하지는 않습니다. 이 라이브러리는 지원 라이브러리에서만 존재하지 않습니까, 아니면 네이티브 프래그먼트 중 하나에서 수행 할 수 있습니까? 나는 그들이 미래에이 기능을 추가하기를 희망한다. –

+1

'Fragment'의'startActivityForResult (Intent, int, Bundle)'메소드를 호출 해 보셨습니까? –

0

프래그먼트에서 리스너 인터페이스 또는 공용 함수를 만들고 활동의 onActivityResult()에서 가져온 인수를 리스너 또는 프래그먼트의 공용 메서드로 전달하고 원하는 작업을 수행 할 수 있습니다. 그곳에.

0

하는 간단한 방법 : 조각에

:

ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(); 

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