গুগল ম্যাপস অ্যান্ড্রয়েড এপিআই ভি 2 - ইন্টারেক্টিভ ইনফো উইন্ডো (মূল অ্যান্ড্রয়েড গুগল ম্যাপের মতো)


191

InfoWindowনতুন গুগল ম্যাপস এপিআই ভি 2 সহ একটি মার্কার ক্লিক করার পরে আমি কাস্টম তৈরির চেষ্টা করছি । আমি এটি Google এর মূল মানচিত্র অ্যাপ্লিকেশনটিতে দেখতে চাই। এটার মত:

উদাহরণ চিত্র

আমার ImageButtonভিতরে থাকলে, এটি কাজ করে না - InfoWindowপুরোটি নির্বাচন করা হয় এবং কেবল এটিই নয় ImageButton। আমি পড়েছি কারণ এটি কোনও কারণ নেই Viewতবে এটি স্ন্যাপশট, তাই স্বতন্ত্র আইটেমগুলি একে অপরের থেকে আলাদা করা যায় না।

সম্পাদনা করুন: ইন ডকুমেন্টেশন (ধন্যবাদ ডিস্কো আছে S2 ):

পূর্ববর্তী বিভাগে তথ্য উইন্ডোতে উল্লিখিত হিসাবে, একটি তথ্য উইন্ডোটি লাইভ ভিউ নয়, বরং মানচিত্রটিতে চিত্রটি চিত্র হিসাবে রেন্ডার করা হয়েছে। ফলস্বরূপ, আপনি যে শ্রোতা দর্শনে সেট করেছেন তা অগ্রাহ্য করা হয়েছে এবং আপনি ভিউয়ের বিভিন্ন অংশে ক্লিক ইভেন্টগুলির মধ্যে পার্থক্য করতে পারবেন না। আপনাকে আপনার কাস্টম তথ্য উইন্ডোর মধ্যে ইন্টারেক্টিভ উপাদানগুলি - যেমন বোতাম, চেকবক্স, বা পাঠ্য ইনপুটগুলি না রাখার পরামর্শ দেওয়া হচ্ছে।

তবে গুগল যদি এটি ব্যবহার করে তবে অবশ্যই এটি তৈরি করার কিছু উপায় থাকতে হবে। কারও কি কোন ধারণা আছে?


"এটি কাজ করছে না" আপনার লক্ষণগুলির একটি বিশেষ উপকারী বর্ণনা নয়। এখানে একটি নমুনা প্রকল্প রয়েছে যা একটি চিত্র সহ একটি কাস্টম তথ্য উইন্ডো দেখায়: github.com/commonsguy/cw-omnibus/tree/master/MapsV2/Pupups
CommonsWare

8
@ কমন্সওয়্যার আমি এর কারণ লিখেছি। মূল ডকুমেন্টেশন থেকে দ্রষ্টব্য: আঁকা তথ্য উইন্ডোটি লাইভ ভিউ নয়। দৃশ্যটি চিত্র হিসাবে রেন্ডার করা হয়েছে (ব্যবহার করে View.draw(Canvas)) ... এর অর্থ হল ভিউটিতে পরবর্তী কোনও পরিবর্তন মানচিত্রে তথ্য উইন্ডো দ্বারা প্রতিবিম্বিত হবে না। পরবর্তীকালে তথ্য উইন্ডো আপডেট করার জন্য, তথ্য উইন্ডোটি স্পর্শ বা অঙ্গভঙ্গি ইভেন্টগুলির মতো কোনও সাধারণ দৃশ্যের জন্য আদর্শ ইন্টারেক্টিভিটির কোনওটিকে সম্মান করবে না। তবে আপনি নীচের বিভাগে বর্ণিত পুরো তথ্য উইন্ডোতে জেনেরিক ক্লিক ইভেন্ট শুনতে পারেন। ... আপনার উদাহরণে কেবল পাঠ্যদর্শন
ব্যবহারকারী 1943012

হাই, পুরো স্ক্রিন মোডে থাকা অবস্থায় আপনি অ্যাকশন বারের নীচে আমার লোকেশন বোতামটি কীভাবে পাবেন? ধন্যবাদ!
tkblackbelt

45
আমি মনে করি না যে এই প্রশ্নটি বন্ধ করা উচিত। আমি যে সমস্যার মুখোমুখি হচ্ছি এটি একটি আইনী প্রশ্ন।
মেরিঙ্কে

12
আমি এটি প্রায়শই দেখতে পাচ্ছি, উত্তর সহ অনেক দরকারী প্রশ্নগুলি বন্ধ হয়ে গেছে। একটি প্রশ্ন সর্বদা যথাযথ প্রশ্নের যথাযথ প্রয়োজনীয়তার সাথে খাপ খায় না তবে আমাদের যদি একটি ভালভাবে ব্যাখ্যা করা সমস্যা এবং একটি উত্তরের উত্তর থাকে তবে প্রশ্নটি বন্ধ করার কোনও কারণ নেই। লোকেরা স্ট্যাকওভারফ্লো ব্যবহার করে জ্ঞান বিনিময় করতে এবং একটি প্রশ্ন থ্রেড বন্ধ করে দেয় যা "অফ-টপিক" হিসাবে এতটা সক্রিয় এবং উত্পাদনশীল হিসাবে আমার কাছে ভাল ধারণা বলে মনে হয় না ..
জন

