조각의 MapView (Honeycomb)


81

이제 최종 SDK가 Google API와 함께 나왔습니다. MapView로 조각을 만드는 가장 좋은 방법은 무엇입니까? MapView가 제대로 작동하려면 MapActivity가 필요합니다.

프래그먼트를 관리하는 액티비티가 MapActivity에서 상속하고 (프래그먼트가 자체 포함되어 있다는 생각에 반하기 때문에 잘못된 솔루션) 일반 xml 기반 레이아웃을 사용하는 것은 작동하지 않습니다. MapActivity.setupMapView ()에서 NullPointerException이 발생합니다.

E / AndroidRuntime (597) : 원인 : java.lang.NullPointerException
E / AndroidRuntime (597) : com.google.android.maps.MapActivity.setupMapView (MapActivity.java:400)에서
E / AndroidRuntime (597) : com.google.android.maps.MapView. (MapView.java:289)
E / AndroidRuntime (597) : com.google.android.maps.MapView. (MapView.java:264)
E / AndroidRuntime (597) : com.google.android.maps.MapView. (MapView.java:247)

두 번째 아이디어는 MapView를 프로그래밍 방식으로 만들고 관련 활동을 (getActivity ()를 통해) 컨텍스트로 MapView 생성자에 전달하는 것입니다. 작동하지 않음 :

E / AndroidRuntime (834) : 원인 : java.lang.IllegalArgumentException : MapViews는 MapActivity 인스턴스 내에서만 만들 수 있습니다.
E / AndroidRuntime (834) : com.google.android.maps.MapView. (MapView.java:291)
E / AndroidRuntime (834) : com.google.android.maps.MapView. (MapView.java:235)
E / AndroidRuntime (834) : de.foo.FinderMapFragment.onCreateView (FinderMapFragment.java:225)
E / AndroidRuntime (834) : android.app.FragmentManagerImpl.moveToState (FragmentManager.java:708)
E / AndroidRuntime (834) : android.app.FragmentManagerImpl.moveToState (FragmentManager.java:900)
E / AndroidRuntime (834) : android.app.FragmentManagerImpl.addFragment (FragmentManager.java:978)에서
E / AndroidRuntime (834) : android.app.Activity.onCreateView (Activity.java:4090)에서
E / AndroidRuntime (834) : android.view.LayoutInflater.createViewFromTag (LayoutInflater.java:664)에서

실제로 MapView가 필요한 백그라운드 스레드를 처리하는 MapFragment와 같은 것이 있어야합니다. 그렇다면 현재 가장 좋은 방법은 무엇입니까?

독일 발렌틴에서 감사합니다.


2
이에 대한 기능 요청을보고했습니다. 별표를주세요. code.google.com/p/android/issues/detail?id=15347
Jeremy Edwards

답변:


8

2012 년 3 월 12 일부로 Google은 Google Maps Android API v2를 출시했습니다 . 이제 이러한 문제를 잊을 수 있습니다. https://developers.google.com/maps/documentation/android/

새 API를 사용한 예-https: //developers.google.com/maps/documentation/android/start#add_a_map

이 API는 Android API 8 이상에서 작동하므로 사용하십시오.).

이제 간단히 "com.google.android.gms.maps.MapFragment"조각 클래스를 사용할 수 있습니다. 활동에지도가 표시됩니다. 위 링크의 레이아웃 예 :

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.google.android.gms.maps.MapFragment"/>

87

조각에서 TabHost를 사용하여이 문제를 해결했습니다.

다음은 아이디어입니다 (간단히).

  1. MainFragmentActivity확장 FragmentActivity(지원 라이브러리에서) 및 MapFragment.

  2. MyMapActivity확장 MapActivity하고 포함합니다 MapView.

  3. LocalActivityManagerFragment 호스트 LocalActivityManager

  4. MapFragment확장 LocalActivityManagerFragment합니다.

  5. 그리고 그것에 활동을 LocalActivityManager포함 MyMapActivity합니다.

구현 예 : https://github.com/inazaruk/map-fragment .


여기에 이미지 설명 입력


4
그런 다음 MapActivity가 상위 활동 (Fragment를 사용하면 쉽습니다)과 통신 할 수 있도록하려면 Activity.getParent ()
Dori

3
당신은 정말 당신은 또한 단지 LocalActivityManager를 사용하여 조각의 내용에 반환 된 창을 첨부 할 수 있습니다하는 TabHost를 사용할 필요가 없습니다
ChristophK

4
경우 다른 사람이 궁금해에서, 여기에 코드입니다 :Intent i = new Intent(getActivity().getParent(), MyMapActivity.class); Window w = localActivityManager.startActivity("tag", i); currentView=w.getDecorView(); currentView.setVisibility(View.VISIBLE); currentView.setFocusableInTouchMode(true); ((ViewGroup) currentView).setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); this.contentView.addView(currentView);
ChristophK

