CameraUpdateFactory.newLatLngBounds क्रैश के साथ MoveCamera


96

मैं नए Android Google Maps API का उपयोग कर रहा हूं ।

मैं एक गतिविधि बनाता हूं जिसमें एक MapFragment शामिल है। गतिविधि में onResumeमैंने मार्करों को GoogleMap ऑब्जेक्ट में सेट किया और फिर मैप के लिए एक बाउंडिंग बॉक्स परिभाषित किया जिसमें सभी मार्कर शामिल हैं।

यह निम्नलिखित छद्म कोड का उपयोग कर रहा है:

LatLngBounds.Builder builder = new LatLngBounds.Builder();
while(data) {
   LatLng latlng = getPosition();
   builder.include(latlng);
}
CameraUpdate cameraUpdate = CameraUpdateFactory
   .newLatLngBounds(builder.build(), 10);
map.moveCamera(cameraUpdate);

map.moveCamera()निम्नलिखित स्टैक के साथ मेरे एप्लिकेशन को क्रैश करने का कारण बनता है:

Caused by: java.lang.IllegalStateException: 
    Map size should not be 0. Most likely, layout has not yet 

    at maps.am.r.b(Unknown Source)
    at maps.y.q.a(Unknown Source)
    at maps.y.au.a(Unknown Source)
    at maps.y.ae.moveCamera(Unknown Source)
    at com.google.android.gms.maps.internal.IGoogleMapDelegate$Stub
        .onTransact(IGoogleMapDelegate.java:83)
    at android.os.Binder.transact(Binder.java:310)
    at com.google.android.gms.maps.internal.IGoogleMapDelegate$a$a
        .moveCamera(Unknown Source)
    at com.google.android.gms.maps.GoogleMap.moveCamera(Unknown Source)
    at ShowMapActivity.drawMapMarkers(ShowMapActivity.java:91)
    at ShowMapActivity.onResume(ShowMapActivity.java:58)
    at android.app.Instrumentation
        .callActivityOnResume(Instrumentation.java:1185)
    at android.app.Activity.performResume(Activity.java:5182)
    at android.app.ActivityThread
        .performResumeActivity(ActivityThread.java:2732)

यदि - newLatLngBounds()कारखाने की विधि के बजाय मैं newLatLngZoom()विधि का उपयोग करता हूं तो एक ही जाल उत्पन्न नहीं होता है।

है onResumeसबसे अच्छी जगह GoogleMap ऑबजेक्ट पर मार्कर आकर्षित करने के लिए या मैं मार्करों ड्राइंग किया जाना चाहिए और कहीं और कैमरे की स्थिति की स्थापना?

जवाबों:


133

आप सरल उपयोग कर सकते हैं newLatLngBounds में विधि OnCameraChangeListener । सभी पूरी तरह से काम करेंगे और आपको स्क्रीन आकार की गणना करने की आवश्यकता नहीं है। यह घटना मानचित्र आकार गणना के बाद होती है (जैसा कि मैं समझता हूं)।

उदाहरण:

map.setOnCameraChangeListener(new OnCameraChangeListener() {

    @Override
    public void onCameraChange(CameraPosition arg0) {
        // Move camera.
        map.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 10));
        // Remove listener to prevent position reset on camera move.
        map.setOnCameraChangeListener(null);
    }
});

1
यह काम करता है क्योंकि मैप के लेआउट के बाद सेटऑनकेमराचेंज लाइस्टनर को कम से कम एक बार चलाने की गारंटी है? क्या यह भविष्य का प्रमाण है?
ग्लेन बेच

3
@SteelRat यही कारण है कि मैं समाधान का उपयोग करने के खिलाफ हूं। आप कभी नहीं जानते कि Google कब इसे बदलता है, या भले ही यह सभी एंड्रॉइड वर्जन या डिवाइस पर इस तरह से काम करता हो।
ग्लेन बेच