উত্তর:


333

আমি কোনও ভাগ্য ছাড়াই নিজেই এই সমস্যার সমাধানের সন্ধান করছিলাম, তাই আমাকে নিজের রোল করতে হয়েছিল যা আমি এখানে আপনার সাথে ভাগ করতে চাই। (দয়া করে আমার খারাপ ইংরাজিকে ক্ষমা করুন) (ইংরেজিতে অন্য একজন চেক লোকের উত্তর দেওয়ার জন্য এটি একটু পাগল :-))

আমি প্রথমে চেষ্টা করেছিলাম একটি ভাল পুরানো ব্যবহার করা PopupWindow। এটি বেশ সহজ - একজনকে কেবল শুনতে হবে OnMarkerClickListenerএবং তারপরে PopupWindowমার্কারের উপরে একটি কাস্টম প্রদর্শন করতে হবে। স্ট্যাকওভারফ্লোতে এখানে থাকা অন্য কয়েকজন লোক এই সমাধানটির পরামর্শ দিয়েছে এবং এটি প্রথম নজরে আসলে বেশ ভাল দেখাচ্ছে। আপনি যখন মানচিত্রটি চারপাশে সরাতে শুরু করবেন তখন এই সমাধানটির সমস্যাটি দেখা যাচ্ছে। আপনাকে PopupWindowএকরকম নিজেকে সরিয়ে নিতে হবে যা সম্ভব (কিছু টিউচ ইভেন্ট শুনে) তবে আইএমএইচও আপনি এটিকে যথেষ্ট ভাল দেখাচ্ছে না, বিশেষত কিছু ধীর ডিভাইসগুলিতে। আপনি যদি এটি সহজ উপায়টি করেন তবে এটি একটি স্পট থেকে অন্য জায়গায় চলে আসে "লাফিয়ে"। আপনি এই জাম্পগুলিকে পোলিশ করতে কিছু অ্যানিমেশনও ব্যবহার করতে পারেন তবে এই পথে PopupWindowসর্বদা "একটি পদক্ষেপ পিছনে" থাকবে যেখানে এটি মানচিত্রটিতে থাকা উচিত যা আমি পছন্দ করি না।

এই মুহুর্তে, আমি অন্য কিছু সমাধান সম্পর্কে ভাবছিলাম। আমি বুঝতে পেরেছিলাম যে সত্যিকার অর্থে আমার এতটা স্বাধীনতার প্রয়োজন নেই - এটির সাথে আসা সমস্ত সম্ভাবনার সাথে আমার কাস্টম মতামতগুলি দেখানোর জন্য (যেমন অ্যানিমেটেড অগ্রগতি বার ইত্যাদি)। আমি মনে করি গুগল ইঞ্জিনিয়াররা এমনকি গুগল ম্যাপস অ্যাপ্লিকেশনটিতে এটি না করানোর একটি ভাল কারণ রয়েছে। আমার কেবলমাত্র তথ্য উইন্ডোতে একটি বা দুটি বাটন যা একটি চাপা অবস্থা দেখতে পাবে এবং ক্লিক করার পরে কিছু ক্রিয়া শুরু করবে। সুতরাং আমি আরও একটি সমাধান নিয়ে এসেছি যা দুটি ভাগে বিভক্ত:

প্রথম অংশ:
প্রথম অংশটি কিছু ক্রিয়াকলাপ ঘটাতে বোতামগুলিতে ক্লিকগুলি ধরতে সক্ষম হবে। আমার ধারণাটি নিম্নরূপ:

  1. ইনফো উইন্ডোএডাপ্টারে তৈরি কাস্টম ইনফো উইন্ডোর একটি রেফারেন্স রাখুন।
  2. MapFragment(বা MapView) একটি কাস্টম ভিউগ্রুপের ভিতরে মোড়ানো ( খনিটিকে ম্যাপওয়্যার্পারলাইআউট বলা হয়)
  3. MapWrapperLayoutএর ডিসপ্যাচ টাচ ইভেন্টকে ওভাররাইড করুন এবং (যদি বর্তমানে ইনফো উইন্ডো দেখানো হয়) প্রথমটি মোশনইভেন্টসকে পূর্বের তৈরি ইনফো উইন্ডোতে যান। যদি এটি মোশনএভেন্টস গ্রাস না করে (যেমন আপনি ইনফুইন্ডো ইত্যাদির অভ্যন্তরে কোনও ক্লিকযোগ্য স্থানে ক্লিক করেন নি) তবে (এবং কেবল তখনই) ইভেন্টগুলি মানচিত্রের ল্যাপআউটের সুপারক্লাসে নামতে দিন যাতে এটি শেষ পর্যন্ত মানচিত্রে সরবরাহ করা হবে।

এখানে মানচিত্রের ল্যাপআউটটির উত্স কোডটি রয়েছে:

package com.circlegate.tt.cg.an.lib.map;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.Marker;

import android.content.Context;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;

public class MapWrapperLayout extends RelativeLayout {
    /**
     * Reference to a GoogleMap object 
     */
    private GoogleMap map;

