Map context menu for sample in progress

This commit is contained in:
Alexey Kulish 2016-11-16 18:57:43 +03:00
parent 8ff8e0f719
commit 2561aea26e
62 changed files with 5182 additions and 44 deletions

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="100%p" android:toYDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="-100%p" android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="0" android:toYDelta="100%p"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="-100%p"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<nine-patch android:src="@drawable/bg_contextmenu_shadow_top_light" />
</item>
<item>
<shape>
<solid android:color="@color/bg_color_light" />
</shape>
</item>
</layer-list>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<nine-patch android:src="@drawable/bg_contextmenu_shadow_right_light" />
</item>
<item>
<shape>
<solid
android:color="@color/bg_color_light" />
</shape>
</item>
</layer-list>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<nine-patch android:src="@drawable/bg_contextmenu_dots_light" />
</item>
<item>
<shape>
<solid
android:color="@color/bg_color_light" />
</shape>
</item>
</layer-list>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/blue_button_drawable_pressed" android:state_pressed="true"/>
<item android:drawable="@drawable/blue_button_drawable_idle"/>
</selector>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="4dp" />
<solid android:color="@color/map_widget_blue"/>
</shape>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="4dp" />
<solid android:color="@color/map_widget_blue_pressed"/>
</shape>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/list_item_light_pressed" android:state_focused="true"/>
<item android:drawable="@color/list_item_light_pressed" android:state_selected="true"/>
<item android:drawable="@color/list_item_light_pressed" android:state_pressed="true"/>
</selector>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/list_item_light_pressed" android:state_selected="true"/>
<item android:drawable="@color/list_item_light_pressed" android:state_pressed="true"/>
<item android:drawable="@color/list_item_light_pressed" android:state_focused="true"/>
<item android:drawable="@color/list_item_light"/>
</selector>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<bitmap
android:gravity="fill"
android:src="@drawable/map_bt_round_1_shadow" />
</item>
<item>
<inset
android:insetBottom="@dimen/map_button_inset_shadow"
android:insetLeft="@dimen/map_button_inset_shadow"
android:insetRight="@dimen/map_button_inset_shadow"
android:insetTop="@dimen/map_button_inset_shadow" >
<shape android:shape="oval" >
<solid android:color="@color/map_widget_blue" />
</shape>
</inset>
</item>
</layer-list>

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<bitmap
android:gravity="fill"
android:src="@drawable/map_bt_round_1_shadow" />
</item>
<item>
<inset
android:insetBottom="@dimen/map_button_inset_shadow"
android:insetLeft="@dimen/map_button_inset_shadow"
android:insetRight="@dimen/map_button_inset_shadow"
android:insetTop="@dimen/map_button_inset_shadow" >
<shape android:shape="oval" >
<solid android:color="@color/map_widget_blue_pressed" />
</shape>
</inset>
</item>
</layer-list>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/fab_background_pressed" android:state_pressed="true"/>
<item android:drawable="@drawable/fab_background_normal"></item>
</selector>

View file

@ -96,13 +96,10 @@
</FrameLayout> </FrameLayout>
<ListView <FrameLayout
android:id="@android:id/list" android:id="@+id/fragmentContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"/>
android:background="@color/listBackgroundColor"
android:drawSelectorOnTop="true"
android:visibility="gone"/>
</FrameLayout> </FrameLayout>

View file

@ -0,0 +1,257 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="@+id/context_menu_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent">
<LinearLayout
android:id="@+id/context_menu_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/context_menu_top_shadow"
android:layout_width="match_parent"
android:layout_height="@dimen/context_menu_top_shadow_h"
android:orientation="horizontal">
</LinearLayout>
<LinearLayout
android:id="@+id/context_menu_top_shadow_all"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:background="?attr/bg_map_context_menu"
android:orientation="vertical">
<LinearLayout
android:id="@+id/context_menu_top_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/context_menu_first_line_bottom_margin"
android:baselineAligned="false"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/context_menu_icon_layout"
android:layout_width="52dp"
android:layout_height="match_parent">
<ImageView
android:id="@+id/context_menu_icon_view"
android:layout_width="@dimen/map_widget_icon"
android:layout_height="@dimen/map_widget_icon"
android:layout_marginLeft="16dp"
android:layout_marginStart="12dp"
android:layout_marginTop="@dimen/context_menu_icon_top_padding"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/context_menu_first_line_top_margin"
android:layout_weight="1">
<TextView
android:id="@+id/context_menu_line1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/TextAppearance.ContextMenuTitle"/>
</LinearLayout>
<LinearLayout
android:id="@+id/context_menu_close_btn_layout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:minWidth="@dimen/context_menu_top_right_button_min_width"
android:orientation="horizontal">
<Button
android:id="@+id/title_button_top_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:paddingLeft="@dimen/context_menu_button_padding_x"
android:paddingRight="@dimen/context_menu_button_padding_x"
android:textColor="?attr/contextMenuButtonColor"
android:textSize="@dimen/default_desc_text_size"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="@dimen/context_menu_second_line_top_margin"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/context_menu_line2_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:id="@+id/context_menu_line2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
style="@style/TextAppearance.ContextMenuSubtitle"/>
</LinearLayout>
<LinearLayout
android:id="@+id/compass_layout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:minWidth="@dimen/context_menu_top_right_button_min_width"
android:orientation="horizontal">
<ImageView
android:id="@+id/direction"
android:layout_width="@dimen/directionIconSize"
android:layout_height="@dimen/directionIconSize"
android:layout_marginTop="1sp"
android:layout_gravity="center_vertical"/>
<TextView
android:id="@+id/distance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="2dp"
android:layout_marginRight="4dp"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
tools:text="100500 km"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/title_button_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/context_menu_action_buttons_h"
android:layout_marginTop="@dimen/context_menu_buttons_top_margin"
android:clickable="true"
android:orientation="horizontal"
android:paddingBottom="@dimen/context_menu_buttons_padding_bottom"
android:paddingLeft="62dp"
android:paddingRight="2dp"
android:visibility="gone"
tools:visibility="visible">
<Button
android:id="@+id/title_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:gravity="left|center_vertical"
android:paddingLeft="@dimen/context_menu_button_padding_x"
android:paddingRight="@dimen/context_menu_button_padding_x"
android:textColor="?attr/contextMenuButtonColor"
android:textSize="@dimen/default_desc_text_size"/>
<TextView
android:id="@+id/title_button_right_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="-4dp"
android:clickable="true"
android:gravity="center_vertical"
tools:text="— 00:26"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"/>
<Button
android:id="@+id/title_button_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:paddingLeft="@dimen/context_menu_button_padding_x"
android:paddingRight="@dimen/context_menu_button_padding_x"
android:textColor="?attr/contextMenuButtonColor"
android:textSize="@dimen/default_desc_text_size"/>
</LinearLayout>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="@drawable/bg_contextmenu_shadow"
android:foregroundGravity="top|fill_horizontal">
<ScrollView
android:id="@+id/context_menu_bottom_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/ctx_menu_info_view_bg">
<LinearLayout
android:id="@+id/context_menu_bottom_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/ctx_menu_info_view_bg"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
</FrameLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/context_menu_fab_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<ImageView
android:id="@+id/context_menu_fab_view"
android:layout_width="@dimen/fab_size_with_shadow"
android:layout_height="@dimen/fab_size_with_shadow"
android:layout_gravity="right"
android:layout_marginRight="@dimen/fab_margin_right"
android:background="@drawable/fab_background_style"
android:scaleType="center"/>
</FrameLayout>
</FrameLayout>

View file

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="?attr/expandable_list_item_background"
android:minHeight="@dimen/list_item_height"
android:orientation="horizontal"
android:baselineAligned="false">
<LinearLayout
android:id="@+id/context_menu_icon_layout"
android:layout_width="42dp"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/context_menu_icon_view"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size"
android:layout_marginLeft="16dp"
android:layout_marginStart="12dp"
android:layout_marginTop="17dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginTop="14dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/context_menu_line1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:maxLines="3"
android:ellipsize="end"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size_large"/>
<TextView
android:id="@+id/context_menu_line2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginTop="4dp"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"/>
</LinearLayout>
<LinearLayout
android:id="@+id/context_menu_close_btn_layout"
android:layout_width="32dp"
android:layout_height="match_parent"
android:orientation="horizontal"
android:visibility="gone">
<ImageView
android:id="@+id/close_btn_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginTop="12dp"
android:scaleType="center"
android:src="@drawable/ic_action_remove_dark"/>
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/main_view"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="?attr/bottom_menu_view_bg"
android:orientation="vertical">
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@null"
android:dividerHeight="0dp">
</ListView>
</LinearLayout>

View file

@ -1,7 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<declare-styleable name="AppTheme"> <declare-styleable name="AppTheme">
<!-- list colors --> <attr name="bg_map_context_menu" format="reference" />
<attr name="dashboard_button" format="reference" />
<attr name="left_menu_view_bg" format="reference" />
<attr name="bottom_menu_view_bg" format="reference" />
<attr name="dashboard_divider" format="reference" /> <attr name="dashboard_divider" format="reference" />
<attr name="ctx_menu_info_divider" format="color"/> <attr name="ctx_menu_info_divider" format="color"/>
<attr name="searchbar_text" format="color"/> <attr name="searchbar_text" format="color"/>

View file

@ -6,6 +6,10 @@
<item name="android:windowBackground">@color/windowBackgroundColor</item> <item name="android:windowBackground">@color/windowBackgroundColor</item>
<item name="android:colorBackground">@color/windowBackgroundColor</item> <item name="android:colorBackground">@color/windowBackgroundColor</item>
<item name="bg_map_context_menu">@drawable/bg_map_context_menu_light</item>
<item name="dashboard_button">@drawable/dashboard_button_light</item>
<item name="left_menu_view_bg">@drawable/bg_left_menu_light</item>
<item name="bottom_menu_view_bg">@drawable/bg_bottom_menu_light</item>
<item name="toolbar_theme">@style/AppTheme.Toolbar</item> <item name="toolbar_theme">@style/AppTheme.Toolbar</item>
<item name="bg_color">@color/bg_color_light</item> <item name="bg_color">@color/bg_color_light</item>
<item name="ctx_menu_info_divider">@color/ctx_menu_info_divider_light</item> <item name="ctx_menu_info_divider">@color/ctx_menu_info_divider_light</item>
@ -59,4 +63,16 @@
<style name="OsmandListView" parent="@android:style/Widget.ListView"> <style name="OsmandListView" parent="@android:style/Widget.ListView">
</style> </style>
<style name="TextAppearance.ContextMenuTitle" parent="TextAppearance.AppCompat">
<item name="android:textColor">?android:textColorPrimary</item>
<item name="android:textSize">@dimen/default_list_text_size_large</item>
<item name="android:maxLines">6</item>
<item name="android:ellipsize">end</item>
</style>
<style name="TextAppearance.ContextMenuSubtitle" parent="TextAppearance.AppCompat.Subhead">
<item name="android:textColor">?android:textColorSecondary</item>
<item name="android:textSize">@dimen/default_desc_text_size</item>
</style>
</resources> </resources>

View file

