정보 창

정보 창은 마커의 위 또는 지도의 특정 지점에 부가적인 정보를 나타내기 위한 오버레이입니다. 주로 말풍선 형태로 구성되어 텍스트를 표시하는 용도로 사용합니다. 정보 창에 노출될 정보는 어댑터에 의해 지정되므로 정보 창이 열릴 마커의 정보 등을 이용해 동적으로 내용을 갱신할 수 있습니다.

열기 및 닫기

InfoWindow는 일반적인 자바 객체처럼 생성할 수 있습니다. 정보 창을 열려면 객체를 생성하고 adapter 속성에 어댑터 객체를 지정해야 합니다.

다음은 정보 창 객체를 생성하고 어댑터를 지정하는 예제입니다.

InfoWindow infoWindow = new InfoWindow();
infoWindow.setAdapter(new InfoWindow.DefaultTextAdapter(context) {
    @NonNull
    @Override
    public CharSequence getText(@NonNull InfoWindow infoWindow) {
        return "정보 창 내용";
    }
});

Java

InfoWindow infoWindow = new InfoWindow();
infoWindow.setAdapter(new InfoWindow.DefaultTextAdapter(context) {
    @NonNull
    @Override
    public CharSequence getText(@NonNull InfoWindow infoWindow) {
        return "정보 창 내용";
    }
});

Kotlin

val infoWindow = InfoWindow()
infoWindow.adapter = object : InfoWindow.DefaultTextAdapter(context) {
    override fun getText(infoWindow: InfoWindow): CharSequence {
        return "정보 창 내용"
    }
}

이후 open() 메서드를 호출하면 정보 창이 나타납니다. 정보 창은 지도에 추가되어 있는 마커에 열거나 임의의 좌표에 열 수 있습니다. 정보 창을 마커 위에 열려면 open(Marker) 메서드를, 임의의 좌표에 열려면 position 속성을 지정한 후 open(NaverMap) 메서드를 호출합니다.

다음은 정보 창을 마커에 여는 예제입니다.

infoWindow.open(marker);

Java

infoWindow.open(marker);

Kotlin

infoWindow.open(marker)

마커에 정보창을 추가한 모습

다음은 정보 창을 임의의 좌표에 여는 예제입니다.

infoWindow.setPosition(new LatLng(37.5666102, 126.9783881));
infoWindow.open(naverMap);

Java

infoWindow.setPosition(new LatLng(37.5666102, 126.9783881));
infoWindow.open(naverMap);

Kotlin

infoWindow.position = LatLng(37.5666102, 126.9783881)
infoWindow.open(naverMap)

임의의 좌표에 정보창을 추가한 모습

close()를 호출하면 정보 창이 닫히고 지도에서 사라집니다.

다음은 정보 창을 닫는 예제입니다.

infoWindow.close();

Java

infoWindow.close();

Kotlin

infoWindow.close()

정보 창을 임의의 좌표에 열려면 open()close()를 호출하는 대신 다른 오버레이처럼 map 속성을 사용할 수도 있습니다. 속성에 지도 객체를 지정하면 open()을 호출한 것과, null을 지정하면 close()를 호출한 것과 동일한 결과가 나타납니다.

다음은 map 속성을 이용해 정보 창을 임의의 좌표에 여는 예제입니다.

infoWindow.setPosition(new LatLng(37.5670135, 126.9783740));
infoWindow.setMap(naverMap);

Java

infoWindow.setPosition(new LatLng(37.5670135, 126.9783740));
infoWindow.setMap(naverMap);

Kotlin

infoWindow.position = LatLng(37.5666102, 126.9783881)
infoWindow.map = naverMap

다음은 map 속성을 이용해 정보 창을 닫는 예제입니다.

infoWindow.setMap(null);

Java

infoWindow.setMap(null);

Kotlin

infoWindow.map = null

마커 및 지도와 상호작용

정보 창이 마커에 대해 열린 경우 정보 창과 마커 간에는 연관 관계가 형성됩니다. InfoWindow.getMarker()는 정보 창이 열린 마커를, Marker.getInfoWindow()는 마커에 열려 있는 정보 창을 반환합니다. 이러한 연관 정보를 사용하면 정보 창을 사용하는 가장 흔한 패턴인 마커를 클릭할 때 열고, 마커를 다시 클릭하거나 정보 창 바깥 영역, 즉 지도를 클릭할 때 닫는 동작을 쉽게 구현할 수 있습니다.