    /**
     * Vertical offset in pixels between the bottom edge of our InfoWindow 
     * and the marker position (by default it's bottom edge too).
     * It's a good idea to use custom markers and also the InfoWindow frame, 
     * because we probably can't rely on the sizes of the default marker and frame. 
     */
    private int bottomOffsetPixels;

    /**
     * A currently selected marker 
     */
    private Marker marker;

    /**
     * Our custom view which is returned from either the InfoWindowAdapter.getInfoContents 
     * or InfoWindowAdapter.getInfoWindow
     */
    private View infoWindow;    

    public MapWrapperLayout(Context context) {
        super(context);
    }

    public MapWrapperLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MapWrapperLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    /**
     * Must be called before we can route the touch events
     */
    public void init(GoogleMap map, int bottomOffsetPixels) {
        this.map = map;
        this.bottomOffsetPixels = bottomOffsetPixels;
    }

    /**
     * Best to be called from either the InfoWindowAdapter.getInfoContents 
     * or InfoWindowAdapter.getInfoWindow. 
     */
    public void setMarkerWithInfoWindow(Marker marker, View infoWindow) {
        this.marker = marker;
        this.infoWindow = infoWindow;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean ret = false;
        // Make sure that the infoWindow is shown and we have all the needed references
        if (marker != null && marker.isInfoWindowShown() && map != null && infoWindow != null) {
            // Get a marker position on the screen
            Point point = map.getProjection().toScreenLocation(marker.getPosition());

            // Make a copy of the MotionEvent and adjust it's location
            // so it is relative to the infoWindow left top corner
            MotionEvent copyEv = MotionEvent.obtain(ev);
            copyEv.offsetLocation(
                -point.x + (infoWindow.getWidth() / 2), 
                -point.y + infoWindow.getHeight() + bottomOffsetPixels);

            // Dispatch the adjusted MotionEvent to the infoWindow
            ret = infoWindow.dispatchTouchEvent(copyEv);
        }
        // If the infoWindow consumed the touch event, then just return true.
        // Otherwise pass this event to the super class and return it's result
        return ret || super.dispatchTouchEvent(ev);
    }
}

এই সমস্তগুলি আবার ইনফ্লিউভিউতে "লাইভ" এর মতামত তৈরি করবে - অনক্লিকলিস্টনাররা ট্রিগার শুরু করবে ইত্যাদি etc.

দ্বিতীয় অংশ: অবশিষ্ট সমস্যাটি হ'ল স্পষ্টতই, আপনি স্ক্রিনে আপনার ইনফো উইন্ডোর কোনও ইউআই পরিবর্তন দেখতে পাচ্ছেন না। এটি করতে আপনাকে ম্যানুয়ালি মার্কার.শোআইনফো উইন্ডো কল করতে হবে। এখন, আপনি যদি আপনার ইনফো উইন্ডোতে কিছু স্থায়ী পরিবর্তন করেন (যেমন আপনার বোতামটির লেবেল অন্য কোনওটিতে পরিবর্তন করা) তবে এটি যথেষ্ট ভাল।

তবে একটি বোতাম চেপে থাকা অবস্থা বা সেই প্রকৃতির কিছু দেখানো আরও জটিল। প্রথম সমস্যাটি হ'ল, এটি (কমপক্ষে) আমি ইনফো উইন্ডোটিকে সাধারণ বোতামের চাপা অবস্থায় দেখানোতে সক্ষম হইনি। এমনকি যদি আমি দীর্ঘক্ষণ ধরে বোতাম টিপতাম তবে এটি কেবল পর্দায় চাপবিহীন থাকে। আমি বিশ্বাস করি এটি হ'ল মানচিত্রের কাঠামো নিজেই পরিচালনা করেছেন যা সম্ভবত তথ্য উইন্ডোতে কোনও ক্ষণস্থায়ী অবস্থা না দেখানো নিশ্চিত করে। তবে আমি ভুল হতে পারি, আমি এটি সন্ধান করার চেষ্টা করিনি।

আমি যা করেছি তা অন্যটি বাজে হ্যাক - আমি OnTouchListenerবোতামটির সাথে একটি সংযুক্ত করেছি এবং দুটি কাস্টম ড্রয়যোগ্যগুলিতে বোতামটি চাপলে বা ছেড়ে দেওয়া হলে আমি নিজেই এর পটভূমিটি স্যুইচ করেছিলাম - একটি সাধারণ অবস্থায় একটি বোতামযুক্ত এবং অন্যটি চাপযুক্ত অবস্থায় in এটি খুব সুন্দর নয়, তবে এটি কাজ করে :)। এখন আমি স্ক্রিনে স্বাভাবিক থেকে চাপা রাষ্ট্রগুলির মধ্যে বাটনটি স্যুইচ করতে দেখতে সক্ষম হয়েছিল।