@ -0,0 +1,290 @@
package net.osmand.core.samples.android.sample1;
import android.os.AsyncTask;
import android.os.Build;
import net.osmand.Location;
import net.osmand.ResultMatcher;
import net.osmand.binary.GeocodingUtilities.GeocodingResult;
import net.osmand.binary.RouteDataObject;
import net.osmand.data.LatLon;
import net.osmand.util.Algorithms;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
public class GeocodingLookupService {
private SampleApplication app;
private ConcurrentLinkedQueue<LatLon> lookupLocations = new ConcurrentLinkedQueue<>();
private ConcurrentHashMap<LatLon, List<AddressLookupRequest>> addressLookupRequestsMap = new ConcurrentHashMap<>();
private LatLon currentRequestedLocation = null;
private boolean searchDone;
private String lastFoundAddress;
public interface OnAddressLookupProgress {
void geocodingInProgress();
}
public interface OnAddressLookupResult {
void geocodingDone(String address);
}
public static class AddressLookupRequest {
private LatLon latLon;
private OnAddressLookupResult uiResultCallback;
private OnAddressLookupProgress uiProgressCallback;
public AddressLookupRequest(LatLon latLon, OnAddressLookupResult uiResultCallback,
OnAddressLookupProgress uiProgressCallback) {
this.latLon = latLon;
this.uiResultCallback = uiResultCallback;
this.uiProgressCallback = uiProgressCallback;
}
public LatLon getLatLon() {
return latLon;
}
}
public GeocodingLookupService(SampleApplication app) {
this.app = app;
}
public void lookupAddress(AddressLookupRequest request) {
synchronized (this) {
LatLon requestedLocation = request.latLon;
LatLon existingLocation = null;
if (requestedLocation.equals(currentRequestedLocation)) {
existingLocation = currentRequestedLocation;
requestedLocation = existingLocation;
request.latLon = existingLocation;
} else if (lookupLocations.contains(requestedLocation)) {
for (LatLon latLon : lookupLocations) {
if (latLon.equals(requestedLocation)) {
existingLocation = latLon;
requestedLocation = latLon;
request.latLon = latLon;
break;
}
}
}
List<AddressLookupRequest> list = addressLookupRequestsMap.get(requestedLocation);
if (list == null) {
list = new ArrayList<>();
addressLookupRequestsMap.put(requestedLocation, list);
}
list.add(request);
if (existingLocation == null) {
lookupLocations.add(requestedLocation);
}
if (currentRequestedLocation == null && !lookupLocations.isEmpty()) {
currentRequestedLocation = lookupLocations.peek();
execute(new AddressLookupRequestsAsyncTask(app));
}
}
}
public void cancel(AddressLookupRequest request) {
synchronized (this) {
List<AddressLookupRequest> requests = addressLookupRequestsMap.get(request.latLon);
if (requests != null && requests.size() > 0) {
requests.remove(request);
}
}
}
public void cancel(LatLon latLon) {
synchronized (this) {
List<AddressLookupRequest> requests = addressLookupRequestsMap.get(latLon);
if (requests != null && requests.size() > 0) {
requests.clear();
}
}
}
private boolean hasAnyRequest(LatLon latLon) {
synchronized (this) {
List<AddressLookupRequest> requests = addressLookupRequestsMap.get(latLon);
return requests != null && requests.size() > 0;
}
}
@SuppressWarnings("unchecked")
private <P> void execute(AsyncTask<P, ?, ?> task, P... requests) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, requests);
} else {
task.execute(requests);
}
}
private boolean geocode(final LatLon latLon) {
Location loc = new Location("");
loc.setLatitude(latLon.getLatitude());
loc.setLongitude(latLon.getLongitude());
return app.getLocationProvider()
.getGeocodingResult(loc, new ResultMatcher<GeocodingResult>() {
@Override
public boolean publish(GeocodingResult object) {
String result = null;
if (object != null) {
String lang = SampleApplication.LANGUAGE;
boolean transliterate = SampleApplication.TRANSLITERATE;
String geocodingResult = "";
double relevantDistance = -1;
if (object.building != null) {
String bldName = object.building.getName(lang, transliterate);
if (!Algorithms.isEmpty(object.buildingInterpolation)) {
bldName = object.buildingInterpolation;
}
geocodingResult = object.street.getName(lang, transliterate) + " " + bldName + ", "
+ object.city.getName(lang, transliterate);
} else if (object.street != null) {
geocodingResult = object.street.getName(lang, transliterate) + ", " + object.city.getName(lang, transliterate);
relevantDistance = object.getDistanceP();
} else if (object.city != null) {
geocodingResult = object.city.getName(lang, transliterate);
} else if (object.point != null) {
RouteDataObject rd = object.point.getRoad();
String sname = rd.getName(lang, transliterate);
if (Algorithms.isEmpty(sname)) {
sname = "";
}
String ref = rd.getRef(true);
if (!Algorithms.isEmpty(ref)) {
if (!Algorithms.isEmpty(sname)) {
sname += ", ";
}
sname += ref;
}
geocodingResult = sname;
relevantDistance = object.getDistanceP();
}
result = geocodingResult;
if (relevantDistance == -1) {
relevantDistance = object.getDistance();
}
if (!Algorithms.isEmpty(result) && relevantDistance > 100) {
result = app.getString("shared_string_near") + " " + result;
}
}
lastFoundAddress = result;
searchDone = true;
return true;
}
@Override
public boolean isCancelled() {
return !hasAnyRequest(latLon);
}
});
}
private class AddressLookupRequestsAsyncTask extends AsyncTask<AddressLookupRequest, AddressLookupRequest, Void> {
private SampleApplication app;
public AddressLookupRequestsAsyncTask(SampleApplication app) {
super();
this.app = app;
}
@Override
protected Void doInBackground(AddressLookupRequest... addressLookupRequests) {
for (;;) {
try {
while (!lookupLocations.isEmpty()) {
final LatLon latLon;
synchronized (GeocodingLookupService.this) {
latLon = lookupLocations.poll();
currentRequestedLocation = latLon;
List<AddressLookupRequest> requests = addressLookupRequestsMap.get(latLon);
if (requests == null || requests.size() == 0) {
addressLookupRequestsMap.remove(latLon);
continue;
}
}
// geocode
searchDone = false;
while (!geocode(latLon)) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
long counter = 0;
while (!searchDone) {
try {
Thread.sleep(50);
counter++;
// call progress every 500 ms
if (counter == 10) {
counter = 0;
synchronized (GeocodingLookupService.this) {
List<AddressLookupRequest> requests = addressLookupRequestsMap.get(latLon);
for (final AddressLookupRequest request : requests) {
if (request.uiProgressCallback != null) {
app.runInUIThread(new Runnable() {
@Override
public void run() {
request.uiProgressCallback.geocodingInProgress();
}
});
}
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (GeocodingLookupService.this) {
List<AddressLookupRequest> requests = addressLookupRequestsMap.get(latLon);
for (final AddressLookupRequest request : requests) {
if (request.uiResultCallback != null) {
app.runInUIThread(new Runnable() {
@Override
public void run() {
request.uiResultCallback.geocodingDone(lastFoundAddress);
}
});
}
}
addressLookupRequestsMap.remove(latLon);
}
}
} catch (Exception e) {
e.printStackTrace();
}
synchronized (GeocodingLookupService.this) {
currentRequestedLocation = null;
if (lookupLocations.isEmpty()) {
break;
}
}
}
return null;
}
}
}

View file

@ -101,7 +101,7 @@ public class IconsCache {
long hash = ((long)resId << 31L) + clrId; long hash = ((long)resId << 31L) + clrId;
Drawable d = osmandDrawable.get(hash); Drawable d = osmandDrawable.get(hash);
if (d == null) { if (d == null) {
d = OsmandResources.getDrawable(resId); d = OsmandResources.getDrawableNonCached(resId);
if (d != null) { if (d != null) {
d = DrawableCompat.wrap(d); d = DrawableCompat.wrap(d);
d.mutate(); d.mutate();
@ -118,7 +118,7 @@ public class IconsCache {
long hash = ((long)resId << 31L) + color; long hash = ((long)resId << 31L) + color;
Drawable d = osmandDrawable.get(hash); Drawable d = osmandDrawable.get(hash);
if(d == null) { if(d == null) {
d = OsmandResources.getDrawable(resId); d = OsmandResources.getDrawableNonCached(resId);
if (d != null) { if (d != null) {
d = DrawableCompat.wrap(d); d = DrawableCompat.wrap(d);
d.mutate(); d.mutate();
@ -129,6 +129,10 @@ public class IconsCache {
return d; return d;
} }
public Drawable getPaintedOsmandIcon(int resId, @ColorInt int color){
return getPaintedOsmandDrawable(resId, color);
}
public Drawable getPaintedIcon(String osmandId, @ColorInt int color){ public Drawable getPaintedIcon(String osmandId, @ColorInt int color){
int id = OsmandResources.getDrawableId(osmandId); int id = OsmandResources.getDrawableId(osmandId);
if (id != 0) { if (id != 0) {

View file

@ -8,6 +8,8 @@ import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.PointF; import android.graphics.PointF;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
@ -40,8 +42,12 @@ import net.osmand.core.jni.ResolvedMapStyle;
import net.osmand.core.jni.RoadLocator; import net.osmand.core.jni.RoadLocator;
import net.osmand.core.jni.Utilities; import net.osmand.core.jni.Utilities;
import net.osmand.core.samples.android.sample1.MultiTouchSupport.MultiTouchZoomListener; import net.osmand.core.samples.android.sample1.MultiTouchSupport.MultiTouchZoomListener;
import net.osmand.core.samples.android.sample1.data.PointDescription;
import net.osmand.core.samples.android.sample1.mapcontextmenu.MapContextMenu;
import net.osmand.core.samples.android.sample1.mapcontextmenu.MapMultiSelectionMenu;
import net.osmand.core.samples.android.sample1.search.QuickSearchDialogFragment; import net.osmand.core.samples.android.sample1.search.QuickSearchDialogFragment;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.RotatedTileBox;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
import java.io.File; import java.io.File;
@ -77,6 +83,9 @@ public class MainActivity extends AppCompatActivity {
private float elevationAngle; private float elevationAngle;
private MultiTouchSupport multiTouchSupport; private MultiTouchSupport multiTouchSupport;
private MapContextMenu menu;
private MapMultiSelectionMenu multiMenu;
private boolean noMapsFound; private boolean noMapsFound;
// Germany // Germany
@ -224,6 +233,11 @@ public class MainActivity extends AppCompatActivity {
app.getIconsCache().setDisplayDensityFactor(displayDensityFactor); app.getIconsCache().setDisplayDensityFactor(displayDensityFactor);
menu = new MapContextMenu();
menu.setMainActivity(this);
multiMenu = new MapMultiSelectionMenu(this);
if (!InstallOsmandAppDialog.showIfNeeded(getSupportFragmentManager(), this) if (!InstallOsmandAppDialog.showIfNeeded(getSupportFragmentManager(), this)
&& externalStoragePermissionGranted) { && externalStoragePermissionGranted) {
checkMapsInstalled(); checkMapsInstalled();
@ -280,6 +294,10 @@ public class MainActivity extends AppCompatActivity {
return (SampleApplication) getApplication(); return (SampleApplication) getApplication();
} }
public AtlasMapRendererView getMapView() {
return mapView;
}
public void showOnMap(LatLon latLon, int zoom) { public void showOnMap(LatLon latLon, int zoom) {
if (latLon != null) { if (latLon != null) {
PointI target = Utilities.convertLatLonTo31( PointI target = Utilities.convertLatLonTo31(
@ -289,6 +307,38 @@ public class MainActivity extends AppCompatActivity {
} }
} }
public void refreshMap() {
//todo
}
public MapContextMenu getContextMenu() {
return menu;
}
public boolean showContextMenu(@NonNull LatLon latLon,
@Nullable PointDescription pointDescription,
@Nullable Object object) {
if (multiMenu.isVisible()) {
multiMenu.hide();
}
if (!getBox().containsLatLon(latLon)) {
menu.setMapCenter(latLon);
menu.setCenterMarker(true);
}
menu.show(latLon, pointDescription, object);
return true;
}
public RotatedTileBox getBox() {
RotatedTileBox.RotatedTileBoxBuilder boxBuilder = new RotatedTileBox.RotatedTileBoxBuilder();
LatLon screenCenter = getScreenCenter();
boxBuilder.setLocation(screenCenter.getLatitude(), screenCenter.getLongitude());
boxBuilder.setPixelDimensions(mapView.getWidth(), mapView.getHeight(), 0.5f, 0.5f);
boxBuilder.setZoom((int)getZoom());
boxBuilder.setRotate(mapView.getRotation());
return boxBuilder.build();
}
public PointI getScreenCenter31() { public PointI getScreenCenter31() {
PointI point = new PointI(); PointI point = new PointI();
mapView.getLocationFromScreenPoint(new PointI(mapView.getWidth() / 2, mapView.getHeight() / 2), point); mapView.getLocationFromScreenPoint(new PointI(mapView.getWidth() / 2, mapView.getHeight() / 2), point);
@ -302,6 +352,10 @@ public class MainActivity extends AppCompatActivity {
return new LatLon(jniLatLon.getLatitude(), jniLatLon.getLongitude()); return new LatLon(jniLatLon.getLatitude(), jniLatLon.getLongitude());
} }
public float getZoom() {
return zoom;
}
public void saveMapState() { public void saveMapState() {
SharedPreferences prefs = getPreferences(MODE_PRIVATE); SharedPreferences prefs = getPreferences(MODE_PRIVATE);
Editor edit = prefs.edit(); Editor edit = prefs.edit();

View file

@ -4,11 +4,23 @@ import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.support.v4.graphics.drawable.DrawableCompat;
import java.util.HashMap;
import java.util.Map;
import gnu.trove.map.hash.TLongObjectHashMap;
public class OsmandResources { public class OsmandResources {
public static final String BIG_ICON_PREFIX = "mx_";
private static Resources osmandResources; private static Resources osmandResources;
private static String packageName; private static String packageName;
private static Map<String, Integer> stringIds = new HashMap<>();
private static Map<String, Integer> drawableIds = new HashMap<>();
private static TLongObjectHashMap<Drawable> drawable = new TLongObjectHashMap<>();
private static TLongObjectHashMap<String> string = new TLongObjectHashMap<>();
public static void init(Context ctx) { public static void init(Context ctx) {
String packageName = "net.osmand"; String packageName = "net.osmand";
@ -43,40 +55,104 @@ public class OsmandResources {
} }
public static String getString(String id) { public static String getString(String id) {
if (osmandResources != null) { return getStringInternal(resolveStringId(id));
int resolvedId = osmandResources.getIdentifier(id, "string", packageName);
return osmandResources.getString(resolvedId);
}
return null;
} }
public static String getString(String id, Object... formatArgs) { public static String getString(String id, Object... formatArgs) {
if (osmandResources != null) { int resolvedId = resolveStringId(id);
int resolvedId = osmandResources.getIdentifier(id, "string", packageName); if (resolvedId != 0) {
return osmandResources.getString(resolvedId, formatArgs); return osmandResources.getString(resolvedId, formatArgs);
} }
return null; return null;
} }
public static Drawable getDrawable(String id) { public static Drawable getDrawable(String id) {
if (osmandResources != null) { return getDrawableInternal(resolveDrawableId(id));
int resolvedId = osmandResources.getIdentifier(id, "drawable", packageName); }
return osmandResources.getDrawable(resolvedId);
} public static Drawable getBigDrawable(String id) {
return null; return getDrawableInternal(resolveDrawableId(BIG_ICON_PREFIX + id));
} }
public static Drawable getDrawable(int id) { public static Drawable getDrawable(int id) {
if (osmandResources != null) { return getDrawableInternal(id);
return osmandResources.getDrawable(id); }
public static Drawable getDrawableNonCached(int id) {
if (osmandResources != null && id != 0) {
Drawable d = osmandResources.getDrawable(id);
if (d != null) {
d = DrawableCompat.wrap(d);
d.mutate();
}
return d;
} }
return null; return null;
} }
public static int getDrawableId(String id) { public static int getDrawableId(String id) {
return resolveDrawableId(id);
}
public static int getBigDrawableId(String id) {
return resolveDrawableId(BIG_ICON_PREFIX + id);
}
private static Drawable getDrawableInternal(int resId) {
if (osmandResources != null && resId != 0) {
long hash = getResIdHash(resId);
Drawable d = drawable.get(hash);
if (d == null) {
d = osmandResources.getDrawable(resId);
if (d != null) {
d = DrawableCompat.wrap(d);
d.mutate();
drawable.put(hash, d);
}
}
return d;
}
return null;
}
private static String getStringInternal(int resId) {
if (osmandResources != null && resId != 0) {
long hash = getResIdHash(resId);
String s = string.get(hash);
if (s == null) {
s = osmandResources.getString(resId);
string.put(hash, s);
}
return s;
}
return null;
}
private static int resolveStringId(String id) {
if (osmandResources != null) { if (osmandResources != null) {
return osmandResources.getIdentifier(id, "drawable", packageName); Integer resolvedId = stringIds.get(id);
if (resolvedId == null) {
resolvedId = osmandResources.getIdentifier(id, "string", packageName);
stringIds.put(id, resolvedId);
}
return resolvedId;
} }
return 0; return 0;
} }
private static int resolveDrawableId(String id) {
if (osmandResources != null) {
Integer resolvedId = drawableIds.get(id);
if (resolvedId == null) {
resolvedId = osmandResources.getIdentifier(id, "drawable", packageName);
drawableIds.put(id, resolvedId);
}
return resolvedId;
}
return 0;
}
private static long getResIdHash(int resId) {
return ((long)resId << 31L);
}
} }

View file

@ -41,8 +41,10 @@ public class SampleApplication extends Application {
private SampleLocationProvider locationProvider; private SampleLocationProvider locationProvider;
private QuickSearchHelper searchUICore; private QuickSearchHelper searchUICore;
private GeocodingLookupService geocodingLookupService;
public static final String LANGUAGE; public static String LANGUAGE;
public static boolean TRANSLITERATE = false;
static { static {
String langCode = Locale.getDefault().getLanguage(); String langCode = Locale.getDefault().getLanguage();
@ -58,6 +60,7 @@ public class SampleApplication extends Application {
OsmandResources.init(this); OsmandResources.init(this);
locationProvider = new SampleLocationProvider(this); locationProvider = new SampleLocationProvider(this);
searchUICore = new QuickSearchHelper(this); searchUICore = new QuickSearchHelper(this);
geocodingLookupService = new GeocodingLookupService(this);
uiHandler = new Handler(); uiHandler = new Handler();
poiTypes = MapPoiTypes.getDefaultNoInit(); poiTypes = MapPoiTypes.getDefaultNoInit();
@ -76,6 +79,10 @@ public class SampleApplication extends Application {
iconsCache = new IconsCache(assetsCustom, this); iconsCache = new IconsCache(assetsCustom, this);
} }
public GeocodingLookupService getGeocodingLookupService() {
return geocodingLookupService;
}
public int getCoordinatesFormat() { public int getCoordinatesFormat() {
return coordinatesFormat; return coordinatesFormat;
} }

View file

@ -23,6 +23,10 @@ import android.support.v7.app.AlertDialog;
import android.util.Log; import android.util.Log;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.ResultMatcher;
import net.osmand.binary.GeocodingUtilities;
import net.osmand.binary.GeocodingUtilities.GeocodingResult;
import net.osmand.data.LatLon;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
import java.util.ArrayList; import java.util.ArrayList;
@ -513,16 +517,24 @@ public class SampleLocationProvider implements SensorEventListener {
public boolean getRouteSegment(net.osmand.Location loc, ResultMatcher<RouteDataObject> result) { public boolean getRouteSegment(net.osmand.Location loc, ResultMatcher<RouteDataObject> result) {
return currentPositionHelper.getRouteSegment(loc, result); return currentPositionHelper.getRouteSegment(loc, result);
} }
*/
public boolean getGeocodingResult(net.osmand.Location loc, ResultMatcher<GeocodingResult> result) { public boolean getGeocodingResult(net.osmand.Location loc, ResultMatcher<GeocodingResult> result) {
return currentPositionHelper.getGeocodingResult(loc, result); return false; //currentPositionHelper.getGeocodingResult(loc, result); todo
} }
*/
public net.osmand.Location getLastKnownLocation() { public net.osmand.Location getLastKnownLocation() {
return location; return location;
} }
public LatLon getLastKnownLocationLatLon() {
if (location != null) {
return new LatLon(location.getLatitude(), location.getLongitude());
} else {
return null;
}
}
public static class GPSInfo { public static class GPSInfo {
public int foundSatellites = 0; public int foundSatellites = 0;

View file

@ -5,10 +5,13 @@ import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.hardware.Sensor; import android.util.DisplayMetrics;
import android.hardware.SensorManager; import android.util.Log;
import android.view.WindowManager; import android.view.Surface;
import net.osmand.PlatformUtil;
public class SampleUtils { public class SampleUtils {
@ -69,6 +72,7 @@ public class SampleUtils {
return installed; return installed;
} }
/*
public static int getScreenOrientation(Activity a) { public static int getScreenOrientation(Activity a) {
int screenOrientation = ((WindowManager) a.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation(); int screenOrientation = ((WindowManager) a.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
switch (screenOrientation) { switch (screenOrientation) {
@ -92,4 +96,75 @@ public class SampleUtils {
} }
return screenOrientation; return screenOrientation;
} }
*/
public static int getScreenOrientation(Activity activity) {
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = dm.heightPixels;
int orientation;
// if the device's natural orientation is portrait:
if ((rotation == Surface.ROTATION_0
|| rotation == Surface.ROTATION_180) && height > width ||
(rotation == Surface.ROTATION_90
|| rotation == Surface.ROTATION_270) && width > height) {
switch(rotation) {
case Surface.ROTATION_0:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
case Surface.ROTATION_90:
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_180:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
break;
case Surface.ROTATION_270:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
default:
Log.e(PlatformUtil.TAG, "Unknown screen orientation. Defaulting to " +
"portrait.");
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
}
}
// if the device's natural orientation is landscape or if the device
// is square:
else {
switch(rotation) {
case Surface.ROTATION_0:
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_90:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
case Surface.ROTATION_180:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
case Surface.ROTATION_270:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
break;
default:
Log.e(PlatformUtil.TAG, "Unknown screen orientation. Defaulting to " +
"landscape.");
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
}
}
return orientation;
}
public static boolean isOrientationPortrait(Activity ctx) {
int orientation = getScreenOrientation(ctx);
return orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
orientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
}
} }

View file

@ -8,6 +8,7 @@ import com.jwetherell.openmap.common.LatLonPoint;
import com.jwetherell.openmap.common.UTMPoint; import com.jwetherell.openmap.common.UTMPoint;
import net.osmand.LocationConvert; import net.osmand.LocationConvert;
import net.osmand.core.samples.android.sample1.OsmandResources;
import net.osmand.core.samples.android.sample1.SampleApplication; import net.osmand.core.samples.android.sample1.SampleApplication;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
@ -354,4 +355,27 @@ public class PointDescription {
} }
} }
public int getIconId() {
int iconId;
if (isAddress()) {
iconId = OsmandResources.getDrawableId("ic_type_address");
} else if (isFavorite()) {
iconId = OsmandResources.getDrawableId("ic_type_favorites");
} else if (isLocation()) {
iconId = OsmandResources.getDrawableId("ic_type_coordinates");
} else if (isPoi()) {
iconId = OsmandResources.getDrawableId("ic_type_info");
} else if (isWpt()) {
iconId = OsmandResources.getDrawableId("ic_type_waypoint");
} else if (isAudioNote()) {
iconId = OsmandResources.getDrawableId("ic_type_audio");
} else if (isVideoNote()) {
iconId = OsmandResources.getDrawableId("ic_type_video");
}else if (isPhotoNote()) {
iconId = OsmandResources.getDrawableId("ic_type_img");
} else {
iconId = OsmandResources.getDrawableId("ic_type_address");
}
return iconId;
}
} }

View file

@ -0,0 +1,96 @@
package net.osmand.core.samples.android.sample1.mapcontextmenu;
import android.graphics.drawable.Drawable;
import net.osmand.core.samples.android.sample1.IconsCache;
import net.osmand.core.samples.android.sample1.MainActivity;
import net.osmand.core.samples.android.sample1.R;
import net.osmand.core.samples.android.sample1.SampleUtils;
public abstract class BaseMenuController {
private MainActivity mainActivity;
private boolean portraitMode;
private boolean nightMode;
private int landscapeWidthPx;
public BaseMenuController(MainActivity mainActivity) {
this.mainActivity = mainActivity;
init();
}
private void init() {
portraitMode = SampleUtils.isOrientationPortrait(mainActivity);
landscapeWidthPx = mainActivity.getResources().getDimensionPixelSize(R.dimen.dashboard_land_width);
updateNightMode();
}
public MainActivity getMainActivity() {
return mainActivity;
}
public void setMainActivity(MainActivity mainActivity) {
this.mainActivity = mainActivity;
init();
}
public boolean isLight() {
return !nightMode;
}
public void updateNightMode() {
//nightMode = mainActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls();
}
public boolean isLandscapeLayout() {
return !portraitMode;
}
public int getLandscapeWidthPx() {
return landscapeWidthPx;
}
public float getHalfScreenMaxHeightKoef() {
return .7f;
}
public int getSlideInAnimation() {
if (isLandscapeLayout()) {
return R.anim.slide_in_left;
} else {
return R.anim.slide_in_bottom;
}
}
public int getSlideOutAnimation() {
if (isLandscapeLayout()) {
return R.anim.slide_out_left;
} else {
return R.anim.slide_out_bottom;
}
}
protected Drawable getIconOrig(int osmandIconId) {
IconsCache iconsCache = getMainActivity().getMyApplication().getIconsCache();
return iconsCache.getOsmandIcon(osmandIconId, 0);
}
protected Drawable getIcon(int osmandIconId) {
return getIcon(osmandIconId, isLight() ? R.color.icon_color : R.color.icon_color_light);
}
protected Drawable getIcon(int osmandIconId, int colorId) {
IconsCache iconsCache = getMainActivity().getMyApplication().getIconsCache();
return iconsCache.getOsmandIcon(osmandIconId, colorId);
}
protected Drawable getPaintedIcon(int osmandIconId, int color) {
IconsCache iconsCache = getMainActivity().getMyApplication().getIconsCache();
return iconsCache.getPaintedOsmandIcon(osmandIconId, color);
}
protected Drawable getIcon(int osmandIconId, int colorLightId, int colorDarkId) {
IconsCache iconsCache = getMainActivity().getMyApplication().getIconsCache();
return iconsCache.getOsmandIcon(osmandIconId, isLight() ? colorLightId : colorDarkId);
}
}

View file

@ -0,0 +1,242 @@
package net.osmand.core.samples.android.sample1.mapcontextmenu;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.Toolbar;
import android.text.util.Linkify;
import android.view.Gravity;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import net.osmand.AndroidUtils;
import net.osmand.core.samples.android.sample1.OsmandResources;
import net.osmand.core.samples.android.sample1.R;
import net.osmand.core.samples.android.sample1.SampleApplication;
import net.osmand.core.samples.android.sample1.data.PointDescription;
import net.osmand.data.Amenity;
import net.osmand.util.Algorithms;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
public class ContextMenuHelper {
public static void showDescriptionDialog(Context ctx, SampleApplication app, String text, String title) {
showText(ctx, app, text, title);
}
public static void showWikipediaDialog(Context ctx, SampleApplication app, Amenity a) {
if (a.getType().isWiki()) {
showWiki(ctx, app, a, SampleApplication.LANGUAGE);
}
}
private static void showWiki(final Context ctx, final SampleApplication app, final Amenity a, final String lang) {
String preferredLang = lang;
if (Algorithms.isEmpty(preferredLang)) {
preferredLang = SampleApplication.LANGUAGE;
}
final Dialog dialog = new Dialog(ctx);
final String title = Algorithms.isEmpty(lang) ? a.getName() : a.getName(lang);
LinearLayout ll = new LinearLayout(ctx);
ll.setOrientation(LinearLayout.VERTICAL);
final Toolbar topBar = new Toolbar(ctx);
topBar.setClickable(true);
Drawable back = app.getIconsCache().getIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
topBar.setNavigationIcon(back);
topBar.setNavigationContentDescription(app.getString("access_shared_string_navigate_up"));
topBar.setTitle(title);
topBar.setBackgroundColor(ContextCompat.getColor(ctx, R.color.osmand_orange));
topBar.setTitleTextColor(ContextCompat.getColor(ctx, R.color.color_white));
String lng = a.getContentSelected("content", preferredLang, "en");
if (Algorithms.isEmpty(lng)) {
lng = "en";
}
final String langSelected = lng;
String content = a.getDescription(langSelected);
final Button bottomBar = new Button(ctx);
bottomBar.setText(app.getString("read_full_article"));
bottomBar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String article = "https://" + langSelected.toLowerCase() + ".wikipedia.org/wiki/" + title.replace(' ', '_');
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(article));
ctx.startActivity(i);
}
});
MenuItem mi = topBar.getMenu().add(langSelected.toUpperCase()).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(final MenuItem item) {
showPopupLangMenu(ctx, topBar, app, a, dialog, langSelected);
return true;
}
});
MenuItemCompat.setShowAsAction(mi, MenuItem.SHOW_AS_ACTION_ALWAYS);
topBar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
dialog.dismiss();
}
});
final WebView wv = new WebView(ctx);
WebSettings settings = wv.getSettings();
settings.setDefaultTextEncodingName("utf-8");
settings.setBuiltInZoomControls(true);
settings.setDisplayZoomControls(false);
settings.setSupportZoom(true);
wv.loadDataWithBaseURL(null, content, "text/html", "UTF-8", null);
// wv.loadUrl(OsMoService.SIGN_IN_URL + app.getSettings().OSMO_DEVICE_KEY.get());
ScrollView scrollView = new ScrollView(ctx);
ll.addView(topBar);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0);
lp.weight = 1;
ll.addView(scrollView, lp);
ll.addView(bottomBar, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
scrollView.addView(wv);
dialog.setContentView(ll);
wv.setFocusable(true);
wv.setFocusableInTouchMode(true);
wv.requestFocus(View.FOCUS_DOWN);
wv.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_UP:
if (!v.hasFocus()) {
v.requestFocus();
}
break;
}
return false;
}
});
dialog.setCancelable(true);
dialog.show();
}
protected static void showPopupLangMenu(final Context ctx, Toolbar tb,
final SampleApplication app, final Amenity a,
final Dialog dialog, final String langSelected) {
final PopupMenu optionsMenu = new PopupMenu(ctx, tb, Gravity.RIGHT);
Set<String> namesSet = new TreeSet<>();
namesSet.addAll(a.getNames("content", "en"));
namesSet.addAll(a.getNames("description", "en"));
Map<String, String> names = new HashMap<>();
for (String n : namesSet) {
names.put(n, getLangName(ctx, n));
}
String selectedLangName = names.get(langSelected);
if (selectedLangName != null) {
names.remove(langSelected);
}
Map<String, String> sortedNames = AndroidUtils.sortByValue(names);
if (selectedLangName != null) {
MenuItem item = optionsMenu.getMenu().add(selectedLangName);
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
dialog.dismiss();
showWiki(ctx, app, a, langSelected);
return true;
}
});
}
for (final Map.Entry<String, String> e : sortedNames.entrySet()) {
MenuItem item = optionsMenu.getMenu().add(e.getValue());
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
dialog.dismiss();
showWiki(ctx, app, a, e.getKey());
return true;
}
});
}
optionsMenu.show();
}
public static String getLangName(Context ctx, String basename) {
try {
String nm = basename.replace('-', '_').replace(' ', '_');
Field f = R.string.class.getField("lang_"+nm);
if (f != null) {
Integer in = (Integer) f.get(null);
return ctx.getString(in);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
return basename;
}
private static void showText(final Context ctx, final SampleApplication app, final String text, String title) {
final Dialog dialog = new Dialog(ctx);
LinearLayout ll = new LinearLayout(ctx);
ll.setOrientation(LinearLayout.VERTICAL);
final Toolbar topBar = new Toolbar(ctx);
topBar.setClickable(true);
Drawable back = app.getIconsCache().getIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
topBar.setNavigationIcon(back);
topBar.setNavigationContentDescription(app.getString("access_shared_string_navigate_up"));
topBar.setTitle(title);
topBar.setBackgroundColor(ContextCompat.getColor(ctx, R.color.osmand_orange));
topBar.setTitleTextColor(ContextCompat.getColor(ctx, R.color.color_white));
topBar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
dialog.dismiss();
}
});
final TextView textView = new TextView(ctx);
LinearLayout.LayoutParams llTextParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
int textMargin = AndroidUtils.dpToPx(app, 10f);
boolean light = true;
textView.setLayoutParams(llTextParams);
textView.setPadding(textMargin, textMargin, textMargin, textMargin);
textView.setTextSize(16);
textView.setTextColor(ContextCompat.getColor(app, light ? R.color.ctx_menu_info_text_light : R.color.ctx_menu_info_text_dark));
textView.setAutoLinkMask(Linkify.ALL);
textView.setLinksClickable(true);
textView.setText(text);
ScrollView scrollView = new ScrollView(ctx);
ll.addView(topBar);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0);
lp.weight = 1;
ll.addView(scrollView, lp);
scrollView.addView(textView);
dialog.setContentView(ll);
dialog.setCancelable(true);
dialog.show();
}
}

View file

@ -0,0 +1,556 @@
package net.osmand.core.samples.android.sample1.mapcontextmenu;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.View;
import android.widget.LinearLayout;
import net.osmand.core.samples.android.sample1.MainActivity;
import net.osmand.core.samples.android.sample1.data.PointDescription;
import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuController.MenuState;
import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuController.MenuType;
import net.osmand.data.LatLon;
import net.osmand.util.MapUtils;
import java.lang.ref.WeakReference;
public class MapContextMenu extends MenuTitleController {
private MainActivity mainActivity;
private MapMultiSelectionMenu mapMultiSelectionMenu;
private boolean active;
private LatLon latLon;
private PointDescription pointDescription;
private Object object;
private MenuController menuController;
private LatLon mapCenter;
private boolean centerMarker;
private int mapZoom;
private LatLon myLocation;
private Float heading;
private boolean inLocationUpdate = false;
private boolean autoHide;
private MenuAction searchDoneAction;
public MapContextMenu() {
}
@Override
public MainActivity getMainActivity() {
return mainActivity;
}
public void setMainActivity(MainActivity mainActivity) {
this.mainActivity = mainActivity;
if (mapMultiSelectionMenu == null) {
mapMultiSelectionMenu = new MapMultiSelectionMenu(mainActivity);
} else {
mapMultiSelectionMenu.setMainActivity(mainActivity);
}
if (active) {
acquireMenuController(false);
if (menuController != null) {
menuController.addPlainMenuItems(typeStr, this.pointDescription, this.latLon);
}
if (searchDoneAction != null && searchDoneAction.dlg != null && searchDoneAction.dlg.getOwnerActivity() != mainActivity) {
searchDoneAction.dlg = buildSearchActionDialog();
searchDoneAction.dlg.show();
}
} else {
menuController = null;
}
}
public MapMultiSelectionMenu getMultiSelectionMenu() {
return mapMultiSelectionMenu;
}
public boolean isActive() {
return active;
}
public boolean isVisible() {
return findMenuFragment() != null;
}
public void hideMenues() {
if (isVisible()) {
hide();
} else if (mapMultiSelectionMenu.isVisible()) {
mapMultiSelectionMenu.hide();
}
}
@Override
public LatLon getLatLon() {
return latLon;
}
public LatLon getMapCenter() {
return mapCenter;
}
public void setMapCenter(LatLon mapCenter) {
this.mapCenter = mapCenter;
}
public void setCenterMarker(boolean centerMarker) {
this.centerMarker = centerMarker;
}
public int getMapZoom() {
return mapZoom;
}
public void setMapZoom(int mapZoom) {
this.mapZoom = mapZoom;
}
public void updateMapCenter(LatLon mapCenter) {
WeakReference<MapContextMenuFragment> fragmentRef = findMenuFragment();
if (fragmentRef != null) {
fragmentRef.get().updateMapCenter(mapCenter);
}
}
@Override
public PointDescription getPointDescription() {
return pointDescription;
}
@Override
public Object getObject() {
return object;
}
public boolean isExtended() {
return menuController != null;
}
@Override
public MenuController getMenuController() {
return menuController;
}
public boolean init(@NonNull LatLon latLon,
@Nullable PointDescription pointDescription,
@Nullable Object object) {
return init(latLon, pointDescription, object, false, false);
}
public boolean init(@NonNull LatLon latLon,
@Nullable PointDescription pointDescription,
@Nullable Object object,
boolean update, boolean restorePrevious) {
if (myLocation == null) {
myLocation = mainActivity.getMyApplication().getLocationProvider().getLastKnownLocationLatLon();
}
if (!update && isVisible()) {
if (this.object == null || !this.object.equals(object)) {
hide();
} else {
return false;
}
}
if (pointDescription == null) {
this.pointDescription = new PointDescription(latLon.getLatitude(), latLon.getLongitude());
} else {
this.pointDescription = pointDescription;
}
boolean needAcquireMenuController = menuController == null
|| !update
|| this.object == null && object != null
|| this.object != null && object == null
|| (this.object != null && object != null && !this.object.getClass().equals(object.getClass()));
this.latLon = latLon;
this.object = object;
active = true;
if (needAcquireMenuController) {
acquireMenuController(restorePrevious);
} else {
menuController.update(pointDescription, object);
}
initTitle();
if (menuController != null) {
menuController.clearPlainMenuItems();
menuController.addPlainMenuItems(typeStr, this.pointDescription, this.latLon);
}
mainActivity.refreshMap();
return true;
}
public void show() {
if (!isVisible()) {
if (!MapContextMenuFragment.showInstance(this, mainActivity, true)) {
active = false;
}
} else {
WeakReference<MapContextMenuFragment> fragmentRef = findMenuFragment();
if (fragmentRef != null) {
fragmentRef.get().centerMarkerLocation();
}
}
}
public void show(@NonNull LatLon latLon,
@Nullable PointDescription pointDescription,
@Nullable Object object) {
if (init(latLon, pointDescription, object)) {
showInternal();
}
}
private void showInternal() {
if (!MapContextMenuFragment.showInstance(this, mainActivity, centerMarker)) {
active = false;
} else {
if (menuController != null) {
menuController.onShow();
}
}
centerMarker = false;
autoHide = false;
}
public void update(LatLon latLon, PointDescription pointDescription, Object object) {
WeakReference<MapContextMenuFragment> fragmentRef = findMenuFragment();
init(latLon, pointDescription, object, true, false);
if (fragmentRef != null) {
fragmentRef.get().rebuildMenu();
}
}
public void showOrUpdate(LatLon latLon, PointDescription pointDescription, Object object) {
if (isVisible() && this.object != null && this.object.equals(object)) {
update(latLon, pointDescription, object);
} else {
show(latLon, pointDescription, object);
}
}
public void showMinimized(LatLon latLon, PointDescription pointDescription, Object object) {
init(latLon, pointDescription, object);
}
public void close() {
if (active) {
active = false;
if (menuController != null) {
menuController.onClose();
}
hide();
if (menuController != null) {
menuController.setActive(false);
}
mainActivity.refreshMap();
}
}
public void hide() {
if (menuController != null) {
menuController.onHide();
}
WeakReference<MapContextMenuFragment> fragmentRef = findMenuFragment();
if (fragmentRef != null) {
fragmentRef.get().dismissMenu();
}
}
// timeout in msec
public void hideWithTimeout(long timeout) {
autoHide = true;
mainActivity.getMyApplication().runInUIThread(new Runnable() {
@Override
public void run() {
if (autoHide) {
hide();
}
}
}, timeout);
}
public void updateMenuUI() {
WeakReference<MapContextMenuFragment> fragmentRef = findMenuFragment();
if (fragmentRef != null) {
fragmentRef.get().updateMenu();
}
}
private void updateTitle(String address) {
nameStr = address;
pointDescription.setName(address);
WeakReference<MapContextMenuFragment> fragmentRef = findMenuFragment();
if (fragmentRef != null)
fragmentRef.get().refreshTitle();
}
private void acquireMenuController(boolean restorePrevious) {
if (menuController != null) {
menuController.onAcquireNewController(pointDescription, object);
}
menuController = MenuController.getMenuController(mainActivity, latLon, pointDescription, object, MenuType.STANDARD);
menuController.setActive(true);
}
public void onSingleTapOnMap() {
if (menuController == null || !menuController.handleSingleTapOnMap()) {
hide();
}
}
@Override
public void onSearchAddressDone() {
WeakReference<MapContextMenuFragment> fragmentRef = findMenuFragment();
if (fragmentRef != null)
fragmentRef.get().refreshTitle();
if (searchDoneAction != null) {
if (searchDoneAction.dlg != null) {
try {
searchDoneAction.dlg.dismiss();
} catch (Exception e) {
// ignore
} finally {
searchDoneAction.dlg = null;
}
}
searchDoneAction.run();
searchDoneAction = null;
}
}
public WeakReference<MapContextMenuFragment> findMenuFragment() {
Fragment fragment = mainActivity.getSupportFragmentManager().findFragmentByTag(MapContextMenuFragment.TAG);
if (fragment != null && !fragment.isDetached()) {
return new WeakReference<>((MapContextMenuFragment) fragment);
} else {
return null;
}
}
private void callMenuAction(boolean waitForAddressLookup, MenuAction menuAction) {
if (searchingAddress() && waitForAddressLookup) {
menuAction.dlg = buildSearchActionDialog();
menuAction.dlg.show();
searchDoneAction = menuAction;
} else {
menuAction.run();
}
}
private ProgressDialog buildSearchActionDialog() {
ProgressDialog dlg = new ProgressDialog(mainActivity);
dlg.setTitle("");
dlg.setMessage(searchAddressStr);
dlg.setButton(Dialog.BUTTON_NEGATIVE, mainActivity.getMyApplication().getString("shared_string_skip"), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
cancelSearchAddress();
}
});
return dlg;
}
public void setBaseFragmentVisibility(boolean visible) {
WeakReference<MapContextMenuFragment> fragmentRef = findMenuFragment();
if (fragmentRef != null) {
fragmentRef.get().setFragmentVisibility(visible);
}
}
public boolean isLandscapeLayout() {
return menuController != null && menuController.isLandscapeLayout();
}
public int getLandscapeWidthPx() {
if (menuController != null) {
return menuController.getLandscapeWidthPx();
} else {
return 0;
}
}
public void openMenuFullScreen() {
WeakReference<MapContextMenuFragment> fragmentRef = findMenuFragment();
if (fragmentRef != null)
fragmentRef.get().openMenuFullScreen();
}
public boolean slideUp() {
return menuController != null && menuController.slideUp();
}
public boolean slideDown() {
return menuController != null && menuController.slideDown();
}
public void build(View rootView) {
if (menuController != null) {
menuController.build(rootView);
}
}
public int getCurrentMenuState() {
if (menuController != null) {
return menuController.getCurrentMenuState();
} else {
return MenuState.HEADER_ONLY;
}
}
public float getHalfScreenMaxHeightKoef() {
if (menuController != null) {
return menuController.getHalfScreenMaxHeightKoef();
} else {
return 0f;
}
}
public int getSlideInAnimation() {
if (menuController != null) {
return menuController.getSlideInAnimation();
} else {
return 0;
}
}
public int getSlideOutAnimation() {
if (menuController != null) {
return menuController.getSlideOutAnimation();
} else {
return 0;
}
}
public MenuController.TitleButtonController getLeftTitleButtonController() {
if (menuController != null) {
return menuController.getLeftTitleButtonController();
} else {
return null;
}
}
public MenuController.TitleButtonController getRightTitleButtonController() {
if (menuController != null) {
return menuController.getRightTitleButtonController();
} else {
return null;
}
}
public MenuController.TitleButtonController getTopRightTitleButtonController() {
if (menuController != null) {
return menuController.getTopRightTitleButtonController();
} else {
return null;
}
}
public boolean supportZoomIn() {
return menuController == null || menuController.supportZoomIn();
}
public boolean fabVisible() {
return menuController == null || menuController.fabVisible();
}
public boolean buttonsVisible() {
return menuController == null || menuController.buttonsVisible();
}
public boolean displayDistanceDirection() {
return menuController != null && menuController.displayDistanceDirection();
}
public boolean hasCustomAddressLine() {
return menuController != null && menuController.hasCustomAddressLine();
}
public void buildCustomAddressLine(LinearLayout ll) {
if (menuController != null) {
menuController.buildCustomAddressLine(ll);
}
}
public boolean isNightMode() {
if (menuController != null) {
return !menuController.isLight();
} else {
return false;
}
}
public boolean hasHiddenBottomInfo() {
return getCurrentMenuState() == MenuState.HEADER_ONLY;
}
public LatLon getMyLocation() {
return myLocation;
}
public Float getHeading() {
return heading;
}
public void updateMyLocation(net.osmand.Location location) {
if (location != null && active && displayDistanceDirection()) {
myLocation = new LatLon(location.getLatitude(), location.getLongitude());
updateLocation(false, true, false);
}
}
public void updateCompassValue(float value) {
if (active && displayDistanceDirection()) {
// 99 in next line used to one-time initialize arrows (with reference vs. fixed-north direction)
// on non-compass devices
float lastHeading = heading != null ? heading : 99;
heading = value;
if (Math.abs(MapUtils.degreesDiff(lastHeading, heading)) > 5) {
updateLocation(false, false, true);
} else {
heading = lastHeading;
}
}
}
public void updateLocation(final boolean centerChanged, final boolean locationChanged,
final boolean compassChanged) {
if (inLocationUpdate) {
return;
}
inLocationUpdate = true;
mainActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
inLocationUpdate = false;
WeakReference<MapContextMenuFragment> fragmentRef = findMenuFragment();
if (fragmentRef != null) {
fragmentRef.get().updateLocation(centerChanged, locationChanged, compassChanged);
}
}
});
}
private abstract class MenuAction implements Runnable {
protected ProgressDialog dlg;
}
}

View file

@ -0,0 +1,165 @@
package net.osmand.core.samples.android.sample1.mapcontextmenu;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import net.osmand.core.samples.android.sample1.MainActivity;
import net.osmand.core.samples.android.sample1.data.PointDescription;
import net.osmand.data.LatLon;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
public class MapMultiSelectionMenu extends BaseMenuController {
private LatLon latLon;
private LinkedList<MenuObject> objects = new LinkedList<>();
public static class MenuObject extends MenuTitleController {
private LatLon latLon;
private PointDescription pointDescription;
private Object object;
private int order;
private MainActivity mainActivity;
private MenuController controller;
public MenuObject(LatLon latLon, PointDescription pointDescription, Object object, MainActivity mainActivity) {
this.latLon = latLon;
this.pointDescription = pointDescription;
this.object = object;
this.mainActivity = mainActivity;
init();
}
protected void init() {
controller = MenuController.getMenuController(mainActivity, latLon, pointDescription, object, MenuController.MenuType.MULTI_LINE);
controller.setActive(true);
initTitle();
}
@Override
public LatLon getLatLon() {
return latLon;
}
@Override
public PointDescription getPointDescription() {
return pointDescription;
}
@Override
public Object getObject() {
return object;
}
@Override
public MainActivity getMainActivity() {
return mainActivity;
}
@Override
public MenuController getMenuController() {
return controller;
}
@Override
protected boolean needStreetName() {
return false;
}
}
public MapMultiSelectionMenu(MainActivity mainActivity) {
super(mainActivity);
}
public void setMainActivity(MainActivity mainActivity) {
super.setMainActivity(mainActivity);
for (MenuObject o : objects) {
o.mainActivity = mainActivity;
o.init();
}
}
public List<MenuObject> getObjects() {
return objects;
}
@Override
public float getHalfScreenMaxHeightKoef() {
return 0.5f;
}
private void createCollection(List<Object> selectedObjects) {
objects.clear();
for (Object selectedObj : selectedObjects) {
LatLon ll = MenuController.getObjectLocation(selectedObj);
PointDescription pointDescription = MenuController.getObjectName(selectedObj);
if (ll == null) {
ll = latLon;
}
if (pointDescription == null) {
pointDescription = new PointDescription(latLon.getLatitude(), latLon.getLongitude());
}
MenuObject menuObject = new MenuObject(ll, pointDescription, selectedObj, getMainActivity());
menuObject.order = MenuController.getObjectPriority(selectedObj);
objects.add(menuObject);
}
Collections.sort(objects, new Comparator<MenuObject>() {
@Override
public int compare(MenuObject obj1, MenuObject obj2) {
if (obj1.order == obj2.order) {
return obj1.getTitleStr().compareToIgnoreCase(obj2.getTitleStr());
} else {
return obj1.order - obj2.order;
}
}
});
}
private void clearMenu() {
objects.clear();
getMainActivity().refreshMap();
}
public void show(LatLon latLon, List<Object> selectedObjects) {
if (isVisible()) {
hide();
}
this.latLon = latLon;
createCollection(selectedObjects);
updateNightMode();
MapMultiSelectionMenuFragment.showInstance(getMainActivity());
getMainActivity().refreshMap();
}
public boolean isVisible() {
Fragment fragment = getMainActivity().getSupportFragmentManager().findFragmentByTag(MapMultiSelectionMenuFragment.TAG);
return fragment != null;
}
public void hide() {
clearMenu();
Fragment fragment = getMainActivity().getSupportFragmentManager().findFragmentByTag(MapMultiSelectionMenuFragment.TAG);
if (fragment != null) {
MapMultiSelectionMenuFragment menuFragment = (MapMultiSelectionMenuFragment) fragment;
menuFragment.dismissMenu();
}
}
public void onStop() {
}
public void openContextMenu(@NonNull MenuObject menuObject) {
hide();
getMainActivity().showContextMenu(
menuObject.getLatLon(), menuObject.getPointDescription(), menuObject.getObject());
}
}

View file

@ -0,0 +1,207 @@
package net.osmand.core.samples.android.sample1.mapcontextmenu;
import android.annotation.SuppressLint;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import net.osmand.AndroidUtils;
import net.osmand.core.samples.android.sample1.IconsCache;
import net.osmand.core.samples.android.sample1.MainActivity;
import net.osmand.core.samples.android.sample1.R;
import net.osmand.core.samples.android.sample1.mapcontextmenu.MapMultiSelectionMenu.MenuObject;
import java.util.LinkedList;
import java.util.List;
import static android.util.TypedValue.COMPLEX_UNIT_DIP;
public class MapMultiSelectionMenuFragment extends Fragment implements AdapterView.OnItemClickListener {
public static final String TAG = "MapMultiSelectionMenuFragment";
private View view;
private ArrayAdapter<MenuObject> listAdapter;
private MapMultiSelectionMenu menu;
private boolean dismissing = false;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
menu = ((MainActivity) getActivity()).getContextMenu().getMultiSelectionMenu();
view = inflater.inflate(R.layout.menu_obj_selection_fragment, container, false);
if (menu.isLandscapeLayout()) {
AndroidUtils.setBackground(view.getContext(), view, !menu.isLight(),
R.drawable.bg_left_menu_light, 0);
} else {
AndroidUtils.setBackground(view.getContext(), view, !menu.isLight(),
R.drawable.bg_bottom_menu_light, 0);
}
ListView listView = (ListView) view.findViewById(R.id.list);
listAdapter = createAdapter();
listView.setAdapter(listAdapter);
listView.setOnItemClickListener(this);
if (!oldAndroid()) {
runLayoutListener();
}
return view;
}
@Override
public void onStart() {
super.onStart();
menu.getMainActivity().getContextMenu().setBaseFragmentVisibility(false);
}
@Override
public void onStop() {
super.onStop();
if (!dismissing) {
menu.onStop();
}
menu.getMainActivity().getContextMenu().setBaseFragmentVisibility(true);
}
public static void showInstance(final MainActivity mainActivity) {
MapMultiSelectionMenu menu = mainActivity.getContextMenu().getMultiSelectionMenu();
int slideInAnim = menu.getSlideInAnimation();
int slideOutAnim = menu.getSlideOutAnimation();
MapMultiSelectionMenuFragment fragment = new MapMultiSelectionMenuFragment();
menu.getMainActivity().getSupportFragmentManager().beginTransaction()
.setCustomAnimations(slideInAnim, slideOutAnim, slideInAnim, slideOutAnim)
.add(R.id.fragmentContainer, fragment, TAG)
.addToBackStack(TAG).commitAllowingStateLoss();
}
private void runLayoutListener() {
ViewTreeObserver vto = view.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int maxHeight = (int) (getScreenHeight() * menu.getHalfScreenMaxHeightKoef());
int height = view.findViewById(R.id.main_view).getHeight();
ViewTreeObserver obs = view.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
obs.removeOnGlobalLayoutListener(this);
} else {
obs.removeGlobalOnLayoutListener(this);
}
if (!menu.isLandscapeLayout() && height > maxHeight) {
ViewGroup.LayoutParams lp = view.getLayoutParams();
lp.height = maxHeight;
view.setLayoutParams(lp);
view.requestLayout();
}
}
});
}
private ArrayAdapter<MenuObject> createAdapter() {
final List<MenuObject> items = new LinkedList<>(menu.getObjects());
return new ArrayAdapter<MenuObject>(menu.getMainActivity(), R.layout.menu_obj_list_item, items) {
@SuppressLint("InflateParams")
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
v = menu.getMainActivity().getLayoutInflater().inflate(R.layout.menu_obj_list_item, null);
}
final MenuObject item = getItem(position);
buildHeader(v, item, menu.getMainActivity());
return v;
}
};
}
private void buildHeader(View view, MenuObject item, MainActivity mainActivity) {
AndroidUtils.setBackground(mainActivity, view, !menu.isLight(), R.drawable.expandable_list_item_background_light, 0);
IconsCache iconsCache = mainActivity.getMyApplication().getIconsCache();
final View iconLayout = view.findViewById(R.id.context_menu_icon_layout);
final ImageView iconView = (ImageView) view.findViewById(R.id.context_menu_icon_view);
Drawable icon = item.getLeftIcon();
int iconId = item.getLeftIconId();
if (icon != null) {
iconView.setImageDrawable(icon);
iconLayout.setVisibility(View.VISIBLE);
} else if (iconId != 0) {
iconView.setImageDrawable(iconsCache.getOsmandIcon(iconId,
menu.isLight() ? R.color.osmand_orange : R.color.osmand_orange_dark));
iconLayout.setVisibility(View.VISIBLE);
} else {
iconLayout.setVisibility(View.GONE);
}
// Text line 1
TextView line1 = (TextView) view.findViewById(R.id.context_menu_line1);
AndroidUtils.setTextPrimaryColor(mainActivity, line1, !menu.isLight());
line1.setText(item.getTitleStr());
// Text line 2
TextView line2 = (TextView) view.findViewById(R.id.context_menu_line2);
AndroidUtils.setTextSecondaryColor(mainActivity, line2, !menu.isLight());
line2.setText(item.getTypeStr());
Drawable slIcon = item.getTypeIcon();
line2.setCompoundDrawablesWithIntrinsicBounds(slIcon, null, null, null);
line2.setCompoundDrawablePadding(dpToPx(5f));
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
menu.openContextMenu(listAdapter.getItem(position));
}
public void dismissMenu() {
dismissing = true;
if (menu.getMainActivity().getContextMenu().isVisible()) {
menu.getMainActivity().getContextMenu().hide();
} else {
menu.getMainActivity().getSupportFragmentManager().popBackStack();
}
}
private int dpToPx(float dp) {
Resources r = getActivity().getResources();
return (int) TypedValue.applyDimension(
COMPLEX_UNIT_DIP,
dp,
r.getDisplayMetrics()
);
}
private int getScreenHeight() {
DisplayMetrics dm = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
return dm.heightPixels;
}
private boolean oldAndroid() {
return (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH);
}
}