1
@SteelRat मैं सहमत हूं, लेकिन यह गतिविधि के जीवनकाल में एक से अधिक बार कहा जा सकता है? मैं सिर्फ यह तर्क दे रहा हूं कि भले ही यह इस मामले में काम करे, लेकिन इसका बहुत ही सुरुचिपूर्ण समाधान नहीं है। मुझे लगता है कि OnGlobalLayoutListener / Treelistener इस बारे में जाने का एक और सही तरीका है।
ग्लेन बेच

4
शायद map.moveCamera (CameraUpdateFactory.scrollBy (1, 1)) जोड़ना ; ऊपर दिए गए कोड के बाद ट्रिक बन जाएगी?
मेरा

3
setOnCameraChangeListenerअब पदावनत कर दिया जाता है
osrl

56

वे उत्तर ठीक हैं, लेकिन मैं एक अलग दृष्टिकोण के लिए जाऊंगा, एक सरल। यदि विधि केवल नक्शे के बिछाने के बाद काम करती है, तो इसके लिए प्रतीक्षा करें:

map.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
    @Override
    public void onMapLoaded() {
        map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 30));
    }
});

1
मैंने बहुत प्रयोग के बाद पाया कि मुझे इस उत्तर और डेनियल के उपरोक्त के संयोजन को लागू करने की आवश्यकता है । कभी-कभी मानचित्र अभी तक लोड नहीं किया गया था, कभी-कभी लेआउट अभी तक पूरा नहीं हुआ था। जब तक उन में से कोई भी नहीं हो जाता तब तक मैं कैमरा नहीं हिला सकता था।
रॉब

2
डॉक्स से इस विधि के लिए चेतावनी: "यह घटना आग नहीं देगी यदि कनेक्टिविटी के मुद्दों के कारण मानचित्र कभी भी लोड नहीं होता है, या यदि नक्शा लगातार बदल रहा है और उपयोगकर्ता द्वारा मानचित्र के साथ लगातार बातचीत करने के कारण लोडिंग को कभी पूरा नहीं करता है ।" (जोर मेरा)।
शाम

1
यह आवश्यक से अधिक समय तक देरी करता है क्योंकि यह सही स्थिति में जाने से पहले गलत स्थिति में नक्शा टाइलों के लोड होने की प्रतीक्षा करता है।
जॉन पैटरसन

1
ज्यादातर समय यह 3-10 सेकंड के बीच आग लगने के लिए कुछ भी लेता है जो अस्वीकार्य है।
निमा जी

यह कैमरा ले जाने की जगह है। मेरा सुझाव है कि map.moveCamera के बजाय map.animateCamera का उपयोग करें
Bharat

51

ठीक है मैंने यह काम किया। जैसा कि यहां दस्तावेज किया गया है कि एपीआई का उपयोग पूर्व-लेआउट के लिए नहीं किया जा सकता है।

उपयोग करने के लिए सही एपीआई के रूप में वर्णित है:

नोट: यदि कैमरा लेआउट को ले-आउट करने के बाद इसका उपयोग करने जा रहा है, तो कैमराअप जनरेट करने के लिए केवल सरल विधि newLatLngBounds (सीमा, पैडिंग) का उपयोग करें। लेआउट के दौरान, एपीआई मानचित्र की प्रदर्शन सीमाओं की गणना करता है जो कि सीमा बॉक्स को सही ढंग से प्रोजेक्ट करने के लिए आवश्यक हैं। तुलना में, आप किसी भी समय अधिक जटिल विधि newLatLngBounds (सीमा, चौड़ाई, ऊँचाई, पैडिंग) द्वारा लौटाए गए CameraUpdate का उपयोग कर सकते हैं, यहां तक ​​कि मानचित्र के लेआउट से गुजरने से पहले भी, क्योंकि एपीआई उन तर्कों से प्रदर्शन सीमाओं की गणना करता है जिन्हें आप पास करते हैं।

इस समस्या को ठीक करने के लिए मैंने अपने स्क्रीन साइज़ की गणना की और चौड़ाई और ऊँचाई प्रदान की

public static CameraUpdate newLatLngBounds(
    LatLngBounds bounds, int width, int height, int padding)