এখনও একটি শেষ ত্রুটি রয়েছে - আপনি বোতামটি খুব দ্রুত ক্লিক করলে এটি চাপা অবস্থায় দেখা যায় না - এটি কেবল তার স্বাভাবিক অবস্থায় থাকে (যদিও ক্লিকটি নিজেই বহিস্কার করা হয় তাই বোতামটি "কাজ করে")। অন্তত এটি আমার গ্যালাক্সি নেক্সাসে কীভাবে প্রদর্শিত হবে। সুতরাং আমি শেষ কাজটি হ'ল যে আমি এটিতে চাপ দেওয়া অবস্থায় বোতামটি বিলম্ব করেছি। এটিও বেশ কুৎসিত এবং আমি নিশ্চিত না যে এটি কিছু পুরানো, ধীর ডিভাইসে কীভাবে কাজ করবে তবে আমি সন্দেহ করি যে এমনকি মানচিত্রের কাঠামো নিজেও এই জাতীয় কিছু করে। আপনি নিজে চেষ্টা করে দেখতে পারেন - আপনি যখন পুরো ইনফো উইন্ডোটি ক্লিক করেন, তখন এটি কিছুটা চাপ দিয়ে থাকে, তারপরে সাধারণ বোতামগুলি (আবার - কমপক্ষে আমার ফোনে) থাকে) এবং এটি প্রকৃত Google মানচিত্র অ্যাপে এমনকি এটি কীভাবে কাজ করে actually

যাইহোক, আমি নিজেই একটি কাস্টম ক্লাস লিখেছিলাম যা বোতামগুলির রাজ্যের পরিবর্তনগুলি এবং আমি উল্লেখ করা অন্যান্য সমস্ত জিনিস পরিচালনা করে so সুতরাং কোডটি এখানে:

package com.circlegate.tt.cg.an.lib.map;

import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

import com.google.android.gms.maps.model.Marker;

public abstract class OnInfoWindowElemTouchListener implements OnTouchListener {
    private final View view;
    private final Drawable bgDrawableNormal;
    private final Drawable bgDrawablePressed;
    private final Handler handler = new Handler();

    private Marker marker;
    private boolean pressed = false;

    public OnInfoWindowElemTouchListener(View view, Drawable bgDrawableNormal, Drawable bgDrawablePressed) {
        this.view = view;
        this.bgDrawableNormal = bgDrawableNormal;
        this.bgDrawablePressed = bgDrawablePressed;
    }

    public void setMarker(Marker marker) {
        this.marker = marker;
    }

    @Override
    public boolean onTouch(View vv, MotionEvent event) {
        if (0 <= event.getX() && event.getX() <= view.getWidth() &&
            0 <= event.getY() && event.getY() <= view.getHeight())
        {
            switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN: startPress(); break;

            // We need to delay releasing of the view a little so it shows the pressed state on the screen
            case MotionEvent.ACTION_UP: handler.postDelayed(confirmClickRunnable, 150); break;

            case MotionEvent.ACTION_CANCEL: endPress(); break;
            default: break;
            }
        }
        else {
            // If the touch goes outside of the view's area
            // (like when moving finger out of the pressed button)
            // just release the press
            endPress();
        }
        return false;
    }

    private void startPress() {
        if (!pressed) {
            pressed = true;
            handler.removeCallbacks(confirmClickRunnable);
            view.setBackground(bgDrawablePressed);
            if (marker != null) 
                marker.showInfoWindow();
        }
    }

    private boolean endPress() {
        if (pressed) {
            this.pressed = false;
            handler.removeCallbacks(confirmClickRunnable);
            view.setBackground(bgDrawableNormal);
            if (marker != null) 
                marker.showInfoWindow();
            return true;
        }
        else
            return false;
    }

    private final Runnable confirmClickRunnable = new Runnable() {
        public void run() {
            if (endPress()) {
                onClickConfirmed(view, marker);
            }
        }
    };

    /**
     * This is called after a successful click 
     */
    protected abstract void onClickConfirmed(View v, Marker marker);
}

এখানে আমি ব্যবহার করেছি এমন একটি কাস্টম ইনফো উইন্ডো লেআউট ফাইল রয়েছে:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical" >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_marginRight="10dp" >

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:text="Title" />

        <TextView
            android:id="@+id/snippet"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="snippet" />

    </LinearLayout>

    <Button
        android:id="@+id/button" 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />

</LinearLayout>

পরীক্ষার ক্রিয়াকলাপ বিন্যাস ফাইল (এর MapFragmentভিতরে থাকা MapWrapperLayout):

<com.circlegate.tt.cg.an.lib.map.MapWrapperLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map_relative_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

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

</com.circlegate.tt.cg.an.lib.map.MapWrapperLayout>

এবং পরিশেষে একটি পরীক্ষার ক্রিয়াকলাপের উত্স কোড, যা এই সমস্তকে একসাথে আটকায়:

package com.circlegate.testapp;