View file

@ -0,0 +1,322 @@
package net.osmand.core.samples.android.sample1.mapcontextmenu;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.ClipboardManager;
import android.text.util.Linkify;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import net.osmand.core.samples.android.sample1.IconsCache;
import net.osmand.core.samples.android.sample1.MainActivity;
import net.osmand.core.samples.android.sample1.OsmandResources;
import net.osmand.core.samples.android.sample1.R;
import net.osmand.core.samples.android.sample1.SampleApplication;
import java.util.LinkedList;
import static android.util.TypedValue.COMPLEX_UNIT_DIP;
public class MenuBuilder {
public static final float SHADOW_HEIGHT_TOP_DP = 17f;
protected MainActivity mainActivity;
protected SampleApplication app;
protected LinkedList<PlainMenuItem> plainMenuItems;
private boolean firstRow;
protected boolean light;
public class PlainMenuItem {
private int iconId;
private String text;
private boolean needLinks;
private boolean url;
private OnClickListener onClickListener;
public PlainMenuItem(int iconId, String text, boolean needLinks, boolean url, OnClickListener onClickListener) {
this.iconId = iconId;
this.text = text;
this.needLinks = needLinks;
this.url = url;
this.onClickListener = onClickListener;
}
public int getIconId() {
return iconId;
}
public String getText() {
return text;
}
public boolean isNeedLinks() {
return needLinks;
}
public boolean isUrl() {
return url;
}
public OnClickListener getOnClickListener() {
return onClickListener;
}
}
public MenuBuilder(MainActivity mainActivity) {
this.mainActivity = mainActivity;
this.app = mainActivity.getMyApplication();
plainMenuItems = new LinkedList<>();
}
public void setLight(boolean light) {
this.light = light;
}
public void build(View view) {
firstRow = true;
if (needBuildPlainMenuItems()) {
buildPlainMenuItems(view);
}
buildInternal(view);
buildAfter(view);
}
protected void buildPlainMenuItems(View view) {
for (PlainMenuItem item : plainMenuItems) {
buildRow(view, item.getIconId(), item.getText(), 0, item.isNeedLinks(), 0, item.isUrl(), item.getOnClickListener());
}
}
protected boolean needBuildPlainMenuItems() {
return true;
}
protected void buildInternal(View view) {
}
protected void buildAfter(View view) {
buildRowDivider(view, false);
}
protected boolean isFirstRow() {
return firstRow;
}
public void rowBuilt() {
firstRow = false;
}
protected View buildRow(View view, int iconId, String text, int textColor, boolean needLinks, int textLinesLimit, boolean isUrl, OnClickListener onClickListener) {
return buildRow(view, getRowIcon(iconId), text, textColor, needLinks, textLinesLimit, isUrl, onClickListener);
}
protected View buildRow(final View view, Drawable icon, final String text, int textColor, boolean needLinks, int textLinesLimit, boolean isUrl, OnClickListener onClickListener) {
if (!isFirstRow()) {
buildRowDivider(view, false);
}
LinearLayout ll = new LinearLayout(view.getContext());
ll.setOrientation(LinearLayout.HORIZONTAL);
LinearLayout.LayoutParams llParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ll.setLayoutParams(llParams);
ll.setBackgroundResource(resolveAttribute(view.getContext(), android.R.attr.selectableItemBackground));
ll.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
copyToClipboard(text, view.getContext());
return true;
}
});
// Icon
LinearLayout llIcon = new LinearLayout(view.getContext());
llIcon.setOrientation(LinearLayout.HORIZONTAL);
llIcon.setLayoutParams(new LinearLayout.LayoutParams(dpToPx(72f), dpToPx(48f)));
llIcon.setGravity(Gravity.CENTER_VERTICAL);
ll.addView(llIcon);
ImageView iconView = new ImageView(view.getContext());
LinearLayout.LayoutParams llIconParams = new LinearLayout.LayoutParams(dpToPx(24f), dpToPx(24f));
llIconParams.setMargins(dpToPx(16f), dpToPx(12f), dpToPx(32f), dpToPx(12f));
llIconParams.gravity = Gravity.CENTER_VERTICAL;
iconView.setLayoutParams(llIconParams);
iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
iconView.setImageDrawable(icon);
llIcon.addView(iconView);
// Text
LinearLayout llText = new LinearLayout(view.getContext());
llText.setOrientation(LinearLayout.VERTICAL);
ll.addView(llText);
TextView textView = new TextView(view.getContext());
LinearLayout.LayoutParams llTextParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
llTextParams.setMargins(0, dpToPx(8f), 0, dpToPx(8f));
textView.setLayoutParams(llTextParams);
textView.setTextSize(16);
textView.setTextColor(app.getResources().getColor(light ? R.color.ctx_menu_info_text_light : R.color.ctx_menu_info_text_dark));
if (isUrl) {
textView.setTextColor(textView.getLinkTextColors());
} else if (needLinks) {
textView.setAutoLinkMask(Linkify.ALL);
textView.setLinksClickable(true);
}
if (textLinesLimit > 0) {
textView.setMinLines(1);
textView.setMaxLines(textLinesLimit);
}
textView.setText(text);
if (textColor > 0) {
textView.setTextColor(view.getResources().getColor(textColor));
}
LinearLayout.LayoutParams llTextViewParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
llTextViewParams.setMargins(0, 0, dpToPx(10f), 0);
llTextViewParams.gravity = Gravity.CENTER_VERTICAL;
llText.setLayoutParams(llTextViewParams);
llText.addView(textView);
if (onClickListener != null) {
ll.setOnClickListener(onClickListener);
} else if (isUrl) {
ll.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(text));
v.getContext().startActivity(intent);
}
});
}
((LinearLayout) view).addView(ll);
rowBuilt();
return ll;
}
protected void copyToClipboard(String text, Context ctx) {
((ClipboardManager) app.getSystemService(Activity.CLIPBOARD_SERVICE)).setText(text);
Toast.makeText(ctx,
app.getString("copied_to_clipboard") + ":\n" + text,
Toast.LENGTH_SHORT).show();
}
protected void buildButtonRow(final View view, Drawable buttonIcon, String text, OnClickListener onClickListener) {
LinearLayout ll = new LinearLayout(view.getContext());
ll.setOrientation(LinearLayout.HORIZONTAL);
LinearLayout.LayoutParams llParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ll.setLayoutParams(llParams);
ll.setBackgroundResource(resolveAttribute(view.getContext(), android.R.attr.selectableItemBackground));
// Empty
LinearLayout llIcon = new LinearLayout(view.getContext());
llIcon.setOrientation(LinearLayout.HORIZONTAL);
llIcon.setLayoutParams(new LinearLayout.LayoutParams(dpToPx(62f), dpToPx(58f)));
llIcon.setGravity(Gravity.CENTER_VERTICAL);
ll.addView(llIcon);
// Button
LinearLayout llButton = new LinearLayout(view.getContext());
llButton.setOrientation(LinearLayout.VERTICAL);
ll.addView(llButton);
Button buttonView = new Button(view.getContext());
LinearLayout.LayoutParams llBtnParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
buttonView.setLayoutParams(llBtnParams);
buttonView.setPadding(dpToPx(10f), 0, dpToPx(10f), 0);
buttonView.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
//buttonView.setTextSize(view.getResources().getDimension(resolveAttribute(view.getContext(), R.dimen.default_desc_text_size)));
buttonView.setTextColor(view.getResources().getColor(resolveAttribute(view.getContext(), R.attr.contextMenuButtonColor)));
buttonView.setText(text);
if (buttonIcon != null) {
buttonView.setCompoundDrawablesWithIntrinsicBounds(buttonIcon, null, null, null);
buttonView.setCompoundDrawablePadding(dpToPx(8f));
}
llButton.addView(buttonView);
((LinearLayout) view).addView(ll);
ll.setOnClickListener(onClickListener);
rowBuilt();
}
protected void buildRowDivider(View view, boolean matchWidth) {
View horizontalLine = new View(view.getContext());
LinearLayout.LayoutParams llHorLineParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPx(1f));
llHorLineParams.gravity = Gravity.BOTTOM;
if (!matchWidth) {
llHorLineParams.setMargins(dpToPx(72f), 0, 0, 0);
}
horizontalLine.setLayoutParams(llHorLineParams);
horizontalLine.setBackgroundColor(app.getResources().getColor(light ? R.color.ctx_menu_info_divider_light : R.color.ctx_menu_info_divider_dark));
((LinearLayout) view).addView(horizontalLine);
}
public boolean hasCustomAddressLine() {
return false;
}
public void buildCustomAddressLine(LinearLayout ll) {
}
public void addPlainMenuItem(int iconId, String text, boolean needLinks, boolean isUrl, OnClickListener onClickListener) {
plainMenuItems.add(new PlainMenuItem(iconId, text, needLinks, isUrl, onClickListener));
}
public void clearPlainMenuItems() {
plainMenuItems.clear();
}
public Drawable getRowIcon(int iconId) {
IconsCache iconsCache = app.getIconsCache();
return iconsCache.getOsmandIcon(iconId,
light ? R.color.icon_color : R.color.icon_color_light);
}
public Drawable getRowIcon(Context ctx, String fileName) {
Drawable d = OsmandResources.getBigDrawable(fileName);
if (d != null) {
d.setColorFilter(app.getResources()
.getColor(light ? R.color.icon_color : R.color.icon_color_light), PorterDuff.Mode.SRC_IN);
return d;
} else {
return null;
}
}
public int resolveAttribute(Context ctx, int attribute) {
TypedValue outValue = new TypedValue();
ctx.getTheme().resolveAttribute(attribute, outValue, true);
return outValue.resourceId;
}
public int dpToPx(float dp) {
Resources r = app.getResources();
return (int) TypedValue.applyDimension(
COMPLEX_UNIT_DIP,
dp,
r.getDisplayMetrics()
);
}
}