इसके बाद मुझे बाउंडिंग बॉक्स प्री-लेआउट को निर्दिष्ट करने की अनुमति मिली।


18
लेकिन क्या होगा अगर नक्शा पूरी स्क्रीन को नहीं लेता है?
दिबांग

मेरे मामले में मैंने सिर्फ एक बड़ी स्क्रीन की तुलना में प्रभाव में था, और अधिक ध्यान से पेडिंग की गणना करने की आवश्यकता थी इसलिए यह वास्तव में बहुत बड़ी नहीं थी । बहुत सरल कारण।
rfay

2
क्या आप यह दिखा सकते हैं कि स्क्रीन आकार के आधार पर इसकी गणना कैसे करें?
डेनियल गोमेज़ रिको

यह दुर्घटना नहीं करता है, लेकिन उपयोग की जाने वाली चौड़ाई और ऊंचाई शुद्ध अनुमानों के करीब होती है, खींचा जाने वाला सटीक क्षेत्र वास्तव में अप्रत्याशित है।
विंस

34

समाधान उससे भी सरल है ...।

// Pan to see all markers in view.
try {
    this.gmap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
} catch (IllegalStateException e) {
    // layout not yet initialized
    final View mapView = getFragmentManager()
       .findFragmentById(R.id.map).getView();
    if (mapView.getViewTreeObserver().isAlive()) {
        mapView.getViewTreeObserver().addOnGlobalLayoutListener(
        new OnGlobalLayoutListener() {
            @SuppressWarnings("deprecation")
            @SuppressLint("NewApi")
            // We check which build version we are using.
            @Override
            public void onGlobalLayout() {
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                    mapView.getViewTreeObserver()
                        .removeGlobalOnLayoutListener(this);
                } else {
                    mapView.getViewTreeObserver()
                        .removeOnGlobalLayoutListener(this);
                }
                gmap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
            }
        });
    }
}

IllegalStateExceptionइसके बजाय वैश्विक श्रोता को दृश्य पर पकड़ें और उसका उपयोग करें। अन्य तरीकों का उपयोग करके पूर्व आकार को पहले से निर्धारित करना है। इसका मतलब है कि आपको स्क्रीन के आकार की गणना करनी है, न कि स्क्रीन डिवाइस की। वे केवल तभी मेल खाते हैं जब आप अपने मानचित्र के साथ पूर्ण स्क्रीन पर जाते हैं और टुकड़ों का उपयोग नहीं करते हैं।


अब तक मैं आपके छोटे स्निपेट का उपयोग कर रहा हूं, लेकिन यह अभी भी विफल है ... सही उत्तर पहले वाला है :-)
cesards

1
कैसे / कब विफल? इसके साथ कभी कोई मुद्दा नहीं था। पहला उत्तर बस एक हार्डकोड के आकार को एक कमबैक के रूप में पास करता है। "यह" के रूप में "यह अब और दुर्घटना नहीं करता है" में काम करता है, लेकिन यह एक ही काम नहीं कर रहा है।
डेनियल सेगाटो

@ andrea.spot मुझे याद नहीं है कि मैंने सरल क्यों कहा था। मुझे लगता है कि इस बीच स्वीकृत समाधान को संपादित किया गया है। वर्तमान स्वीकृत समाधान मान अपने नक्शे सभी स्क्रीन है, जो हमेशा सच नहीं है ले लो। यदि आप उस स्थिति में नहीं आते हैं, तो आपको या तो नक्शे के आकार को जानना होगा या मेरी पद्धति या कुछ इसी तरह का उपयोग करना होगा।
डैनियल सेगाटो

ज़िंगांग हुआंग द्वारा नीचे दिए गए उत्तर की भी जाँच करें, यह इसमें थोड़ा सा जोड़ता है।
डेनियल सेगाटो

15

यह मेरा फिक्स है, बस उस मामले में नक्शा लोड होने तक प्रतीक्षा करें।

final int padding = getResources().getDimensionPixelSize(R.dimen.spacing);    