다음은 마커와 정보 창간의 연관 관계와 클릭 이벤트를 이용해 이러한 동작을 구현한 예제입니다.

// 지도를 클릭하면 정보 창을 닫음
naverMap.setOnMapClickListener((coord, point) -> {
    infoWindow.close();
});

// 마커를 클릭하면:
Overlay.OnClickListener listener = overlay -> {
    Marker marker = (Marker)overlay;

    if (marker.getInfoWindow() == null) {
        // 현재 마커에 정보 창이 열려있지 않을 경우 엶
        infoWindow.open(marker);
    } else {
        // 이미 현재 마커에 정보 창이 열려있을 경우 닫음
        infoWindow.close();
    }

    return true;
};

marker1.setOnClickListener(listener);
marker2.setOnClickListener(listener);
marker3.setOnClickListener(listener);

Java

// 지도를 클릭하면 정보 창을 닫음
naverMap.setOnMapClickListener((coord, point) -> {
    infoWindow.close();
});

// 마커를 클릭하면:
Overlay.OnClickListener listener = overlay -> {
    Marker marker = (Marker)overlay;

    if (marker.getInfoWindow() == null) {
        // 현재 마커에 정보 창이 열려있지 않을 경우 엶
        infoWindow.open(marker);
    } else {
        // 이미 현재 마커에 정보 창이 열려있을 경우 닫음
        infoWindow.close();
    }

    return true;
};

marker1.setOnClickListener(listener);
marker2.setOnClickListener(listener);
marker3.setOnClickListener(listener);

Kotlin

// 지도를 클릭하면 정보 창을 닫음
naverMap.setOnMapClickListener {
    infoWindow.close()
}

// 마커를 클릭하면:
val listener = Overlay.OnClickListener { overlay ->
    val marker = overlay as Marker

    if (marker.infoWindow == null) {
        // 현재 마커에 정보 창이 열려있지 않을 경우 엶
        infoWindow.open(marker)
    } else {
        // 이미 현재 마커에 정보 창이 열려있을 경우 닫음
        infoWindow.close()
    }

    true
}

marker1.onClickListener = listener
marker2.onClickListener = listener
marker3.onClickListener = listener

어댑터

adapter 속성을 사용해 정보 창에 대한 어댑터를 지정할 수 있습니다. 마커 등 이미지를 사용하는 다른 오버레이와 달리 정보 창에는 이미지를 지정하는 속성이 없습니다. 대신 어댑터 속성을 지니며, 이 속성에 지정된 어댑터 객체가 정보 창에 나타나야 할 이미지를 반환합니다. open()이 호출될 때마다 어댑터의 메서드가 호출되어 정보 창의 내용이 갱신되며, invalidate()를 호출해 명시적으로 내용을 갱신할 수도 있습니다.

정보 창에 어댑터를 지정하는 가장 간단한 방법은 InfoWindow.DefaultTextAdapter를 사용하는 것입니다. DefaultTextAdapter의 유일한 추상 메서드인 getText(InfoWindow)가 정보 창에 나타나야 할 텍스트를 반환하도록 구현하기만 하면 됩니다. 이 어댑터를 정보 창에 지정하면 기본 말풍선 이미지 내에 반환한 텍스트가 나타납니다.

다음은 InfoWindow.DefaultTextAdapter를 이용하는 예제입니다.

infoWindow.setAdapter(new InfoWindow.DefaultTextAdapter(context) {
    @NonNull
    @Override
    public CharSequence getText(@NonNull InfoWindow infoWindow) {
        return "정보 창 내용";
    }
});

Java

infoWindow.setAdapter(new InfoWindow.DefaultTextAdapter(context) {
    @NonNull
    @Override
    public CharSequence getText(@NonNull InfoWindow infoWindow) {
        return "정보 창 내용";
    }
});

Kotlin