View file

@ -0,0 +1,355 @@
package net.osmand.core.samples.android.sample1.mapcontextmenu;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import net.osmand.core.samples.android.sample1.MainActivity;
import net.osmand.core.samples.android.sample1.OsmandResources;
import net.osmand.core.samples.android.sample1.R;
import net.osmand.core.samples.android.sample1.SampleApplication;
import net.osmand.core.samples.android.sample1.SampleUtils;
import net.osmand.core.samples.android.sample1.data.PointDescription;
import net.osmand.core.samples.android.sample1.mapcontextmenu.controllers.AmenityMenuController;
import net.osmand.core.samples.android.sample1.mapcontextmenu.controllers.MyLocationMenuController;
import net.osmand.core.samples.android.sample1.mapcontextmenu.controllers.PointDescriptionMenuController;
import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
public abstract class MenuController extends BaseMenuController {
public static class MenuState {
public static final int HEADER_ONLY = 1;
public static final int HALF_SCREEN = 2;
public static final int FULL_SCREEN = 4;
}
public enum MenuType {
STANDARD,
MULTI_LINE
}
protected MenuBuilder builder;
private int currentMenuState;
private MenuType menuType = MenuType.STANDARD;
private PointDescription pointDescription;
private LatLon latLon;
private boolean active;
protected TitleButtonController leftTitleButtonController;
protected TitleButtonController rightTitleButtonController;
protected TitleButtonController topRightTitleButtonController;
//protected TopToolbarController toolbarController;
public MenuController(MenuBuilder builder, PointDescription pointDescription, MainActivity mainActivity) {
super(mainActivity);
this.pointDescription = pointDescription;
this.builder = builder;
this.currentMenuState = getInitialMenuState();
this.builder.setLight(isLight());
}
public void build(View rootView) {
builder.build(rootView);
}
public static MenuController getMenuController(MainActivity mainActivity,
LatLon latLon, PointDescription pointDescription, Object object,
MenuType menuType) {
SampleApplication app = mainActivity.getMyApplication();
MenuController menuController = null;
if (object != null) {
if (object instanceof Amenity) {
menuController = new AmenityMenuController(mainActivity, pointDescription, (Amenity) object);
} else if (object instanceof LatLon) {
if (pointDescription.isMyLocation()) {
menuController = new MyLocationMenuController(mainActivity, pointDescription);
}
}
}
if (menuController == null) {
menuController = new PointDescriptionMenuController(mainActivity, pointDescription);
}
menuController.menuType = menuType;
menuController.setLatLon(latLon);
return menuController;
}
public void update(PointDescription pointDescription, Object object) {
setPointDescription(pointDescription);
setObject(object);
}
protected void setPointDescription(PointDescription pointDescription) {
this.pointDescription = pointDescription;
}
protected abstract void setObject(Object object);
protected abstract Object getObject();
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public void addPlainMenuItem(int iconId, String text, boolean needLinks, boolean isUrl, OnClickListener onClickListener) {
builder.addPlainMenuItem(iconId, text, needLinks, isUrl, onClickListener);
}
public void clearPlainMenuItems() {
builder.clearPlainMenuItems();
}
public void addPlainMenuItems(String typeStr, PointDescription pointDescription, LatLon latLon) {
addMyLocationToPlainItems(latLon);
}
protected void addMyLocationToPlainItems(LatLon latLon) {
addPlainMenuItem(OsmandResources.getDrawableId("ic_action_get_my_location"), PointDescription.getLocationName(getMainActivity().getMyApplication(),
latLon.getLatitude(), latLon.getLongitude(), true).replaceAll("\n", " "), false, false, null);
}
public PointDescription getPointDescription() {
return pointDescription;
}
public int getInitialMenuState() {
if (isLandscapeLayout()) {
return MenuState.FULL_SCREEN;
} else {
return getInitialMenuStatePortrait();
}
}
public int getSupportedMenuStates() {
if (isLandscapeLayout()) {
return MenuState.FULL_SCREEN;
} else {
return getSupportedMenuStatesPortrait();
}
}
protected int getInitialMenuStatePortrait() {
return MenuState.HEADER_ONLY;
}
protected int getSupportedMenuStatesPortrait() {
return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN | MenuState.FULL_SCREEN;
}
public int getCurrentMenuState() {
return currentMenuState;
}
public MenuType getMenuType() {
return menuType;
}
public boolean slideUp() {
int v = currentMenuState;
for (int i = 0; i < 2; i++) {
v = v << 1;
if ((v & getSupportedMenuStates()) != 0) {
currentMenuState = v;
return true;
}
}
return false;
}
public boolean slideDown() {
int v = currentMenuState;
for (int i = 0; i < 2; i++) {
v = v >> 1;
if ((v & getSupportedMenuStates()) != 0) {
currentMenuState = v;
return true;
}
}
return false;
}
public void setCurrentMenuState(int currentMenuState) {
this.currentMenuState = currentMenuState;
}
public TitleButtonController getLeftTitleButtonController() {
return leftTitleButtonController;
}
public TitleButtonController getRightTitleButtonController() {
return rightTitleButtonController;
}
public TitleButtonController getTopRightTitleButtonController() {
return topRightTitleButtonController;
}
/*
public TopToolbarController getToolbarController() {
return toolbarController;
}
public boolean hasBackAction() {
return toolbarController != null;
}
*/
public LatLon getLatLon() {
return latLon;
}
public boolean supportZoomIn() {
return true;
}
public boolean fabVisible() {
return true;
}
public boolean buttonsVisible() {
return true;
}
public boolean handleSingleTapOnMap() {
return false;
}
public boolean needStreetName() {
return !displayDistanceDirection();
}
public boolean needTypeStr() {
return true;
}
public boolean displayStreetNameInTitle() {
return false;
}
public boolean displayDistanceDirection() {
return false;
}
public int getLeftIconId() {
return 0;
}
public Drawable getLeftIcon() {
return null;
}
public Drawable getSecondLineTypeIcon() {
return null;
}
public String getTypeStr() {
return "";
}
public String getCommonTypeStr() {
return "";
}
public String getNameStr() {
return pointDescription.getName();
}
public boolean hasCustomAddressLine() {
return builder.hasCustomAddressLine();
}
public void buildCustomAddressLine(LinearLayout ll) {
builder.buildCustomAddressLine(ll);
}
public abstract class TitleButtonController {
public String caption = "";
public int leftIconId = 0;
public boolean needRightText = false;
public String rightTextCaption = "";
public boolean visible = true;
public Drawable getLeftIcon() {
if (leftIconId != 0) {
return getIcon(leftIconId, isLight() ? R.color.map_widget_blue : R.color.osmand_orange);
} else {
return null;
}
}
public abstract void buttonPressed();
}
public void onShow() {
/*
if (toolbarController != null) {
getMainActivity().showTopToolbar(toolbarController);
}
*/
}
public void onHide() {
}
public void onClose() {
/*
if (toolbarController != null) {
getMainActivity().hideTopToolbar(toolbarController);
}
*/
}
public void onAcquireNewController(PointDescription pointDescription, Object object) {
}
public void setLatLon(@NonNull LatLon latLon) {
this.latLon = latLon;
}
/*
public static class ContextMenuToolbarController extends TopToolbarController {
private MenuController menuController;
public ContextMenuToolbarController(MenuController menuController) {
super(TopToolbarControllerType.CONTEXT_MENU);
this.menuController = menuController;
}
public MenuController getMenuController() {
return menuController;
}
}
*/
public static int getObjectPriority(Object o) {
if (o instanceof Amenity) {
return 100;
}
return 1000;
}
public static LatLon getObjectLocation(Object o) {
if (o instanceof Amenity) {
return ((Amenity) o).getLocation();
}
return null;
}
public static PointDescription getObjectName(Object o) {
if (o instanceof Amenity) {
return new PointDescription(PointDescription.POINT_TYPE_POI, ((Amenity) o).getName(
SampleApplication.LANGUAGE, SampleApplication.TRANSLITERATE));
}
return null;
}
}