import com.circlegate.tt.cg.an.lib.map.MapWrapperLayout;
import com.circlegate.tt.cg.an.lib.map.OnInfoWindowElemTouchListener;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {    
    private ViewGroup infoWindow;
    private TextView infoTitle;
    private TextView infoSnippet;
    private Button infoButton;
    private OnInfoWindowElemTouchListener infoButtonListener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final MapFragment mapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id.map);
        final MapWrapperLayout mapWrapperLayout = (MapWrapperLayout)findViewById(R.id.map_relative_layout);
        final GoogleMap map = mapFragment.getMap();

        // MapWrapperLayout initialization
        // 39 - default marker height
        // 20 - offset between the default InfoWindow bottom edge and it's content bottom edge 
        mapWrapperLayout.init(map, getPixelsFromDp(this, 39 + 20)); 

        // We want to reuse the info window for all the markers, 
        // so let's create only one class member instance
        this.infoWindow = (ViewGroup)getLayoutInflater().inflate(R.layout.info_window, null);
        this.infoTitle = (TextView)infoWindow.findViewById(R.id.title);
        this.infoSnippet = (TextView)infoWindow.findViewById(R.id.snippet);
        this.infoButton = (Button)infoWindow.findViewById(R.id.button);

        // Setting custom OnTouchListener which deals with the pressed state
        // so it shows up 
        this.infoButtonListener = new OnInfoWindowElemTouchListener(infoButton,
                getResources().getDrawable(R.drawable.btn_default_normal_holo_light),
                getResources().getDrawable(R.drawable.btn_default_pressed_holo_light)) 
        {
            @Override
            protected void onClickConfirmed(View v, Marker marker) {
                // Here we can perform some action triggered after clicking the button
                Toast.makeText(MainActivity.this, marker.getTitle() + "'s button clicked!", Toast.LENGTH_SHORT).show();
            }
        }; 
        this.infoButton.setOnTouchListener(infoButtonListener);


        map.setInfoWindowAdapter(new InfoWindowAdapter() {
            @Override
            public View getInfoWindow(Marker marker) {
                return null;
            }

            @Override
            public View getInfoContents(Marker marker) {
                // Setting up the infoWindow with current's marker info
                infoTitle.setText(marker.getTitle());
                infoSnippet.setText(marker.getSnippet());
                infoButtonListener.setMarker(marker);

                // We must call this to set the current marker and infoWindow references
                // to the MapWrapperLayout
                mapWrapperLayout.setMarkerWithInfoWindow(marker, infoWindow);
                return infoWindow;
            }
        });

        // Let's add a couple of markers
        map.addMarker(new MarkerOptions()
            .title("Prague")
            .snippet("Czech Republic")
            .position(new LatLng(50.08, 14.43)));

        map.addMarker(new MarkerOptions()
            .title("Paris")
            .snippet("France")
            .position(new LatLng(48.86,2.33)));

        map.addMarker(new MarkerOptions()
            .title("London")
            .snippet("United Kingdom")
            .position(new LatLng(51.51,-0.1)));
    }

    public static int getPixelsFromDp(Context context, float dp) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int)(dp * scale + 0.5f);
    }
}

এটাই. এখন পর্যন্ত আমি কেবল এটি আমার গ্যালাক্সি নেক্সাস (৪.২.১) এবং নেক্সাস 7 (এছাড়াও ৪.২.১) এ পরীক্ষা করেছি, সুযোগ পেলে আমি কিছু জিঞ্জারব্রেড ফোনে চেষ্টা করব। আমি এখনও অবধি খুঁজে পেয়েছি এমন একটি সীমাবদ্ধতা হ'ল আপনি স্ক্রিনে আপনার বোতামটি যেখান থেকে মানচিত্রটি টানতে পারবেন না এবং মানচিত্রটিকে চারদিকে সরাতে পারবেন না। এটি সম্ভবত একরকম কাটিয়ে উঠতে পারে তবে আপাতত, আমি তার সাথেই বেঁচে থাকতে পারি।

আমি জানি এটি একটি কুৎসিত হ্যাক তবে আমি আরও ভাল কিছু পাইনি এবং আমার এই নকশার প্যাটার্নটি এত খারাপভাবে প্রয়োজন যে এটি মানচিত্রের ভি 1 কাঠামোতে ফিরে যাওয়ার সত্যিই কারণ হতে পারে (যা বিটিডব্লিউ। আমি সত্যিই এড়াতে চাই টুকরো ইত্যাদি সহ নতুন অ্যাপের জন্য) for আমি কেবল বুঝতে পারি না যে কেন গুগল বিকাশকারীদের ইনফো উইন্ডোতে একটি বোতাম রাখার কোনও সরকারী উপায়ে অফার করে না। এটি এমন একটি সাধারণ নকশার প্যাটার্ন, তবুও এই প্যাটার্নটি এমনকি সরকারী গুগল ম্যাপস অ্যাপ্লিকেশনটিতেও ব্যবহৃত হয় :)। আমি কেন কারণগুলি বুঝতে পারি যে তারা ইনফোউইন্ডোগুলিতে কেবল আপনার দৃষ্টিভঙ্গিগুলিকে "লাইভ" করতে পারে না - এটি সম্ভবত মানচিত্রের আশেপাশে এবং স্ক্রোল করার সময় পারফরম্যান্সকে মেরে ফেলবে। তবে মতামত ব্যবহার না করে কীভাবে এই প্রভাব অর্জন করবেন তার কিছু উপায় থাকতে হবে।


6
আকর্ষণীয় সমাধান। আমি এটা ট্রাই করতে চাই. পারফরম্যান্স কেমন ছিল?
প্যাট্রিক

10
প্রতিস্থাপন করা প্রয়োজন view.setBackground(bgDrawablePressed);সঙ্গে if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { view.setBackgroundDrawable(bgDrawablePressed); }else{ view.setBackground(bgDrawablePressed); }, অ্যান্ড্রয়েড জিনজার ব্রেড কাজ করার নোট: এক আরো সংঘটন আছে view.setBackgroundকোডে।
বালাজি