infoWindow.adapter = object : InfoWindow.DefaultTextAdapter(context) {
    override fun getText(infoWindow: InfoWindow): CharSequence {
        return "정보 창 내용"
    }
}

정보창에 설정한 텍스트가 나타나는 모습

텍스트뿐만 아니라 복잡한 정보를 표현하려면 DefaultViewAdapter를 사용할 수 있습니다. getView(InfoWindow) 메서드가 반환한 뷰가 말풍선 내에 나타납니다. 기본 말풍선 이미지를 사용하지 않으려면 ViewAdapterAdapter를 직접 구현할 수도 있습니다.

정보 창은 어댑터 패턴을 사용하므로 정보 창이 열릴 마커나 좌표에 대한 정보를 쉽게 표현할 수 있습니다. 예를 들어, 마커를 클릭하면 마커의 속성을 정보 창으로 보여주고자 할 때, 정보 창 객체는 하나만 사용하고 어댑터가 마커의 속성에 따른 정보를 반환하도록 구현하면 됩니다.

다음은 마커를 클릭할 때마다 마커에 정보 창을 열고, tag 속성을 정보 창에 나타내는 예제입니다.

marker1.setTag("마커 1");
marker1.setOnClickListener(overlay -> {
    // 마커를 클릭할 때 정보창을 엶
    infoWindow.open(marker1);
    return true;
});

marker2.setTag("마커 2");
marker2.setOnClickListener(overlay -> {
    // 마커를 클릭할 때 정보창을 엶
    infoWindow.open(marker2);
    return true;
});

infoWindow.setAdapter(new InfoWindow.DefaultTextAdapter(context) {
    @NonNull
    @Override
    public CharSequence getText(@NonNull InfoWindow infoWindow) {
        // 정보 창이 열린 마커의 tag를 텍스트로 노출하도록 반환 
        return (CharSequence)infoWindow.getMarker().getTag();
    }
});

Java

marker1.setTag("마커 1");
marker1.setOnClickListener(overlay -> {
    // 마커를 클릭할 때 정보창을 엶
    infoWindow.open(marker1);
    return true;
});

marker2.setTag("마커 2");
marker2.setOnClickListener(overlay -> {
    // 마커를 클릭할 때 정보창을 엶
    infoWindow.open(marker2);
    return true;
});

infoWindow.setAdapter(new InfoWindow.DefaultTextAdapter(context) {
    @NonNull
    @Override
    public CharSequence getText(@NonNull InfoWindow infoWindow) {
        // 정보 창이 열린 마커의 tag를 텍스트로 노출하도록 반환 
        return (CharSequence)infoWindow.getMarker().getTag();
    }
});

Kotlin

marker1.tag = "마커 1"
marker1.setOnClickListener {
    // 마커를 클릭할 때 정보창을 엶
    infoWindow.open(marker1)
    true
}

marker2.tag = "마커 2"
marker2.setOnClickListener {
    // 마커를 클릭할 때 정보창을 엶
    infoWindow.open(marker2)
    true
}

infoWindow.adapter = object : InfoWindow.DefaultTextAdapter(context) {
    override fun getText(infoWindow: InfoWindow): CharSequence {
        // 정보 창이 열린 마커의 tag를 텍스트로 노출하도록 반환
        return infoWindow.marker?.tag as CharSequence? ?: ""
    }
}

마커의 속성에 따른 정보를 반환하는 모습 마커의 속성에 따른 정보를 반환하는 모습

단, 뷰를 반환하는 어댑터를 사용하더라도, 어댑터가 반환하는 뷰 및 하위 뷰는 클릭 이벤트를 직접 받을 수 없습니다. 예를 들어 정보 창에 여러 개의 버튼을 배치하더라도 각 버튼 뷰에 지정된 클릭 리스너의 onClick()은 호출되지 않습니다. 오직 정보 창에 지정된 클릭 리스너의 onClick()만이 호출됩니다.

배치

정보 창이 나타날 방향, 이미지의 앵커, 대상 지점과의 간격 등을 지정하면 기본 말풍선 이미지를 사용하지 않더라도 정보가 정확한 위치에 나타나도록 할 수 있습니다.

방향