View file

@ -0,0 +1,192 @@
package net.osmand.core.samples.android.sample1.mapcontextmenu;
import android.graphics.drawable.Drawable;
import net.osmand.core.samples.android.sample1.GeocodingLookupService;
import net.osmand.core.samples.android.sample1.GeocodingLookupService.AddressLookupRequest;
import net.osmand.core.samples.android.sample1.MainActivity;
import net.osmand.core.samples.android.sample1.data.PointDescription;
import net.osmand.data.LatLon;
import net.osmand.util.Algorithms;
public abstract class MenuTitleController {
protected int leftIconId;
protected Drawable leftIcon;
protected String nameStr = "";
protected String typeStr = "";
protected String commonTypeStr = "";
protected Drawable secondLineTypeIcon;
protected String streetStr = "";
private AddressLookupRequest addressLookupRequest;
protected String searchAddressStr;
protected String addressNotFoundStr;
public abstract MainActivity getMainActivity();
public abstract LatLon getLatLon();
public abstract PointDescription getPointDescription();
public abstract Object getObject();
public abstract MenuController getMenuController();
public String getTitleStr() {
if (displayStreetNameInTitle() && searchingAddress()) {
return searchAddressStr;
} else {
return nameStr;
}
}
public boolean searchingAddress() {
return addressLookupRequest != null;
}
public void cancelSearchAddress() {
if (addressLookupRequest != null) {
getMainActivity().getMyApplication().getGeocodingLookupService().cancel(addressLookupRequest);
addressLookupRequest = null;
onSearchAddressDone();
}
}
public boolean displayStreetNameInTitle() {
MenuController menuController = getMenuController();
return menuController != null && menuController.displayStreetNameInTitle();
}
// Has title which does not equal to "Looking up address" and "No address determined"
public boolean hasValidTitle() {
String title = getTitleStr();
return !addressNotFoundStr.equals(title) && !searchAddressStr.equals(title);
}
public int getLeftIconId() {
return leftIconId;
}
public Drawable getLeftIcon() {
return leftIcon;
}
public Drawable getTypeIcon() {
return secondLineTypeIcon;
}
public String getTypeStr() {
MenuController menuController = getMenuController();
if (menuController != null && menuController.needTypeStr()) {
return typeStr;
} else {
return "";
}
}
public String getStreetStr() {
if (needStreetName()) {
if (searchingAddress()) {
return searchAddressStr;
} else {
return streetStr;
}
} else {
return "";
}
}
protected void initTitle() {
searchAddressStr = PointDescription.getSearchAddressStr(getMainActivity().getMyApplication());
addressNotFoundStr = PointDescription.getAddressNotFoundStr(getMainActivity().getMyApplication());
if (searchingAddress()) {
cancelSearchAddress();
}
acquireIcons();
acquireNameAndType();
if (needStreetName()) {
acquireStreetName();
}
}
protected boolean needStreetName() {
MenuController menuController = getMenuController();
boolean res = getObject() != null || Algorithms.isEmpty(getPointDescription().getName());
if (res && menuController != null) {
res = menuController.needStreetName();
}
return res;
}
protected void acquireIcons() {
MenuController menuController = getMenuController();
leftIconId = 0;
leftIcon = null;
secondLineTypeIcon = null;
if (menuController != null) {
leftIconId = menuController.getLeftIconId();
leftIcon = menuController.getLeftIcon();
secondLineTypeIcon = menuController.getSecondLineTypeIcon();
}
}
protected void acquireNameAndType() {
nameStr = "";
typeStr = "";
commonTypeStr = "";
streetStr = "";
MenuController menuController = getMenuController();
if (menuController != null) {
nameStr = menuController.getNameStr();
typeStr = menuController.getTypeStr();
commonTypeStr = menuController.getCommonTypeStr();
}
if (Algorithms.isEmpty(nameStr)) {
nameStr = typeStr;
typeStr = commonTypeStr;
} else if (Algorithms.isEmpty(typeStr)) {
typeStr = commonTypeStr;
}
}
protected void acquireStreetName() {
addressLookupRequest = new AddressLookupRequest(getLatLon(), new GeocodingLookupService.OnAddressLookupResult() {
@Override
public void geocodingDone(String address) {
if (addressLookupRequest != null) {
addressLookupRequest = null;
if (Algorithms.isEmpty(address)) {
streetStr = PointDescription.getAddressNotFoundStr(getMainActivity().getMyApplication());
} else {
streetStr = address;
}
if (displayStreetNameInTitle()) {
nameStr = streetStr;
getPointDescription().setName(nameStr);
}
onSearchAddressDone();
}
}
}, new GeocodingLookupService.OnAddressLookupProgress() {
@Override
public void geocodingInProgress() {
// animate three dots
}
});
getMainActivity().getMyApplication().getGeocodingLookupService().lookupAddress(addressLookupRequest);
}
protected void onSearchAddressDone() {
}
}