4
KK_07k11A0585: মনে হচ্ছে আপনার ইনফো উইন্ডো অ্যাডাপ্টার প্রয়োগটি সম্ভবত ভুল। ওভাররাইড করার জন্য দুটি পদ্ধতি রয়েছে: getInfoWindow () এবং getInfoContents ()। কাঠামোটি প্রথমে getInfoWindow () পদ্ধতি এবং (কেবলমাত্র) যদি এটি শূন্য হয়, এটি getInfoContents () বলে। যদি আপনি getInfoWindow থেকে কিছু দর্শন ফিরিয়ে দেন তবে ফ্রেমওয়ার্কটি এটি ডিফল্ট তথ্য উইন্ডো ফ্রেমের ভিতরে রাখবে - যা আপনার ক্ষেত্রে আপনি চান না। সুতরাং কেবল getInfoWindow থেকে শূন্য ফিরে আসুন এবং getInfoContent থেকে আপনাকে দেখুন ফিরিয়ে দিন এবং এটি ঠিক আছে।
chose007

18
যদি কারও আগ্রহী, আমি এই সমাধানটি আমার নিজের অ্যাপ - সিজি ট্রানজিটে (আপনি এটি গুগল প্লেতে সন্ধান করতে পারেন) ব্যবহার করছি। দুই মাস পরে এটি কয়েক হাজার হাজার ব্যবহারকারী ব্যবহার করেছেন এবং এটি সম্পর্কে কেউ এখনও অভিযোগ করেনি।
chose007

2
আপনি যদি কোনও স্ট্যান্ডার্ড ইনফিনডো ব্যবহার না করে তবে নীচের অফসেটটি কীভাবে নির্ধারণ করবেন?
21

12

আমি দেখতে পাচ্ছি যে এই প্রশ্নটি ইতিমধ্যে পুরানো তবে এখনও ...

যা ইচ্ছা তা অর্জনের জন্য আমরা আমাদের সংস্থায় একটি শিপমিল গ্রন্থাগার তৈরি করেছি - ভিউ এবং সবকিছু সহ একটি ইন্টারেক্টিভ ইনফর্ম উইন্ডো। আপনি গিথুব এ এটি পরীক্ষা করে দেখতে পারেন ।

আমি আসা করি এটা সাহায্য করবে :)


এটি গুচ্ছ দ্বারা ব্যবহার করা সম্ভব?
gcolucci

9

সমস্যাটি আমার এখানে দেওয়া। আমি AbsoluteLayoutওভারলে তৈরি করি যাতে তথ্য উইন্ডো থাকে (প্রতিটি বিট ইন্টারেক্টিভিটি এবং অঙ্কন ক্ষমতা সহ একটি নিয়মিত দৃশ্য)। তারপরে আমি শুরু করি Handlerযা প্রতি 16 এমএসে পয়েন্টের অবস্থানের সাথে তথ্য উইন্ডোটির অবস্থানকে সিঙ্ক্রোনাইজ করে। মনে হচ্ছে পাগল, তবে আসলে কাজ করে।

ডেমো ভিডিও: https://www.youtube.com/watch?v=bT9RpH4p9mU (একযোগে এমুলেটর এবং ভিডিও রেকর্ডিং চলার কারণে কর্মক্ষমতা হ্রাস পেয়েছে তা বিবেচনা করুন)।

ডেমোর কোড: https://github.com/deville/info-window-demo

বিশদ সরবরাহকারী একটি নিবন্ধ (রাশিয়ান ভাষায়): http://habrahabr.ru/post/213415/


এটি মানচিত্রটিকে স্ক্রোল করে গতি কমিয়ে / পিছিয়ে দেবে
শেন একনায়কে

2

যারা choose007'sউত্তর এবং দৌড়াতে পারে না তাদের জন্য

clickListenerসমাধানে যদি সর্বদা সঠিকভাবে কাজ না করে থাকে তবে পরিবর্তে chose007'sবাস্তবায়নের চেষ্টা করুন । কোনও ক্রিয়া বা ব্যবহার করে স্পর্শ ইভেন্ট হ্যান্ডেল করুন । কোনও কারণে, প্রেরণের সময় মানচিত্রগুলি কিছু অদ্ভুত আচরণের কারণ হয় ।View.onTouchListenerclickListenerACTION_UPACTION_DOWNinfoWindowclickListeners

infoWindow.findViewById(R.id.my_view).setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
          int action = MotionEventCompat.getActionMasked(event);
          switch (action){
                case MotionEvent.ACTION_UP:
                    Log.d(TAG,"a view in info window clicked" );
                    break;
                }
                return true;
          }

সম্পাদনা করুন: আমি এভাবেই ধাপে ধাপে এটি করেছি

প্রথমে আপনার ক্রিয়াকলাপ / খণ্ডের কোথাও আপনার নিজের ইনফোইন্ডো (গ্লোবাল ভেরিয়েবল) স্ফীত করুন। খনি খণ্ডের মধ্যে। এছাড়াও নিশ্চিত করুন যে আপনার ইনফাইন্ডো লেআউটে রুট ভিউটি লিনিয়ারালআউট (কোনও কারণে আপেক্ষিক প্লেয়ারটি ইনফাইন্ডে স্ক্রিনের পুরো প্রস্থ গ্রহণ করছে)

