एक दृश्य में मानचित्र दृश्य (हनीकॉम्ब)


81

अब जब गूगल एसडी के साथ अंतिम एसडीके बाहर हो गया है - मैपव्यू के साथ एक फ्रैगमेंट बनाने का सबसे अच्छा तरीका क्या है? MapView को सही कार्य करने के लिए MapActivity की आवश्यकता होती है।

Fragments को प्रबंधित करने वाली गतिविधि का MapActivity से विरासत में मिला (बुरा समाधान क्योंकि यह इस विचार के खिलाफ जाता है कि Fragments स्वयं निहित हैं) और एक नियमित xml आधारित लेआउट का उपयोग करने से काम नहीं होता है। मुझे MapActivity.setupMapView () में एक NullPointerException मिलती है:

E / AndroidRuntime (597): इसके कारण: java.lang.NullPointerException
E / AndroidRuntime (597): com.google.android.maps.apActivity.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)

मेरा दूसरा विचार था, मानचित्र दृश्य को प्रोग्रामेटिक रूप से बनाना और संबंधित गतिविधि (गेटअक्टिविटी ()) को मानचित्र व्यू कंस्ट्रक्टर के संदर्भ में पास करना। काम नहीं करता:

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.ragmentManagerImpl.moveToState (FragmentManager.java:708) पर
E / AndroidRuntime (834): android.app पर।
E / AndroidRuntime (834): Android.app.FragmentManagerImpl.addFragment (FragmentManager.java:978) पर
E / AndroidRuntime (834): android.app.Activity.onCreateView (गतिविधि.java.409) पर
E / AndroidRuntime (834): android.view.LayoutInflater.createViewFromTag (LayoutInflater.java:664) पर

वास्तव में MapFragment जैसा कुछ होना चाहिए जो पृष्ठभूमि थ्रेड्स का ध्यान रखता है MapView को मुझे लगता है कि जरूरत है ... तो ऐसा करने के लिए वर्तमान सर्वोत्तम अभ्यास क्या है?

जर्मनी, वैलेंटाइन का धन्यवाद और सम्मान


2
मैंने इसके लिए एक फीचर अनुरोध की सूचना दी। कृपया इसे घूरें। code.google.com/p/android/issues/detail?id=15347
जेरेमी एडवर्ड्स

जवाबों:


8

03.12.2012 तक Google ने Google मैप्स Android API v2 जारी किया । अब आप इन समस्याओं को भूल सकते हैं। https://developers.google.com/maps/documentation/android/

नए एपीआई का उपयोग कर उदाहरण - 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 पैरेंट एक्टिविटी (जो एक फ्रैगमेंट के साथ आसान है) के साथ शुरू हो सके तो आप एक्टिविटी.गेटपेंट ()
डोरी

3
आपको वास्तव में एक TabHost का उपयोग करने की आवश्यकता नहीं है, आप केवल एक LocalActivityManager का उपयोग कर सकते हैं और अपनी विखंडन सामग्री में लौटी विंडो संलग्न कर सकते हैं
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 को अब
निकाला

4
यह टैब और टुकड़ों का उपयोग करते हुए मेरे लिए अच्छा काम करता है। स्पष्टीकरण के बारे में पूछने वालों के लिए, मैं इस परियोजना और इसके कोड को देखूंगा, इसे समझना आसान है। और हां, LocalActivityManagerपदावनत किया गया है, लेकिन यह सिर्फ एक हैक है, यह समस्या ठीक से हल हो जाएगी जब वे फ्रेगमेंट के भीतर मैप्स के लिए उपयुक्त समर्थन को शामिल करने का निर्णय लेते हैं।
mdelolmo

23

जैसा कि Google समूहों में चर्चा की गई थी , पीटर डॉयल ने Google मैप्स का भी समर्थन करते हुए एक कस्टम कम्पेटिबिलिटी लाइब्रेरी का निर्माण किया। android-support-v4-googlemaps

हालाँकि, एक नकारात्मक पहलू यह भी है:

वर्तमान में, एक नकारात्मक पक्ष यह है कि FragmentActivity का विस्तार करने वाले सभी वर्ग MapActivity हैं। एक अलग वर्ग (यानी FragmentMapActivity) बनाना संभव है, लेकिन इसके लिए FragmentActivity कोड के कुछ रिफैक्टिंग की आवश्यकता होती है।


6
इसका मतलब यह भी है कि आपका ऐप नवीनतम समर्थन लाइब्रेरी के साथ अद्यतित नहीं होगा। हालांकि android-support-v4-googlemaps को कई बार अपडेट किया गया है, यह वर्तमान में 2 संस्करण पीछे है। मैं दूसरों से सहमत हूं कि यह संशोधित लाइब्रेरी डीरेलिएटेड लोकल एक्टिविटी मैनजर का उपयोग करने से बड़ी हैक है।
स्टेन कुर्दिज़ल

1
github.com/petedoyle/android-support-v4-googlemaps अब तक है (r10 इस संदेश के रूप में)। मैंने भी चीजों को रिफलेक्ट किया है इसलिए भविष्य में इसे बनाए रखना आसान होगा।
पीट डॉयल