View file

@ -0,0 +1,625 @@
package net.osmand.core.samples.android.sample1.mapcontextmenu.builders;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.v7.app.AlertDialog;
import android.support.v7.view.ContextThemeWrapper;
import android.support.v7.widget.AppCompatButton;
import android.text.Html;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import net.osmand.core.samples.android.sample1.MainActivity;
import net.osmand.core.samples.android.sample1.OsmandResources;
import net.osmand.core.samples.android.sample1.R;
import net.osmand.core.samples.android.sample1.SampleApplication;
import net.osmand.core.samples.android.sample1.data.PointDescription;
import net.osmand.core.samples.android.sample1.mapcontextmenu.ContextMenuHelper;
import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuBuilder;
import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuController;
import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
import net.osmand.data.QuadRect;
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.MapPoiTypes;
import net.osmand.osm.PoiType;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import net.osmand.util.OpeningHoursParser;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class AmenityMenuBuilder extends MenuBuilder {
private final Amenity amenity;
private List<Amenity> nearestWiki = new ArrayList<>();
public AmenityMenuBuilder(MainActivity mainActivity, final Amenity amenity) {
super(mainActivity);
this.amenity = amenity;
processNearstWiki();
}
private void buildRow(View view, int iconId, String text, String textPrefix,
boolean collapsable, final View collapsableView,
int textColor, boolean isWiki, boolean isText, boolean needLinks,
boolean isPhoneNumber, boolean isUrl) {
buildRow(view, getRowIcon(iconId), text, textPrefix, collapsable, collapsableView, textColor,
isWiki, isText, needLinks, isPhoneNumber, isUrl);
}
protected void buildRow(final View view, Drawable icon, final String text, final String textPrefix,
boolean collapsable, final View collapsableView,
int textColor, boolean isWiki, boolean isText, boolean needLinks,
boolean isPhoneNumber, boolean isUrl) {
if (!isFirstRow()) {
buildRowDivider(view, false);
}
final String txt;
if (!Algorithms.isEmpty(textPrefix)) {
txt = textPrefix + ": " + text;
} else {
txt = text;
}
LinearLayout baseView = new LinearLayout(view.getContext());
baseView.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams llBaseViewParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
baseView.setLayoutParams(llBaseViewParams);
LinearLayout ll = new LinearLayout(view.getContext());
ll.setOrientation(LinearLayout.HORIZONTAL);
LinearLayout.LayoutParams llParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ll.setLayoutParams(llParams);
ll.setBackgroundResource(resolveAttribute(view.getContext(), android.R.attr.selectableItemBackground));
ll.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
copyToClipboard(txt, view.getContext());
return true;
}
});
baseView.addView(ll);
// Icon
LinearLayout llIcon = new LinearLayout(view.getContext());
llIcon.setOrientation(LinearLayout.HORIZONTAL);
llIcon.setLayoutParams(new LinearLayout.LayoutParams(dpToPx(72f), dpToPx(48f)));
llIcon.setGravity(Gravity.CENTER_VERTICAL);
ll.addView(llIcon);
ImageView iconView = new ImageView(view.getContext());
LinearLayout.LayoutParams llIconParams = new LinearLayout.LayoutParams(dpToPx(24f), dpToPx(24f));
llIconParams.setMargins(dpToPx(16f), dpToPx(12f), dpToPx(32f), dpToPx(12f));
llIconParams.gravity = Gravity.CENTER_VERTICAL;
iconView.setLayoutParams(llIconParams);
iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
iconView.setImageDrawable(icon);
llIcon.addView(iconView);
// Text
LinearLayout llText = new LinearLayout(view.getContext());
llText.setOrientation(LinearLayout.VERTICAL);
ll.addView(llText);
TextView textView = new TextView(view.getContext());
LinearLayout.LayoutParams llTextParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
llTextParams.setMargins(0, collapsable ? dpToPx(13f) : dpToPx(8f), 0, collapsable ? dpToPx(13f) : dpToPx(8f));
textView.setLayoutParams(llTextParams);
textView.setTextSize(16);
textView.setTextColor(app.getResources().getColor(light ? R.color.ctx_menu_info_text_light : R.color.ctx_menu_info_text_dark));
boolean textDefined = false;
if (isPhoneNumber || isUrl) {
if (!Algorithms.isEmpty(textPrefix)) {
SpannableString spannableString = new SpannableString(txt);
spannableString.setSpan(new URLSpan(txt), textPrefix.length() + 2, txt.length(), 0);
textView.setText(spannableString);
textDefined = true;
} else {
textView.setTextColor(textView.getLinkTextColors());
}
} else if (needLinks) {
textView.setAutoLinkMask(Linkify.ALL);
textView.setLinksClickable(true);
}
textView.setEllipsize(TextUtils.TruncateAt.END);
if (isWiki) {
textView.setMinLines(1);
textView.setMaxLines(15);
} else if (isText) {
textView.setMinLines(1);
textView.setMaxLines(10);
}
if (!textDefined) {
textView.setText(txt);
}
if (textColor > 0) {
textView.setTextColor(view.getResources().getColor(textColor));
}
LinearLayout.LayoutParams llTextViewParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT);
llTextViewParams.weight = 1f;
llTextViewParams.setMargins(0, 0, dpToPx(10f), 0);
llTextViewParams.gravity = Gravity.CENTER_VERTICAL;
llText.setLayoutParams(llTextViewParams);
llText.addView(textView);
final ImageView iconViewCollapse = new ImageView(view.getContext());
if (collapsable && collapsableView != null) {
// Icon
LinearLayout llIconCollapse = new LinearLayout(view.getContext());
llIconCollapse.setLayoutParams(new LinearLayout.LayoutParams(dpToPx(40f), dpToPx(48f)));
llIconCollapse.setOrientation(LinearLayout.HORIZONTAL);
llIconCollapse.setGravity(Gravity.CENTER_VERTICAL);
ll.addView(llIconCollapse);
LinearLayout.LayoutParams llIconCollapseParams = new LinearLayout.LayoutParams(dpToPx(24f), dpToPx(24f));
llIconCollapseParams.setMargins(0, dpToPx(12f), dpToPx(32f), dpToPx(12f));
llIconCollapseParams.gravity = Gravity.CENTER_VERTICAL;
iconViewCollapse.setLayoutParams(llIconCollapseParams);
iconViewCollapse.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
iconViewCollapse.setImageDrawable(app.getIconsCache().getThemedIcon(collapsableView.getVisibility() == View.GONE ?
"ic_action_arrow_down" : "ic_action_arrow_up"));
llIconCollapse.addView(iconViewCollapse);
ll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (collapsableView.getVisibility() == View.VISIBLE) {
collapsableView.setVisibility(View.GONE);
iconViewCollapse.setImageDrawable(app.getIconsCache().getThemedIcon("ic_action_arrow_down"));
} else {
collapsableView.setVisibility(View.VISIBLE);
iconViewCollapse.setImageDrawable(app.getIconsCache().getThemedIcon("ic_action_arrow_up"));
}
}
});
baseView.addView(collapsableView);
}
if (isWiki) {
AppCompatButton wikiButton = new AppCompatButton(view.getContext());
LinearLayout.LayoutParams llWikiButtonParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
llWikiButtonParams.setMargins(0, dpToPx(10f), dpToPx(2f), dpToPx(10f));
wikiButton.setLayoutParams(llWikiButtonParams);
wikiButton.setPadding(dpToPx(14f), 0, dpToPx(14f), 0);
wikiButton.setBackgroundResource(R.drawable.blue_button_drawable);
wikiButton.setTextColor(Color.WHITE);
wikiButton.setText(app.getString("read_more"));
wikiButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ContextMenuHelper.showWikipediaDialog(view.getContext(), app, amenity);
}
});
llText.addView(wikiButton);
}
((LinearLayout) view).addView(baseView);
if (isPhoneNumber) {
ll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
final String[] phones = text.split(",|;");
if (phones.length > 1) {
AlertDialog.Builder dlg = new AlertDialog.Builder(v.getContext());
dlg.setNegativeButton(R.string.shared_string_cancel, null);
dlg.setItems(phones, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + phones[which]));
v.getContext().startActivity(intent);
}
});
dlg.show();
} else {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + text));
v.getContext().startActivity(intent);
}
}
});
} else if (isUrl) {
ll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(text));
v.getContext().startActivity(intent);
}
});
} else if (isWiki) {
ll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ContextMenuHelper.showWikipediaDialog(view.getContext(), app, amenity);
}
});
} else if (isText && text.length() > 200) {
ll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ContextMenuHelper.showDescriptionDialog(view.getContext(), app, text, textPrefix);
}
});
}
rowBuilt();
}
private View getCollapsableTextView(Context context, boolean collapsed, String text) {
final TextView textView = new TextView(context);
textView.setVisibility(collapsed ? View.GONE : View.VISIBLE);
LinearLayout.LayoutParams llTextDescParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
llTextDescParams.setMargins(dpToPx(72f), 0, dpToPx(40f), dpToPx(13f));
textView.setLayoutParams(llTextDescParams);
textView.setTextSize(16);
textView.setTextColor(app.getResources().getColor(light ? R.color.ctx_menu_info_text_light : R.color.ctx_menu_info_text_dark));
textView.setText(text);
return textView;
}
private View getCollapsableWikiView(Context context, boolean collapsed) {
final LinearLayout view = new LinearLayout(context);
view.setOrientation(LinearLayout.VERTICAL);
view.setVisibility(collapsed ? View.GONE : View.VISIBLE);
LinearLayout.LayoutParams llParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
llParams.setMargins(dpToPx(68f), 0, dpToPx(12f), dpToPx(13f));
view.setLayoutParams(llParams);
for (final Amenity wiki : nearestWiki) {
AppCompatButton wikiButton = new AppCompatButton(
new ContextThemeWrapper(view.getContext(), R.style.AppTheme));
LinearLayout.LayoutParams llWikiButtonParams =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
wikiButton.setLayoutParams(llWikiButtonParams);
wikiButton.setPadding(dpToPx(14f), 0, dpToPx(14f), 0);
wikiButton.setTextColor(app.getResources()
.getColor(light ? R.color.color_dialog_buttons_light : R.color.color_dialog_buttons_dark));
wikiButton.setText(wiki.getName());
wikiButton.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
wikiButton.setSingleLine(true);
wikiButton.setEllipsize(TextUtils.TruncateAt.END);
wikiButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PointDescription pointDescription = MenuController.getObjectName(wiki);
mainActivity.getContextMenu().show(
new LatLon(wiki.getLocation().getLatitude(), wiki.getLocation().getLongitude()),
pointDescription, wiki);
}
});
view.addView(wikiButton);
}
return view;
}
@Override
public void buildInternal(View view) {
boolean hasWiki = false;
MapPoiTypes poiTypes = app.getPoiTypes();
String preferredLang = SampleApplication.LANGUAGE;
List<AmenityInfoRow> infoRows = new LinkedList<>();
List<AmenityInfoRow> descriptions = new LinkedList<>();
for (Map.Entry<String, String> e : amenity.getAdditionalInfo().entrySet()) {
int iconId;
Drawable icon = null;
int textColor = 0;
String key = e.getKey();
String vl = e.getValue();
String textPrefix = "";
View collapsableView = null;
boolean collapsable = false;
boolean isWiki = false;
boolean isText = false;
boolean isDescription = false;
boolean needLinks = !"population".equals(key);
boolean isPhoneNumber = false;
boolean isUrl = false;
int poiTypeOrder = 0;
String poiTypeKeyName = "";
AbstractPoiType pt = poiTypes.getAnyPoiAdditionalTypeByKey(key);
if (pt == null && !Algorithms.isEmpty(vl) && vl.length() < 50) {
pt = poiTypes.getAnyPoiAdditionalTypeByKey(key + "_" + vl);
}
PoiType pType = null;
if (pt != null) {
pType = (PoiType) pt;
if (pType.isFilterOnly()) {
continue;
}
poiTypeOrder = pType.getOrder();
poiTypeKeyName = pType.getKeyName();
}
if (amenity.getType().isWiki()) {
if (!hasWiki) {
iconId = OsmandResources.getDrawableId("ic_action_note_dark");
String lng = amenity.getContentSelected("content", preferredLang, "en");
if (Algorithms.isEmpty(lng)) {
lng = "en";
}
final String langSelected = lng;
String content = amenity.getDescription(langSelected);
vl = Html.fromHtml(content).toString();
if (vl.length() > 300) {
vl = vl.substring(0, 300);
}
hasWiki = true;
isWiki = true;
needLinks = false;
} else {
continue;
}
} else if (key.startsWith("name:")) {
continue;
} else if (Amenity.OPENING_HOURS.equals(key)) {
iconId = OsmandResources.getDrawableId("ic_action_time");
collapsableView = getCollapsableTextView(view.getContext(), true, amenity.getOpeningHours());
collapsable = true;
OpeningHoursParser.OpeningHours rs = OpeningHoursParser.parseOpenedHours(amenity.getOpeningHours());
if (rs != null) {
vl = rs.toLocalString();
Calendar inst = Calendar.getInstance();
inst.setTimeInMillis(System.currentTimeMillis());
boolean opened = rs.isOpenedForTime(inst);
if (opened) {
textColor = R.color.color_ok;
} else {
textColor = R.color.color_invalid;
}
}
needLinks = false;
} else if (Amenity.PHONE.equals(key)) {
iconId = OsmandResources.getDrawableId("ic_action_call_dark");
isPhoneNumber = true;
} else if (Amenity.WEBSITE.equals(key)) {
iconId = OsmandResources.getDrawableId("ic_world_globe_dark");
isUrl = true;
} else if (Amenity.CUISINE.equals(key)) {
iconId = OsmandResources.getDrawableId("ic_action_cuisine");
StringBuilder sb = new StringBuilder();
for (String c : e.getValue().split(";")) {
if (sb.length() > 0) {
sb.append(", ");
} else {
sb.append(app.getString("poi_cuisine")).append(": ");
}
sb.append(poiTypes.getPoiTranslation("cuisine_" + c).toLowerCase());
}
vl = sb.toString();
} else {
if (key.contains(Amenity.DESCRIPTION)) {
iconId = OsmandResources.getDrawableId("ic_action_note_dark");
} else {
iconId = OsmandResources.getDrawableId("ic_action_info_dark");
}
if (pType != null) {
poiTypeOrder = pType.getOrder();
poiTypeKeyName = pType.getKeyName();
if (pType.getParentType() != null && pType.getParentType() instanceof PoiType) {
icon = getRowIcon(view.getContext(), ((PoiType) pType.getParentType()).getOsmTag() + "_" + pType.getOsmTag().replace(':', '_') + "_" + pType.getOsmValue());
}
if (!pType.isText()) {
if (!Algorithms.isEmpty(pType.getPoiAdditionalCategory())) {
vl = pType.getPoiAdditionalCategoryTranslation() + ": " + pType.getTranslation().toLowerCase();
} else {
vl = pType.getTranslation();
}
} else {
isText = true;
isDescription = iconId == OsmandResources.getDrawableId("ic_action_note_dark");
textPrefix = pType.getTranslation();
vl = amenity.unzipContent(e.getValue());
}
if (!isDescription && icon == null) {
icon = getRowIcon(view.getContext(), pType.getIconKeyName());
if (isText && icon != null) {
textPrefix = "";
}
}
if (icon == null && isText) {
iconId = OsmandResources.getDrawableId("ic_action_note_dark");
}
} else {
textPrefix = Algorithms.capitalizeFirstLetterAndLowercase(e.getKey());
vl = amenity.unzipContent(e.getValue());
}
}
if (vl.startsWith("http://") || vl.startsWith("https://") || vl.startsWith("HTTP://") || vl.startsWith("HTTPS://")) {
isUrl = true;
}
if (isDescription) {
descriptions.add(new AmenityInfoRow(key, OsmandResources.getDrawableId("ic_action_note_dark"), textPrefix,
vl, collapsable, collapsableView, 0, false, true, true, 0, "", false, false));
} else if (icon != null) {
infoRows.add(new AmenityInfoRow(key, icon, textPrefix, vl, collapsable, collapsableView,
textColor, isWiki, isText, needLinks, poiTypeOrder, poiTypeKeyName, isPhoneNumber, isUrl));
} else {
infoRows.add(new AmenityInfoRow(key, iconId, textPrefix, vl, collapsable, collapsableView,
textColor, isWiki, isText, needLinks, poiTypeOrder, poiTypeKeyName, isPhoneNumber, isUrl));
}
}
Collections.sort(infoRows, new Comparator<AmenityInfoRow>() {
@Override
public int compare(AmenityInfoRow row1, AmenityInfoRow row2) {
if (row1.order < row2.order) {
return -1;
} else if (row1.order == row2.order) {
return row1.name.compareTo(row2.name);
} else {
return 1;
}
}
});
for (AmenityInfoRow info : infoRows) {
buildAmenityRow(view, info);
}
String langSuffix = ":" + preferredLang;
AmenityInfoRow descInPrefLang = null;
for (AmenityInfoRow desc : descriptions) {
if (desc.key.length() > langSuffix.length()
&& desc.key.substring(desc.key.length() - langSuffix.length(), desc.key.length()).equals(langSuffix)) {
descInPrefLang = desc;
break;
}
}
if (descInPrefLang != null) {
descriptions.remove(descInPrefLang);
descriptions.add(0, descInPrefLang);
}
for (AmenityInfoRow info : descriptions) {
buildAmenityRow(view, info);
}
if (nearestWiki.size() > 0) {
AmenityInfoRow wikiInfo = new AmenityInfoRow(
"nearest_wiki", OsmandResources.getDrawableId("ic_action_wikipedia"), null, app.getString("wiki_around") + " (" + nearestWiki.size()+")", true,
getCollapsableWikiView(view.getContext(), true),
0, false, false, false, 1000, null, false, false);
buildAmenityRow(view, wikiInfo);
}
buildRow(view, OsmandResources.getDrawableId("ic_action_get_my_location"), PointDescription.getLocationName(app,
amenity.getLocation().getLatitude(), amenity.getLocation().getLongitude(), true)
.replaceAll("\n", " "), 0, false, 0, false, null);
}
public void buildAmenityRow(View view, AmenityInfoRow info) {
if (info.icon != null) {
buildRow(view, info.icon, info.text, info.textPrefix, info.collapsable, info.collapsableView,
info.textColor, info.isWiki, info.isText, info.needLinks, info.isPhoneNumber, info.isUrl);
} else if (info.iconId != 0) {
buildRow(view, info.iconId, info.text, info.textPrefix, info.collapsable, info.collapsableView,
info.textColor, info.isWiki, info.isText, info.needLinks, info.isPhoneNumber, info.isUrl);
}
}
private void processNearstWiki() {
QuadRect rect = MapUtils.calculateLatLonBbox(
amenity.getLocation().getLatitude(), amenity.getLocation().getLongitude(), 250);
/* todo
nearestWiki = app.getResourceManager().searchAmenities(
new BinaryMapIndexReader.SearchPoiTypeFilter() {
@Override
public boolean accept(PoiCategory type, String subcategory) {
return type.isWiki();
}
@Override
public boolean isEmpty() {
return false;
}
}, rect.top, rect.left, rect.bottom, rect.right, -1, null);
Collections.sort(nearestWiki, new Comparator<Amenity>() {
@Override
public int compare(Amenity o1, Amenity o2) {
double d1 = MapUtils.getDistance(amenity.getLocation(), o1.getLocation());
double d2 = MapUtils.getDistance(amenity.getLocation(), o2.getLocation());
return Double.compare(d1, d2);
}
});
for (Amenity wiki : nearestWiki) {
if (wiki.getId().equals(amenity.getId())) {
nearestWiki.remove(wiki);
break;
}
}
*/
}
private static class AmenityInfoRow {
private String key;
private Drawable icon;
private int iconId;
private String textPrefix;
private String text;
private View collapsableView;
private boolean collapsable;
private int textColor;
private boolean isWiki;
private boolean isText;
private boolean needLinks;
private boolean isPhoneNumber;
private boolean isUrl;
private int order;
private String name;
public AmenityInfoRow(String key, Drawable icon, String textPrefix, String text,
boolean collapsable, View collapsableView,
int textColor, boolean isWiki, boolean isText, boolean needLinks,
int order, String name, boolean isPhoneNumber, boolean isUrl) {
this.key = key;
this.icon = icon;
this.textPrefix = textPrefix;
this.text = text;
this.collapsable = collapsable;
this.collapsableView = collapsableView;
this.textColor = textColor;
this.isWiki = isWiki;
this.isText = isText;
this.needLinks = needLinks;
this.order = order;
this.name = name;
this.isPhoneNumber = isPhoneNumber;
this.isUrl = isUrl;
}
public AmenityInfoRow(String key, int iconId, String textPrefix, String text,
boolean collapsable, View collapsableView,
int textColor, boolean isWiki, boolean isText, boolean needLinks,
int order, String name, boolean isPhoneNumber, boolean isUrl) {
this.key = key;
this.iconId = iconId;
this.textPrefix = textPrefix;
this.text = text;
this.collapsable = collapsable;
this.collapsableView = collapsableView;
this.textColor = textColor;
this.isWiki = isWiki;
this.isText = isText;
this.needLinks = needLinks;
this.order = order;
this.name = name;
this.isPhoneNumber = isPhoneNumber;
this.isUrl = isUrl;
}
}
}