8
주의의 LocalActivityManager는 이제 사용되지 않습니다
louiscoquio

4
탭과 조각을 사용하여 잘 작동합니다. 설명에 대해 묻는 사람들에게는 프로젝트와 코드를보고 싶습니다. 이해하기 쉽습니다. 그리고 예, LocalActivityManager더 이상 사용되지 않지만 이것은 해킹에 불과합니다.이 문제는 Fragments 내에지도에 대한 적절한 지원을 포함하기로 결정하면 제대로 해결됩니다.
mdelolmo 2012-08-07

23

Google 그룹스 에서 논의한대로 Peter Doyle은 Google지도를 지원하는 맞춤 호환성 라이브러리도 구축했습니다. android-support-v4-googlemaps

그러나 단점도 있습니다.

현재 한 가지 단점은 FragmentActivity를 확장하는 모든 클래스가 MapActivity라는 것입니다. 별도의 클래스 (예 : FragmentMapActivity)를 만들 수 있지만 FragmentActivity 코드의 일부 리팩토링이 필요합니다.


6
이는 또한 앱이 최신 지원 라이브러리로 업데이트되지 않음을 의미합니다. android-support-v4-googlemaps는 여러 번 업데이트되었지만 현재는 두 가지 버전이 뒤쳐져 있습니다. 이 수정 된 라이브러리가 더 이상 사용되지 않는 LocalActivityManager를 사용하는 것보다 더 큰 해킹이라는 다른 사람들과 동의합니다.
Stan Kurdziel 2012 년

1
github.com/petedoyle/android-support-v4-googlemaps 는 현재 최신 버전입니다 (이 메시지 기준 r10). 또한 리팩토링을해서 향후 최신 정보를 쉽게 확인할 수 있도록했습니다.
Pete Doyle

질문이 하나 있습니다. 응용 프로그램이 이미 배포 및 설치되어있는 경우 "최신 지원 라이브러리로 최신 상태가 아님"의 단점은 무엇입니까?
hendrix

이 접근 방식 인 IMO의 주요 문제는 선택적지도 지원으로 앱을 배포 할 수 없다는 것입니다. 모든 FragmentActivities는 MapActivity를 확장하므로 Google API가없는 기기 (예 : Kindle Fire)에서 충돌이 발생합니다.
Paul Lammertsma

13

답을 명확히하기 위해서입니다. 나는 inazaruk와 ChristophK가 제안한 접근 방식을 시도했습니다. 실제로 Google지도뿐만 아니라 단편에서 모든 활동을 실행할 수 있습니다. 다음은 inazaruk 및 ChristophK 덕분에 Google지도 활동을 조각으로 구현하는 코드입니다.

import com.actionbarsherlock.app.SherlockFragment;
import android.view.Window;

import android.app.LocalActivityManager;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MapFragment extends SherlockFragment {
    private static final String KEY_STATE_BUNDLE = "localActivityManagerState";

    private LocalActivityManager mLocalActivityManager;

    protected LocalActivityManager getLocalActivityManager() {
        return mLocalActivityManager;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Bundle state = null;
        if (savedInstanceState != null) {
            state = savedInstanceState.getBundle(KEY_STATE_BUNDLE);
        }

        mLocalActivityManager = new LocalActivityManager(getActivity(), true);
        mLocalActivityManager.dispatchCreate(state);
    }

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
            //This is where you specify you activity class
        Intent i = new Intent(getActivity(), GMapActivity.class); 
        Window w = mLocalActivityManager.startActivity("tag", i); 
        View currentView=w.getDecorView(); 
        currentView.setVisibility(View.VISIBLE); 
        currentView.setFocusableInTouchMode(true); 
        ((ViewGroup) currentView).setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        return currentView;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBundle(KEY_STATE_BUNDLE,
                mLocalActivityManager.saveInstanceState());
    }

    @Override
    public void onResume() {
        super.onResume();
        mLocalActivityManager.dispatchResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mLocalActivityManager.dispatchPause(getActivity().isFinishing());
    }

    @Override
    public void onStop() {
        super.onStop();
        mLocalActivityManager.dispatchStop();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mLocalActivityManager.dispatchDestroy(getActivity().isFinishing());
    }
}

2
그러나 피하는 유일한 솔루션 LocalActivityManager(여기에 설명 된대로 : code.google.com/p/android/issues/detail?id=15347 )은 모두 확장 FragmentActivities하는 것인데, 이는 훨씬 덜 최적화 된 것 같습니다.
ESTEL

LocalActivityManager는 더 이상 사용되지 않습니다. ActivityGroup이 더 이상 사용되지 않고이 상황에 여전히 유용하며 사람들이 단점을 해결하기 위해 사용하는 경우 Google은 향후 릴리스에서이를 축출하는 것에 대해 두 번 생각할 것입니다.
straya