정보 창은 기본적으로 마커의 위에 배치되나, open(Marker, Align)를 사용하면 배치되는 방향을 변경할 수 있습니다. 위, 아래, 왼쪽, 오른쪽, 각 대각선, 중앙 등 Align 열거형에 정의된 아홉 곳에 정보 창을 배치할 수 있습니다.

다음은 정보 창을 마커의 오른쪽에 배치하는 예제입니다.

infoWindow.open(marker, Align.Right);

Java

infoWindow.open(marker, Align.Right);

Kotlin

infoWindow.open(marker, Align.Right)

정보창을 마커의 오른쪽에 배치한 모습

앵커

anchor 속성을 지정하면 이미지가 가리키는 지점과 대상 지점을 일치시킬 수 있습니다. 앵커는 이미지에서 기준이 되는 지점을 의미하는 값으로, 이미지에서 앵커로 지정된 지점이 대상 지점에 위치하게 됩니다. 왼쪽 위가 (0, 0), 오른쪽 아래가 (1, 1)인 비율값으로 표현합니다.

앵커 속성은 기본 배경 이미지를 사용하지 않을 때 유용합니다. 예를 들어 다음 그림과 같이 오른쪽 아래에 꼬리가 달려 있는 이미지를 사용하면, 이미지에서 가리키는 지점은 오른쪽 아래이지만 정보 창은 중앙 아래를 기준으로 대상 지점에 붙어 있으므로 이미지와 정보 창의 위치 간에 이격이 발생합니다.

이미지와 정보 창의 좌표 간 이격이 발생한 모습

이 경우 앵커를 오른쪽 아래를 의미하는 (1, 1)로 지정하면 이미지와 대상 지점 간 이격을 해소할 수 있습니다.

다음은 정보 창의 앵커를 오른쪽 아래로 지정하는 예제입니다.

infoWindow.setAnchor(new PointF(1, 1));

Java

infoWindow.setAnchor(new PointF(1, 1));

Kotlin

infoWindow.anchor = PointF(1f, 1f)

정보창의 앵커를 오른쪽 아래로 지정한 모습

간격

offsetXoffsetY 속성을 이용하면 정보 창과 대상 마커 또는 좌표와의 간격을 지정할 수 있습니다. 간격 속성은 픽셀 단위이므로 이미지가 불균형해 앵커 지점을 고정할 수 없는 경우 유용합니다. 예를 들어 다음 그림과 같이 오른쪽 아래로부터 왼쪽으로 50픽셀 떨어진 지점에 꼬리가 달려 있는 이미지를 사용하면 콘텐츠의 크기에 따라 적합한 앵커 지점이 변경됩니다.

앵커 지점을 고정할 수 없는 경우 1 앵커 지점을 고정할 수 없는 경우 2

이 경우 앵커는 오른쪽 아래를 의미하는 (1, 1)로 지정하고 offsetX-50픽셀로 지정하면 이미지와 대상 지점 간 이격을 해소할 수 있습니다.

다음은 이미지가 늘어나더라도 꼬리가 올바른 위치에 나타나도록 정보 창의 앵커와 오프셋을 지정하는 예제입니다.

infoWindow.setAnchor(new PointF(1, 1));
infoWindow.setOffsetX(-50);

Java

infoWindow.setAnchor(new PointF(1, 1));
infoWindow.setOffsetX(-50);

Kotlin

infoWindow.anchor = PointF(1f, 1f)
infoWindow.offsetX = -50

x축 오프셋을 지정한 모습 1 x축 오프셋을 지정한 모습 2

불투명

alpha 속성을 이용하면 정보 창의 불투명도를 지정할 수 있습니다. 값의 범위는 0~1이며, 0일 경우 완전히 투명, 1일 경우 완전히 불투명한 상태가 됩니다. 불투명도가 0일 경우 visiblefalse인 경우와 달리 여전히 화면에 나타나 있는 것으로 간주됩니다. 따라서 이벤트 처리의 대상이 됩니다.

다음은 정보 창을 반투명으로 지정하는 예제입니다.

infoWindow.setAlpha(0.5f);

Java

infoWindow.setAlpha(0.5f);

Kotlin

infoWindow.alpha = 0.5f

정보창을 반투명으로 지정한 모습

results matching ""

    No results matching ""