View file

@ -0,0 +1,115 @@
package net.osmand.core.samples.android.sample1.mapcontextmenu.controllers;
import net.osmand.core.samples.android.sample1.MainActivity;
import net.osmand.core.samples.android.sample1.OsmandResources;
import net.osmand.core.samples.android.sample1.data.PointDescription;
import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuBuilder;
import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuController;
import net.osmand.core.samples.android.sample1.mapcontextmenu.builders.AmenityMenuBuilder;
import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
import net.osmand.util.Algorithms;
public class AmenityMenuController extends MenuController {
private Amenity amenity;
public AmenityMenuController(MainActivity mainActivity, PointDescription pointDescription, Amenity amenity) {
super(new AmenityMenuBuilder(mainActivity, amenity), pointDescription, mainActivity);
this.amenity = amenity;
}
@Override
protected void setObject(Object object) {
if (object instanceof Amenity) {
this.amenity = (Amenity) object;
}
}
@Override
protected Object getObject() {
return amenity;
}
@Override
protected int getSupportedMenuStatesPortrait() {
return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN | MenuState.FULL_SCREEN;
}
@Override
public boolean needStreetName() {
if (amenity.getSubType() != null && amenity.getType() != null) {
PoiType pt = amenity.getType().getPoiTypeByKeyName(amenity.getSubType());
if (pt != null && pt.getOsmTag() != null && pt.getOsmTag().equals("place")) {
return false;
}
}
return true;
}
@Override
public int getLeftIconId() {
return getLeftIconId(amenity);
}
public static int getLeftIconId(Amenity amenity) {
int id = 0;
PoiType st = amenity.getType().getPoiTypeByKeyName(amenity.getSubType());
if (st != null) {
id = OsmandResources.getBigDrawableId(st.getIconKeyName());
if (id == 0) {
id = OsmandResources.getBigDrawableId(st.getOsmTag() + "_" + st.getOsmValue());
}
}
return id;
}
@Override
public boolean displayDistanceDirection() {
return true;
}
@Override
public String getTypeStr() {
return getTypeStr(amenity);
}
public static String getTypeStr(Amenity amenity) {
PoiCategory pc = amenity.getType();
PoiType pt = pc.getPoiTypeByKeyName(amenity.getSubType());
String typeStr = amenity.getSubType();
if (pt != null) {
typeStr = pt.getTranslation();
} else if (typeStr != null) {
typeStr = Algorithms.capitalizeFirstLetterAndLowercase(typeStr.replace('_', ' '));
}
return typeStr;
}
@Override
public String getCommonTypeStr() {
PoiCategory pc = amenity.getType();
return pc.getTranslation();
}
@Override
public void addPlainMenuItems(String typeStr, PointDescription pointDescription, LatLon latLon) {
addPlainMenuItems(amenity, typeStr, builder);
}
public static void addPlainMenuItems(Amenity amenity, String typeStr, MenuBuilder builder) {
if (!Algorithms.isEmpty(typeStr)) {
int resId = getLeftIconId(amenity);
if (resId == 0) {
PoiCategory pc = amenity.getType();
resId = OsmandResources.getBigDrawableId(pc.getIconKeyName());
}
if (resId == 0) {
resId = OsmandResources.getDrawableId("ic_action_folder_stroke");
}
builder.addPlainMenuItem(resId, typeStr, false, false, null);
}
}
}