try {
    mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(pCameraBounds, padding));
} catch (IllegalStateException ise) {

    mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {

        @Override
        public void onMapLoaded() {
            mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(pCameraBounds, padding));
        }
    });
}

सरल और कुशल +1
16

14

मार्करों को जोड़ना और निकालना पूर्व-पूर्णता पूरा किया जा सकता है, लेकिन कैमरे को स्थानांतरित करना ( newLatLngBounds(boundary, padding)ओपी के जवाब में उल्लेख के अनुसार उपयोग करने के अलावा) नहीं कर सकता है ।

संभवतः प्रारंभिक कैमरा अपडेट करने के लिए सबसे अच्छी जगह एक-शॉट का उपयोग करना है OnGlobalLayoutListenerजैसा कि Google के नमूना कोड में दिखाया गया है , उदाहरण के लिए MarkerDemoActivity.javasetUpMap() में निम्नलिखित अंश देखें :

// Pan to see all markers in view.
// Cannot zoom to bounds until the map has a size.
final View mapView = getSupportFragmentManager()
    .findFragmentById(R.id.map).getView();
if (mapView.getViewTreeObserver().isAlive()) {
    mapView.getViewTreeObserver().addOnGlobalLayoutListener(
    new OnGlobalLayoutListener() {
        @SuppressLint("NewApi") // We check which build version we are using.
        @Override
        public void onGlobalLayout() {
            LatLngBounds bounds = new LatLngBounds.Builder()
                    .include(PERTH)
                    .include(SYDNEY)
                    .include(ADELAIDE)
                    .include(BRISBANE)
                    .include(MELBOURNE)
                    .build();
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
              mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            } else {
              mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
            mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
        }
    });
}


मुझे यह त्रुटि अभिविन्यास परिवर्तन पर मिलती है। मुझे यह नमूना कोड से भी मिला, लेकिन यह मेरे लिए काम नहीं करता था। मुझे अब भी वही त्रुटि मिलती है।
13

14

स्वीकृत उत्तर मेरे लिए काम नहीं करेगा क्योंकि मुझे अपने ऐप के विभिन्न स्थानों में समान कोड का उपयोग करना था।

कैमरे को बदलने के लिए इंतजार करने के बजाय, मैंने ली के नक्शे के आकार को निर्दिष्ट करने के सुझाव के आधार पर एक सरल समाधान बनाया। यह तब होता है जब आपका नक्शा स्क्रीन का आकार होता है।

// Gets screen size
int width = getResources().getDisplayMetrics().widthPixels;
int height = getResources().getDisplayMetrics().heightPixels;
// Calls moveCamera passing screen size as parameters
map.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), width, height, 10));

आशा है कि यह किसी और की मदद करता है!


8

स्वीकृत उत्तर है, जैसा कि टिप्पणियों में बताया गया है, थोड़ा हैकी। इसे लागू करने के बाद मैंने IllegalStateExceptionएनालिटिक्स में लॉग्स के ऊपर-स्वीकार्य राशि को देखा । मैंने जो समाधान का उपयोग किया है वह एक जोड़ना OnMapLoadedCallbackहै जिसमें CameraUpdateप्रदर्शन किया गया है। कॉलबैक में जोड़ा जाता है GoogleMap। आपके नक्शे के पूरी तरह से लोड होने के बाद कैमरा अपडेट किया जाएगा।

यह कैमरा अपडेट को करने से पहले मैप को ज़ूम आउट (0,0) व्यू को संक्षेप में दिखाता है। मुझे लगता है कि दुर्घटनाग्रस्त होने या अनिर्दिष्ट व्यवहार पर भरोसा करने की तुलना में यह अधिक स्वीकार्य है।


5
 map.moveCamera(CameraUpdateFactory.newLatLngZoom(bounds.getCenter(),10));

इस का उपयोग यह mee के लिए काम किया


यह सिर्फ नक्शे को केंद्र में रखता है लेकिन गतिशील रूप से ज़ूम को सीमा में समायोजित नहीं करता है।
गियोवन्नी डि ग्रेगोरियो