4

이에 대한 Google의 좋은 소식입니다. 오늘 실내지도 및 MapFragment가 포함 된 새로운 Google Maps API를 출시합니다 .

With this new API, adding a map to your Activity is as simple as:

<fragment
  android:id="@+id/map"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  class="com.google.android.gms.maps.MapFragment" />

정확히. FragmentPagerAdapter에서 사용해보십시오.
Thomas Dignan 2013 년

당신이 블랙 뷰에 대해 이야기하는 경우, 그것을 해결하기 위해 작은 해킹있다 stackoverflow.com/questions/13837697/...
마르셀

감사. 나는 나중에 그것을 보았지만 지금은 폴라리스와 함께 첫 번째 맵 API 버전을 사용하고 있습니다.
Thomas Dignan 2013

2

Google Maps API는 AOSP의 일부가 아닙니다. Google 직원이 응답하지 않는 한 향후 MapFragment가 있을지 여부를 알 수 없습니다.

가능한 제한적인 대안은 a를 사용하고 WebViewFragment이를 남용하여 사용자 정의 maps.google.comURL 을로드하는 것 입니다.


1
Map API가 곧 조각과 벡터 드로잉으로 업데이트되기를 바랍니다!
Nathan Schwermann 2011 년

2

Google이 아직 응답하지 않은 것이 너무 아쉽습니다. FWIW 당신이 정말로 이것을해야한다면 나는 다른 방법을 찾지 못했습니다.

탭 관리 활동을 MapActivity에서 상속하고 거기에 프로그래밍 방식으로 MapView를 만들고 mapfragment.xml에 ViewGroup을 포함하고 다음을 사용하여 MapView를 ViewGroup에 추가합니다.

((ViewGroup) getFragmentManager (). findFragmentById (R.id.finder_map_fragment) .getView ()). addView (mapView) ;;

분명히 이것은 파편이 독립적이어야한다는 생각에 강하게 반대되지만 ...


감사합니다. Fragment 관리 활동을 MapActivity 확장으로 만들면 완벽하게 작동했습니다.
Pete Doyle 2011 년

2

다음 은 매우 단순화 된 MapFragmentMonoDroid ( Android 용 Mono ) 버전입니다 .

public class MapFragment : Fragment
{
    // FOLLOW http://stackoverflow.com/questions/5109336/mapview-in-a-fragment-honeycomb
    private static  String KEY_STATE_BUNDLE = "localActivityManagerState";

    public override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        Bundle state = null;
        if (savedInstanceState != null) {
            state = savedInstanceState.GetBundle(KEY_STATE_BUNDLE);
        }
        mLocalActivityManager = new LocalActivityManager(Activity, true);
        mLocalActivityManager.DispatchCreate(state);
    }

    public override Android.Views.View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        //This is where you specify you activity class
        Intent i = new Intent(Activity, typeof(SteamLocationMapActivity)); 
        Window w = mLocalActivityManager.StartActivity("tag", i); 
        View currentView=w.DecorView; 
        currentView.Visibility = ViewStates.Visible; 
        currentView.FocusableInTouchMode = true; 
        ((ViewGroup) currentView).DescendantFocusability = DescendantFocusability.AfterDescendants;
        return currentView;
    }

    private LocalActivityManager mLocalActivityManager;
    protected LocalActivityManager GetLocalActivityManager() {
        return mLocalActivityManager;
    }   


    public override void OnSaveInstanceState(Bundle outState)
    {
        base.OnSaveInstanceState(outState);
        outState.PutBundle(KEY_STATE_BUNDLE,mLocalActivityManager.SaveInstanceState());
    }

    public override void OnResume()
    {
        base.OnResume();
        mLocalActivityManager.DispatchResume();

    }

    public override void OnPause()
    {
        base.OnPause();
        mLocalActivityManager.DispatchPause(Activity.IsFinishing);
    }

    public override void OnStop()
    {
        base.OnStop();
        mLocalActivityManager.DispatchStop();
    }
}



1

해결책을 얻을 수 있습니까?

  1. TempFragmentActivity 클래스 생성은 MapActivity를 확장합니다.
  2. TempFragmentActivity 안에 MapView 객체가 있습니다 (xml의 일반 정의와 유사)
  3. 이 MapView 객체를 제거하십시오 parent (LinearLayout) (나중에 예외 없음)
  4. 이 MapView 객체를 어딘가에 보관하십시오 (예 : TempFragmentActivity의 정적 멤버).
  5. Fragment에서 코드를 사용 하여이 MapView 객체를 일부 LinearLayout에 추가하십시오 (xml에서 정의하지 마십시오).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.