infoWindow = (ViewGroup) getActivity().getLayoutInflater().inflate(R.layout.info_window, null);
/* Other global variables used in below code*/
private HashMap<Marker,YourData> mMarkerYourDataHashMap = new HashMap<>();
private GoogleMap mMap;
private MapWrapperLayout mapWrapperLayout;

তারপরে গুগল ম্যাপস অ্যান্ড্রয়েড এপি'র ম্যাপআরেডি কলব্যাকে ( মানচিত্র> ডকুমেন্টেশন - শুরু করা অনম্যাপ্রেডিটি কী তা যদি আপনি না জানেন তবে এটি অনুসরণ করুন )

   @Override
    public void onMapReady(GoogleMap googleMap) {
       /*mMap is global GoogleMap variable in activity/fragment*/
        mMap = googleMap;
       /*Some function to set map UI settings*/ 
        setYourMapSettings();

MapWrapperLayoutইনিশিয়ালাইজেশন http://stackoverflow.com/questions/14123243/google-maps-android-api-v2- ইন্টারেক্টিভ-ইনফাউন্ডো-মত-আসল-অ্যান্ড্রয়েড-গো / 15040761 # 15040761 39 - ডিফল্ট মার্কার উচ্চতা 20 - এর মধ্যে অফসেট ডিফল্ট ইনফো উইন্ডো নীচের প্রান্ত এবং এটি সামগ্রীর নীচের প্রান্ত * /

        mapWrapperLayout.init(mMap, Utils.getPixelsFromDp(mContext, 39 + 20));

        /*handle marker clicks separately - not necessary*/
       mMap.setOnMarkerClickListener(this);

       mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
                @Override
                public View getInfoWindow(Marker marker) {
                    return null;
                }

            @Override
            public View getInfoContents(Marker marker) {
                YourData data = mMarkerYourDataHashMap.get(marker);
                setInfoWindow(marker,data);
                mapWrapperLayout.setMarkerWithInfoWindow(marker, infoWindow);
                return infoWindow;
            }
        });
    }

SetInfoWindow পদ্ধতি

private void setInfoWindow (final Marker marker, YourData data)
            throws NullPointerException{
        if (data.getVehicleNumber()!=null) {
            ((TextView) infoWindow.findViewById(R.id.VehicelNo))
                    .setText(data.getDeviceId().toString());
        }
        if (data.getSpeed()!=null) {
            ((TextView) infoWindow.findViewById(R.id.txtSpeed))
                    .setText(data.getSpeed());
        }

        //handle dispatched touch event for view click
        infoWindow.findViewById(R.id.any_view).setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int action = MotionEventCompat.getActionMasked(event);
                switch (action) {
                    case MotionEvent.ACTION_UP:
                        Log.d(TAG,"any_view clicked" );
                        break;
                }
                return true;
            }
        });

হ্যান্ডেল চিহ্নিতকারী আলাদাভাবে ক্লিক করুন

    @Override
    public boolean onMarkerClick(Marker marker) {
        Log.d(TAG,"on Marker Click called");
        marker.showInfoWindow();
        CameraPosition cameraPosition = new CameraPosition.Builder()
                .target(marker.getPosition())      // Sets the center of the map to Mountain View
                .zoom(10)
                .build();
        mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition),1000,null);
        return true;
    }

আপনি আমাকে আপনার কোড দেখাতে পারেন? আমি স্পর্শ ইভেন্টগুলিতে সফলভাবে লগ করতে সক্ষম হয়েছি কিন্তু ইভেন্টগুলিতে ক্লিক না করে আমি এই বাস্তবায়নের জন্য গিয়েছিলাম। এছাড়াও, আপনার পছন্দ007 এর সমাধানটি সঠিকভাবে প্রয়োগ করতে হবে।
মনীশ জাঙ্গিদ

আমি আমার সম্পূর্ণ বাস্তবায়ন ভাগ করে নিয়েছি। আপনার যদি কোনও প্রশ্ন থাকে তবে আমাকে জানতে দিন
মণীশ জানিদ

0

শুধু অনুমান, এটি চেষ্টা করার মতো আমার কাছে পর্যাপ্ত অভিজ্ঞতা নেই ...) -:

যেহেতু গুগলম্যাপ হ'ল একটি খণ্ড, তাই অন ক্লিকের ইভেন্টটি চিহ্নিতকারী এবং কাস্টম টুকরা দর্শন প্রদর্শন করা সম্ভব । একটি মানচিত্রের খণ্ডটি এখনও পটভূমিতে দৃশ্যমান হবে। কেউ কি চেষ্টা করে? কোনও কারণেই কেন এটি কাজ করতে পারেনি?

অসুবিধাটি হ'ল মানচিত্রের টুকরোটি ব্যাকগ্রাউডে জমাটবদ্ধ হবে, যতক্ষণ না কোনও কাস্টম তথ্য খণ্ডটি এতে নিয়ন্ত্রণ না করে।


5
আমি মনে করি না উত্তর হিসাবে অনুমান পোস্ট করা আকর্ষণীয়। সম্ভবত এটি মূল প্রশ্নের মন্তব্য হওয়া উচিত। শুধু আমার চিন্তা।
জোহান কার্লসন

1
এই গ্রন্থাগারটি github.com/Appolica/InteractiveInfoWindowAndroid তেমন কিছু করে
Deyan Genovski

-2