हम "LatLngBounds.Builder" का उपयोग करके अधिक मैटर्स के लिए सीमाओं की गणना कर सकते हैं।
रमेश भूपति

@ रमेशभूपति लेकिन यह अभी भी एक केंद्र और एक ज़ूम के साथ एक मानचित्र दृश्य रहेगा।
तैमूर

4

बहुत ही दुर्लभ मामलों में, MapView लेआउट समाप्त हो गया है, लेकिन GoogleMap लेआउट समाप्त नहीं हुआ है, ViewTreeObserver.OnGlobalLayoutListenerस्वयं क्रैश को रोक नहीं सकता है। मैंने Google Play सेवाओं के पैकेज संस्करण 5084032 के साथ दुर्घटना देखी। यह दुर्लभ मामला मेरे मैप व्यू की दृश्यता के गतिशील परिवर्तन के कारण हो सकता है।

इस समस्या को हल करने के लिए, मैंने इसमें एम्बेड GoogleMap.OnMapLoadedCallbackकिया onGlobalLayout(),

if (mapView.getViewTreeObserver().isAlive()) {
    mapView.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        @SuppressWarnings("deprecation")
        public void onGlobalLayout() {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            } else {
                mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
            try {
                map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 5));
            } catch (IllegalStateException e) {
                map.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
                    @Override
                    public void onMapLoaded() {
                        Log.d(LOG_TAG, "move map camera OnMapLoadedCallback");
                        map.moveCamera(CameraUpdateFactory
                            .newLatLngBounds(bounds, 5));
                    }
                });
            }
        }
    });
}

दिलचस्प है: यदि मैं mapView.getViewTreeObserver()एक स्थानीय चर में रिफ्लेक्टर करता हूं तो निम्न त्रुटि होती है: "IllegalStateException: यह ViewTreeObserver जीवित नहीं है, getViewTreeObserver () फिर से कॉल करें" । क्या आपने यह कोशिश की?
JJD

अगर mapView.getViewTreeObserver ()। IsAlive () गलत हो रहा है तो मैं map.setOnMapLoadedCallback ()
southerton

4

मैंने अलग-अलग दृष्टिकोण का उपयोग किया है जो Google मैप्स एसडीके (9.6+) के हाल के संस्करणों के लिए काम करता है और onCameraIdleListener पर आधारित है । जैसा कि मैंने देखा है कि यह कॉलबैक विधि है onCameraIdleजिसे हमेशा कहा जाता है onMapReady। तो मेरा दृष्टिकोण कोड के इस टुकड़े की तरह दिखता है (इस पर विचार करते हुए Activity):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // set content view and call getMapAsync() on MapFragment
}

@Override
public void onMapReady(GoogleMap googleMap) {
    map = googleMap;
    map.setOnCameraIdleListener(this);
    // other initialization stuff
}

@Override
public void onCameraIdle() {
    /* 
       Here camera is ready and you can operate with it. 
       you can use 2 approaches here:

      1. Update the map with data you need to display and then set
         map.setOnCameraIdleListener(null) to ensure that further events
         will not call unnecessary callback again.

      2. Use local boolean variable which indicates that content on map
         should be updated
    */
}

4

मैंने दो कॉलबैक को संयोजित करने का एक तरीका बनाया है: onMapReady और onGlobalLayout को एक एकल वेधशाला में, जो केवल तभी उत्सर्जित करेगा जब दोनों घटनाओं को ट्रिगर किया गया हो।

https://gist.github.com/abhaysood/e275b3d0937f297980d14b439a8e0d4a


1
यह वास्तव में इसे हल करने का सबसे साफ तरीका है। मैं लंबे समय से ऐसा कर रहा हूं और प्रति दिन 1k उपयोगकर्ताओं पर भी एनालिटिक्स में कोई त्रुटि नहीं लौटाई जाती है। +1
स्काइल डेसी

2

ठीक है, मैं एक ही मुद्दे का सामना कर रहा हूँ। मेरा सपोर्टमैप फ्रैगमेंट, एबीएस, और नेविगेशन दराज के साथ मेरा टुकड़ा है। मैंने जो किया वह था:

public void resetCamera() {

    LatLngBounds.Builder builderOfBounds = new LatLngBounds.Builder();
    // Set boundaries ...
    LatLngBounds bounds = builderOfBounds.build();
    CameraUpdate cu;
    try{
        cu = CameraUpdateFactory.newLatLngBounds(bounds,10);
        // This line will cause the exception first times 
        // when map is still not "inflated"
        map.animateCamera(cu); 
        System.out.println("Set with padding");
    } catch(IllegalStateException e) {
        e.printStackTrace();
        cu = CameraUpdateFactory.newLatLngBounds(bounds,400,400,0);
        map.animateCamera(cu);
        System.out.println("Set with wh");
    }

    //do the rest...
}

और, वैसे, मैं फुलाए जाने resetCamera()से onCreateViewपहले और लौटने से पहले कॉल कर रहा हूं ।
यह पहली बार अपवाद को पकड़ता है (जबकि नक्शा "आकार प्राप्त करता है" यह कहने के तरीके के रूप में ...) और फिर, दूसरी बार मुझे कैमरे को रीसेट करने की आवश्यकता है, मानचित्र में पहले से ही आकार है और इसे पैडिंग के माध्यम से करता है।

मुद्दे को प्रलेखन में समझाया गया है , यह कहता है:

इस कैमरा अपडेट के साथ कैमरा को तब तक न बदलें जब तक कि मैप में लेआउट न आ गया हो (इस विधि के लिए उचित बाउंडिंग बॉक्स और ज़ूम स्तर को सही ढंग से निर्धारित करने के लिए, मैप का आकार होना चाहिए)। नहीं IllegalStateExceptionतो फेंक दिया जाएगा। यह मानचित्र उपलब्ध होने के लिए पर्याप्त नहीं है (यानी getMap()एक गैर-अशक्त वस्तु लौटाता है); मानचित्र वाले दृश्य में लेआउट भी होना चाहिए जैसे कि इसके आयाम निर्धारित किए गए हैं। यदि आप यह सुनिश्चित नहीं कर सकते हैं कि यह खराब हो गया है, तो newLatLngBounds(LatLngBounds, int, int, int)इसके बजाय उपयोग करें और मैन्युअल रूप से नक्शे के आयाम प्रदान करें।

मुझे लगता है कि यह एक बहुत अच्छा समाधान है। आशा है कि यह किसी की मदद करता है।


1
क्या कोई सुनने वाला है जब लेआउट पूरी तरह से लोड हो गया है। ?
सागर नायक

क्या अपवाद दोनों में या दोनों newLatLngBounds()में उठाया गया है animateCamera()? क्या कैच-ब्रांच से नया अपवाद नहीं होगा?
कूलमाइंड

1

यदि आपको शुरू करने के लिए संभावित उपयोगकर्ता इंटरैक्शन की प्रतीक्षा करने की आवश्यकता है, OnMapLoadedCallbackतो पिछले उत्तरों में वर्णित अनुसार उपयोग करें । लेकिन, अगर आपको नक्शे के लिए एक डिफ़ॉल्ट स्थान प्रदान करना है, तो उन उत्तरों में उल्लिखित किसी भी समाधान की कोई आवश्यकता नहीं है। दोनों MapFragmentऔर MapViewएक स्वीकार कर सकते हैं GoogleMapOptionsशुरू कि डिफ़ॉल्ट स्थान सब ठीक प्रदान कर सकते हैं पर। एकमात्र ट्रिक उन्हें सीधे अपने लेआउट में शामिल नहीं करना है क्योंकि सिस्टम उन्हें विकल्पों के बिना कॉल करेगा, लेकिन उन्हें गतिशील रूप से आरंभ करने के लिए।

इसे अपने लेआउट में उपयोग करें:

<FrameLayout
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

और अपने में टुकड़े को बदलें onCreateView():