View file

@ -0,0 +1,51 @@
package net.osmand.core.samples.android.sample1.mapcontextmenu.controllers;
import android.graphics.drawable.Drawable;
import net.osmand.core.samples.android.sample1.MainActivity;
import net.osmand.core.samples.android.sample1.OsmandResources;
import net.osmand.core.samples.android.sample1.data.PointDescription;
import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuBuilder;
import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuController;
public class MyLocationMenuController extends MenuController {
public MyLocationMenuController(MainActivity mainActivity, PointDescription pointDescription) {
super(new MenuBuilder(mainActivity), pointDescription, mainActivity);
}
@Override
protected void setObject(Object object) {
}
@Override
protected Object getObject() {
return getLatLon();
}
@Override
protected int getSupportedMenuStatesPortrait() {
return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN;
}
@Override
public String getTypeStr() {
return getPointDescription().getTypeName();
}
@Override
public String getCommonTypeStr() {
return getMainActivity().getMyApplication().getString("shared_string_location");
}
@Override
public boolean needStreetName() {
return true;
}
@Override
public Drawable getLeftIcon() {
return OsmandResources.getDrawable("map_pedestrian_location");
}
}

View file

@ -0,0 +1,82 @@
package net.osmand.core.samples.android.sample1.mapcontextmenu.controllers;
import android.graphics.drawable.Drawable;
import net.osmand.core.samples.android.sample1.MainActivity;
import net.osmand.core.samples.android.sample1.OsmandResources;
import net.osmand.core.samples.android.sample1.data.PointDescription;
import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuBuilder;
import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuController;
import net.osmand.util.Algorithms;
public class PointDescriptionMenuController extends MenuController {
private boolean hasTypeInDescription;
public PointDescriptionMenuController(MainActivity mainActivity, final PointDescription pointDescription) {
super(new MenuBuilder(mainActivity), pointDescription, mainActivity);
initData();
}
private void initData() {
hasTypeInDescription = !Algorithms.isEmpty(getPointDescription().getTypeName());
}
@Override
protected void setObject(Object object) {
initData();
}
@Override
protected Object getObject() {
return null;
}
@Override
protected int getSupportedMenuStatesPortrait() {
return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN | MenuState.FULL_SCREEN;
}
@Override
public boolean displayStreetNameInTitle() {
return true;
}
@Override
public boolean displayDistanceDirection() {
return true;
}
@Override
public Drawable getLeftIcon() {
return getIcon(getPointDescription().getIconId());
}
@Override
public Drawable getSecondLineTypeIcon() {
if (hasTypeInDescription) {
return getIcon(OsmandResources.getDrawableId("ic_small_group"));
} else {
return null;
}
}
@Override
public String getTypeStr() {
if (hasTypeInDescription) {
return getPointDescription().getTypeName();
} else {
return "";
}
}
@Override
public String getCommonTypeStr() {
return getMainActivity().getMyApplication().getString("shared_string_location");
}
@Override
public boolean needStreetName() {
return !getPointDescription().isAddress();
}
}

View file

@ -23,7 +23,7 @@ public class QuickSearchHelper {
public QuickSearchHelper(SampleApplication app) { public QuickSearchHelper(SampleApplication app) {
this.app = app; this.app = app;
core = new SearchUICore(app.getPoiTypes(), SampleApplication.LANGUAGE, false); core = new SearchUICore(app.getPoiTypes(), SampleApplication.LANGUAGE, SampleApplication.TRANSLITERATE);
} }
public SearchUICore getCore() { public SearchUICore getCore() {

View file

@ -198,13 +198,7 @@ public abstract class QuickSearchListFragment extends ListFragment {
dialogFragment.hide(); dialogFragment.hide();
getMainActivity().showOnMap(searchResult.location, searchResult.preferredZoom); getMainActivity().showOnMap(searchResult.location, searchResult.preferredZoom);
/* todo getMainActivity().getContextMenu().show(searchResult.location, pointDescription, object);
getMyApplication().getSettings().setMapLocationToShow(
searchResult.location.getLatitude(), searchResult.location.getLongitude(),
searchResult.preferredZoom, pointDescription, true, object);
MapActivity.launchMapActivityMoveToTop(getActivity());
*/
} }
} }

View file

@ -202,11 +202,11 @@ public class QuickSearchListItem {
} }
public static int getPoiTypeIconId(SampleApplication app, AbstractPoiType abstractPoiType) { public static int getPoiTypeIconId(SampleApplication app, AbstractPoiType abstractPoiType) {
int res = OsmandResources.getDrawableId("mx_" + abstractPoiType.getIconKeyName()); int res = OsmandResources.getBigDrawableId(abstractPoiType.getIconKeyName());
if (res != 0) { if (res != 0) {
return res; return res;
} else if (abstractPoiType instanceof PoiType) { } else if (abstractPoiType instanceof PoiType) {
res = OsmandResources.getDrawableId("mx_" + ((PoiType) abstractPoiType).getOsmTag() res = OsmandResources.getBigDrawableId(((PoiType) abstractPoiType).getOsmTag()
+ "_" + ((PoiType) abstractPoiType).getOsmValue()); + "_" + ((PoiType) abstractPoiType).getOsmValue());
if (res != 0) { if (res != 0) {
return res; return res;
@ -222,9 +222,9 @@ public class QuickSearchListItem {
int res = 0; int res = 0;
PoiType st = amenity.getType().getPoiTypeByKeyName(amenity.getSubType()); PoiType st = amenity.getType().getPoiTypeByKeyName(amenity.getSubType());
if (st != null) { if (st != null) {
res = OsmandResources.getDrawableId("mx_" + st.getIconKeyName()); res = OsmandResources.getBigDrawableId(st.getIconKeyName());
if (res == 0) { if (res == 0) {
res = OsmandResources.getDrawableId("mx_" + st.getOsmTag() + "_" + st.getOsmValue()); res = OsmandResources.getBigDrawableId(st.getOsmTag() + "_" + st.getOsmValue());
} }
} }
return res; return res;
@ -234,9 +234,9 @@ public class QuickSearchListItem {
PoiType st = amenity.getType().getPoiTypeByKeyName(amenity.getSubType()); PoiType st = amenity.getType().getPoiTypeByKeyName(amenity.getSubType());
if (st != null) { if (st != null) {
String id = st.getIconKeyName(); String id = st.getIconKeyName();
if (OsmandResources.getDrawableId("mx_" + id) == 0) { if (OsmandResources.getBigDrawableId(id) == 0) {
id = st.getOsmTag() + "_" + st.getOsmValue(); id = st.getOsmTag() + "_" + st.getOsmValue();
if (OsmandResources.getDrawableId("mx_" + id) != 0) { if (OsmandResources.getBigDrawableId(id) != 0) {
return id; return id;
} }
} else { } else {

View file

@ -0,0 +1,37 @@
package net.osmand.core.samples.android.sample1.view;
import android.view.GestureDetector;
import android.view.MotionEvent;
public class SingleTapConfirm implements GestureDetector.OnGestureListener {
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
}