আমি এই প্রশ্নের জন্য একটি নমুনা অ্যান্ড্রয়েড স্টুডিও প্রকল্প তৈরি করেছি।

আউটপুট স্ক্রিন শট:

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

সম্পূর্ণ প্রকল্প উত্স কোড ডাউনলোড করুন এখানে ক্লিক করুন

অনুগ্রহ করে নোট করুন: আপনাকে আপনার এন্ড্রোডিম্যানিફેস্ট.এক্সএমএল এপিআই কী যুক্ত করতে হবে


5
জিপ ফাইলের পরিবর্তে গিথুব / গিস্টের মাধ্যমে আপনার কোডটি ভাগ করা ভাল। সুতরাং আমরা সরাসরি সেখানে পরীক্ষা করতে পারেন।
নওন্ডলা সন্দীপ

আমি কিছুটা বাগ পেয়েছি, যখন আপনি কিছু বোতাম টিপুন, সমস্ত বোতাম ক্লিক করা হবে।
মোরোজভ

3
@ নউন্ডলা এবং অন্যান্যরা: তার জিপড কোডটি ডাউনলোড করতে বিরক্ত করবেন না। এটি এই প্রশ্নের জন্য গৃহীত উত্তরের সঠিক কপি পেস্ট paste
গণেশ মোহন

1
@ গণেশ 2 শিব ঠিক আছে, জিপড কোডটি অকেজো। আপনাকে অনুলিপি করা হবে না অনুলিপি কোড পেস্ট কোড
ওঙ্কার নেনে

-7

এটা সত্যিই সহজ।

googleMap.setInfoWindowAdapter(new InfoWindowAdapter() {

            // Use default InfoWindow frame
            @Override
            public View getInfoWindow(Marker marker) {              
                return null;
            }           

            // Defines the contents of the InfoWindow
            @Override
            public View getInfoContents(Marker marker) {

                // Getting view from the layout file info_window_layout
                View v = getLayoutInflater().inflate(R.layout.info_window_layout, null);

                // Getting reference to the TextView to set title
                TextView note = (TextView) v.findViewById(R.id.note);

                note.setText(marker.getTitle() );

                // Returning the view containing InfoWindow contents
                return v;

            }

        });

আপনি যে ক্লাসে গুগল্যাপ ব্যবহার করছেন সেখানে কেবল উপরের কোডটি যুক্ত করুন। R.layout.info_window_layout আমাদের কাস্টম লেআউট যা দেখিয়ে দিচ্ছে যে ইনফাউন্ডোর জায়গায় আসবে। আমি এখানে এখানে পাঠ্যদর্শনটি যুক্ত করেছি। নমুনা স্ন্যাপের মতো করে তুলতে আপনি এখানে অ্যাডিটোনাল ভিউ যুক্ত করতে পারেন। আমার তথ্য_ওয়াইন্ডো_আউটআউট ছিল

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" 
    android:orientation="vertical" 
    >

        <TextView 
        android:id="@+id/note"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

আমি আশা করি এটি সাহায্য করবে আমরা কাস্টম ইনফোওয়াইন্ডোর একটি কার্যকারী উদাহরণ খুঁজে পেতে পারি http://wptrafficanalyzer.in/blog/customizing-infowindow-contents-in-google-map-android-api-v2- using-infowindowadapter / #comment-39731

সম্পাদিত: এই কোডটি দেখায় যে আমরা কীভাবে তথ্য উইন্ডোতে কাস্টম ভিউ যুক্ত করতে পারি। এই কোডটি কাস্টম ভিউ আইটেমগুলিতে ক্লিকগুলি পরিচালনা করে না। সুতরাং এটি উত্তর নিকটে কিন্তু ঠিক উত্তর না কেন এটি উত্তর হিসাবে গৃহীত হয় না।


আপনি যেখানে চিহ্নিতকারীগুলি তৈরি করেন সেখানে getInfoContents এবং getInfoWindow কে ওভাররাইড করবেন? উদাহরণস্বরূপ, আমি যদি বিভিন্ন ধরণের চিহ্নিতকারী যুক্ত করতে এবং বিভিন্ন পদ্ধতি ব্যবহার করে যাচ্ছি তবে আমি কি সেই সমস্ত পদ্ধতির শরীরের মধ্যে যেখানে আমি আলাদা চিহ্নিতকারী তৈরি করি কেবল সেখানে ওভাররাইড করব?
17:37

হ্যাঁ আমি getInfoContents এবং getInfoWindow কে ওভাররাইড করি।
জিশান মির্জা

এটি চেষ্টা করে দেখুন এবং এটি অন্য কোনও এক্সএমএল লেআউটকে
ফুটিয়ে তোলার মতো

31
দেখে মনে হচ্ছে আপনি আমার প্রশ্নটি পড়েন নি। আমি জানি কীভাবে ইনফাইন্ডোর অভ্যন্তরে কাস্টম ভিউ তৈরি করতে হয়। আমি যা জানি না তা হ'ল কীভাবে ভিতরে কাস্টম বোতাম তৈরি করা যায় এবং এর ক্লিক ইভেন্টগুলি শুনতে হয়।
ব্যবহারকারী 1943012

5
এই সমাধানটি আসল প্রশ্নের উত্তর দেয় না
biddulph.r
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.