GoogleMapOptions options = new GoogleMapOptions();
options.camera(new CameraPosition.Builder().target(location).zoom(15).build());
// other options calls if required

SupportMapFragment fragment = (SupportMapFragment) getFragmentManager().findFragmentById(R.id.map);
if (fragment == null) {
  FragmentTransaction transaction = getFragmentManager().beginTransaction();
  fragment = SupportMapFragment.newInstance(options);
  transaction.replace(R.id.map, fragment).commit();
  getFragmentManager().executePendingTransactions();
}
if (fragment != null)
  GoogleMap map = fragment.getMap();

शुरू करने के लिए तेज़ होने के अलावा, कोई दुनिया का नक्शा पहले नहीं दिखाया जाएगा और दूसरा कैमरा चाल होगा। मानचित्र सीधे निर्दिष्ट स्थान से शुरू होगा।


0

एक अन्य दृष्टिकोण कुछ ऐसा होगा (मान लें कि आपका सबसे ऊपरी दृश्य एक फ्रेम -आउट नाम है rootContainer, भले ही वह तब तक काम करेगा जब तक आप हमेशा अपने सबसे ऊपरी कंटेनर का चयन करें चाहे वह किस प्रकार या नाम का हो):

((FrameLayout)findViewById(R.id.rootContainer)).getViewTreeObserver()
    .addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        public void onGlobalLayout() {
            layoutDone = true;
        }
    });

केवल काम के लिए अपने कैमरे कार्यों को संशोधित करता है, तो layoutDoneयह है trueअतिरिक्त कार्यों को जोड़ने या करने के लिए तर्क ऊपर तार किए बिना अपने सभी समस्याओं का समाधान होगा layoutListenerहैंडलर।


0

मुझे यह काम करने के लिए मिला और अन्य समाधानों की तुलना में अधिक सरल है:

private void moveMapToBounds(final CameraUpdate update) {
    try {
        if (movedMap) {
            // Move map smoothly from the current position.
            map.animateCamera(update);
        } else {
            // Move the map immediately to the starting position.
            map.moveCamera(update);
            movedMap = true;
        }
    } catch (IllegalStateException e) {
        // Map may not be laid out yet.
        getWindow().getDecorView().post(new Runnable() {
            @Override
            public void run() {
                moveMapToBounds(update);
            }
        });
    }
}

लेआउट चलने के बाद यह फिर से कॉल की कोशिश करता है। शायद एक अनंत लूप से बचने के लिए एक सुरक्षा शामिल कर सकता है।


0

सिर्फ कुछ इस तरह का उपयोग क्यों न करें:

CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds(builder.build(), padding);
try {
    map.moveCamera(cameraUpdate);
} catch (Exception e) {
    int width = getResources().getDisplayMetrics().widthPixels;
    int height = getResources().getDisplayMetrics().heightPixels;
    cameraUpdate = CameraUpdateFactory.newLatLngBounds(builder.build(), width, height, padding);
    map.moveCamera(cameraUpdate);
}

ट्राइ newLatLngBounds(builder.build(), padding)-कैच के अंदर क्यों नहीं है? क्या यह अपवाद होता है moveCamera()?
कूलमाइंड

0

Google मानचित्र रेपो में एक सहायक वर्ग है जिसका आप लाभ उठा सकते हैं - यह लेआउट और मानचित्र दोनों का इंतजार करता है जो GoogleMap के साथ कॉलबैक सूचित करने से पहले तैयार हो:

मूल स्रोत यहां है:

https://github.com/googlemaps/android-samples/blob/7ee737b8fd6d39c77f8b3716ba948e1ce3730e61/ApiDemos/java/app/src/main/java/com/example/mapdemo/OnMapAndViewReadyListener.java

एक कोटलिन कार्यान्वयन भी है:

https://github.com/googlemaps/android-samples/blob/master/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/OnMapAndViewReadyListener.kt