मेरा एक सवाल है। यदि आवेदन पहले से ही तैनात और स्थापित है, तो "नवीनतम समर्थन पुस्तकालय के साथ तारीख तक नहीं होने" का नुकसान क्या है?
हेंड्रिक्स

इस दृष्टिकोण के साथ प्राथमिक समस्या, IMO, यह है कि आप अपने एप्लिकेशन को वैकल्पिक मानचित्र समर्थन के साथ परिनियोजित नहीं कर पाएंगे। चूंकि सभी FragmentActivities MapActivity का विस्तार करते हैं, यह बस Google API (जैसे किंडल फायर) के बिना उपकरणों पर क्रैश हो जाएगा।
पॉल लामर्ट्स्मा

13

बस जवाब स्पष्ट करने के लिए। मैंने इज़रुक और क्रिस्टोफ़के द्वारा सुझाए गए दृष्टिकोण की कोशिश की। वास्तव में आप किसी भी गतिविधि को एक टुकड़े में चला सकते हैं - न केवल Google मानचित्र। यहाँ वह कोड है जो इनज़्रुक और क्रिस्टोफ़क के लिए धन्यवाद के रूप में 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, जो कि कम इष्टतम भी लगता है।
एस्टेल

LocalActivityManager अधिक अपग्रेड किया गया है क्योंकि इस स्थिति के लिए एक्टिविटी ग्रुप अभी भी उपयोगी है, और संभवतः Google भविष्य की रिलीज़ में इसे बाहर करने के बारे में दो बार सोचेगा यदि लोग इसका उपयोग अपनी कमियों को हल करने के लिए कर रहे हैं।
आवारा

4

इस पर Google की ओर से शानदार खबर। वे आज एक नया Google मैप्स API जारी कर रहे हैं , जिसमें इनडोर नक्शे और MapFragment हैं।

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 में इसका उपयोग करने का प्रयास करें।
थॉमस डिगन

आप काले दृश्य के बारे में बात कर रहे हैं, वहाँ इसे ठीक करने के लिए एक छोटा सा हैक है stackoverflow.com/questions/13837697/...
मार्सेलो

धन्यवाद। मैंने बाद में यह देखकर समाप्त कर दिया, लेकिन अब मैं पोलारिस के साथ पहले मानचित्र एपीआई संस्करण का उपयोग कर रहा हूं।
थॉमस डिगन

2

Google मैप्स API AOSP का हिस्सा नहीं है। जब तक कोई गोगलर जवाब नहीं देता तब तक यह बताना मुश्किल है कि भविष्य में कोई मैपफ्राग्मेंट होगा या नहीं।

एक संभव सीमित विकल्प एक का उपयोग करना है WebViewFragmentऔर एक कस्टम maps.google.comURL को लोड करने के लिए इसका दुरुपयोग करना है ।


1
यहां उम्मीद है कि मैप एपीआई जल्द ही टुकड़ों और वेक्टर ड्राइंग के साथ अपडेट किया जाएगा!
नाथन श्वरमन

2

एचएम बहुत बुरा है कि Google ने अभी तक कोई प्रतिक्रिया नहीं दी है। FWIW अगर आपको वास्तव में ऐसा करने की आवश्यकता है तो मुझे इसके अलावा कोई अन्य तरीका नहीं मिला:

MapActivity से टैब प्रबंध गतिविधि विरासत में मिली है, मैपव्यू को प्रोग्रामेटिक रूप से वहां बनाएं, मैपफ्रैगमेंट करें। xml में एक व्यूग्रुप होता है और मैप व्यू को व्यूग्रुप में जोड़ें

((देखेंसमूह) getFragmentManager ()। FindFragmentById (R.id.finder_map_fragment) .getView ())। AddView (mapView) ;;

स्पष्ट रूप से यह इस विचार के खिलाफ दृढ़ता से जाता है कि टुकड़े आत्म-निहित होने के लिए मानसिक हैं लेकिन ...


धन्यवाद, Fragment प्रबंध गतिविधि का विस्तार करना MapActivity मेरे लिए पूरी तरह से काम करती है।
पीट डॉयल

2

यहाँ एक बहुत सरल सरलीकृत MapFragment का एक मोनोअरोइड ( Android के लिए मोनो ) संस्करण है :

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 ऑब्जेक्ट फॉर्म पैरेंट (LinearLayout) को हटा दें (बाद के अपवाद को शून्य करें)
  4. इस MapView ऑब्जेक्ट को कहीं पर रखें (उदा: TempFragmentActivity के स्थिर सदस्य)
  5. अपने फ्रेग्मेंट में, कुछ LinearLayout में कोड (xml में परिभाषित न करें) का उपयोग करके इस MapView ऑब्जेक्ट को जोड़ें

0

मैंने एक छोटी सी लाइब्रेरी लिखी, जिसमें LocalActivityManager- आधारित समाधानों को MapFragment समस्या के लिए तैयार किया गया (इसमें विभिन्न उपयोग स्थितियों को दर्शाने वाला एक उदाहरण ऐप भी शामिल है):

https://github.com/coreform/android-tandemactivities

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.