public class OnMapAndViewReadyListener implements OnGlobalLayoutListener, OnMapReadyCallback {

/** A listener that needs to wait for both the GoogleMap and the View to be initialized. */
public interface OnGlobalLayoutAndMapReadyListener {
    void onMapReady(GoogleMap googleMap);
}

private final SupportMapFragment mapFragment;
private final View mapView;
private final OnGlobalLayoutAndMapReadyListener devCallback;

private boolean isViewReady;
private boolean isMapReady;
private GoogleMap googleMap;

public OnMapAndViewReadyListener(
        SupportMapFragment mapFragment, OnGlobalLayoutAndMapReadyListener devCallback) {
    this.mapFragment = mapFragment;
    mapView = mapFragment.getView();
    this.devCallback = devCallback;
    isViewReady = false;
    isMapReady = false;
    googleMap = null;

    registerListeners();
}

private void registerListeners() {
    // View layout.
    if ((mapView.getWidth() != 0) && (mapView.getHeight() != 0)) {
        // View has already completed layout.
        isViewReady = true;
    } else {
        // Map has not undergone layout, register a View observer.
        mapView.getViewTreeObserver().addOnGlobalLayoutListener(this);
    }

    // GoogleMap. Note if the GoogleMap is already ready it will still fire the callback later.
    mapFragment.getMapAsync(this);
}

@Override
public void onMapReady(GoogleMap googleMap) {
    // NOTE: The GoogleMap API specifies the listener is removed just prior to invocation.
    this.googleMap = googleMap;
    isMapReady = true;
    fireCallbackIfReady();
}

@SuppressWarnings("deprecation")  // We use the new method when supported
@SuppressLint("NewApi")  // We check which build version we are using.
@Override
public void onGlobalLayout() {
    // Remove our listener.
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
        mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    } else {
        mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }
    isViewReady = true;
    fireCallbackIfReady();
}

private void fireCallbackIfReady() {
    if (isViewReady && isMapReady) {
        devCallback.onMapReady(googleMap);
    }
}
}

0

जैसा कि OnCameraChangeListener () में बताया गया है , setOnCameraChangeListenerअब पदावनत हो गया है। तो आपको इसे तीन मेथोड में से एक से बदलना चाहिए:

  • GoogleMap.OnCameraMoveStartedListener
  • GoogleMap.OnCameraMoveListener
  • GoogleMap.OnCameraIdleListener

मेरे मामले में, मैंने उपयोग किया OnCameraIdleListenerऔर अंदर मैंने इसे हटा दिया क्योंकि इसे किसी भी आंदोलन पर फिर से और फिर से लागू किया गया था।

googleMap.setOnCameraIdleListener {
    googleMap.setOnCameraIdleListener(null) // It removes the listener.
    googleMap.moveCamera(track)
    googleMap.cameraPosition
    clusterManager!!.cluster()
    // Add another listener to make ClusterManager correctly zoom clusters and markers.
    googleMap.setOnCameraIdleListener(clusterManager)
}

अपडेट करें

मैंने googleMap.setOnCameraIdleListenerअपनी परियोजना में हटा दिया , क्योंकि यह कभी-कभी नहीं बुलाया जाता था जब एक नक्शा दिखाया गया था, लेकिन बनाए रखा गया था googleMap.setOnCameraIdleListener(clusterManager)


आपके उत्तर के लिए धन्यवाद। मैं पहले से ही इस तरह से लगभग एक ही समाधान का पता लगा रहा हूं।
अरसलान मकबूल

@ArslanMaqbool, धन्यवाद! यदि आप अपना संस्करण साझा करते हैं तो मैं अभी प्रक्रिया में हूं और आपके लिए आभारी हूं।
कूलमाइंड

मेरी खुशी @CoolMind
Arslan Maqbool

0

मुझे mMap.animateCamera को कॉल करने की कोशिश में एक ही त्रुटि थी। मैंने इसे नीचे दिखाए गए अनुसार onMapReady फ़ंक्शन में setOnMapLoadedCallback कॉलबैक कहकर हल किया

public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

   // other codes go there

    mMap.setOnMapLoadedCallback(() -> {
            //Your code where exception occurs goes here...
            
        });
}

यह ठीक काम करना चाहिए।

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