Quick search for samples in progress

This commit is contained in:
Alexey Kulish 2016-11-15 19:57:42 +03:00
parent 4eb7265bf9
commit 38a8fec227
47 changed files with 5122 additions and 727 deletions

View file

@ -105,6 +105,7 @@ repositories {
dependencies {
compile project(path: ':OsmAnd-java', configuration: 'android')
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.android.support:design:23.3.0'
compile fileTree(dir: "libs", include: ["*.jar"])
compile "net.osmand:OsmAndCore_android:0.1-SNAPSHOT@aar"
debugCompile "net.osmand:OsmAndCore_androidNativeRelease:0.1-SNAPSHOT@aar"

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 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: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -5,78 +5,6 @@
android:orientation="vertical"
tools:context="net.osmand.core.samples.android.sample1.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:focusableInTouchMode="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="48dp"
android:layout_height="match_parent"
android:gravity="center">
<ProgressBar
android:id="@+id/searchProgressBar"
android:layout_width="32dp"
android:layout_height="32dp"
android:indeterminate="true"
android:visibility="gone"/>
<ImageView
android:id="@+id/searchIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_action_search_dark"/>
</LinearLayout>
<EditText
android:id="@+id/searchEditText"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="8dp"
android:background="@null"
android:gravity="center_vertical"
android:hint="@string/search_hint"
android:lines="1"
android:textColor="@color/titleTextColor"
tools:text="Search request"/>
<ImageButton
android:id="@+id/clearButton"
style="@style/Widget.AppCompat.ActionButton"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="@string/shared_string_close"
android:src="@drawable/ic_action_remove_dark"/>
</LinearLayout>
<TextView
android:id="@+id/searchDetailsText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="56dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:gravity="center_vertical"
android:lines="1"
android:textColor="@color/titleTextColor"
android:visibility="gone"
tools:text="City • Street"
tools:visibility="visible"/>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -107,6 +35,23 @@
</FrameLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|left"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp">
<ImageButton
android:id="@+id/search_button"
android:layout_width="52dp"
android:layout_height="52dp"
android:background="@drawable/btn_circle"
android:contentDescription="@string/shared_string_search"
android:src="@drawable/map_search_dark"/>
</FrameLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="@+id/bottomShadowView"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/ctx_menu_info_view_bg"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto">
<net.osmand.core.samples.android.sample1.customcontrols.OsmandImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
app:osmandSrc="bg_shadow_list_bottom"/>
<View
android:layout_width="match_parent"
android:layout_height="16dp"/>
</LinearLayout>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="@+id/topShadowView"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/ctx_menu_info_view_bg"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto">
<View
android:layout_width="match_parent"
android:layout_height="16dp"/>
<net.osmand.core.samples.android.sample1.customcontrols.OsmandImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
app:osmandSrc="bg_shadow_list_top"/>
</LinearLayout>

View file

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="fill_parent"
android:layout_height="@dimen/dashboard_map_toolbar"
android:background="?attr/bg_color"
android:minHeight="@dimen/dashboard_map_toolbar"
android:theme="?attr/toolbar_theme"
app:contentInsetLeft="54dp"
app:contentInsetStart="54dp">
<include layout="@layout/search_text_layout"/>
</android.support.v7.widget.Toolbar>
<LinearLayout
android:id="@+id/button_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/ctx_menu_info_view_bg"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/ctx_menu_info_divider"/>
<LinearLayout
android:id="@+id/buttonToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:minHeight="48dp"
android:orientation="horizontal">
<net.osmand.core.samples.android.sample1.customcontrols.OsmandImageView
android:id="@+id/buttonToolbarImage"
android:layout_width="54dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:osmandSrc="ic_action_marker_dark"/>
<net.osmand.core.samples.android.sample1.customcontrols.OsmandTextView
android:id="@+id/buttonToolbarTitle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@null"
android:ellipsize="end"
android:gravity="center_vertical"
android:lines="1"
android:singleLine="true"
android:textColor="?attr/color_dialog_buttons"
android:textSize="@dimen/default_desc_text_size"
app:osmandText="shared_string_show_on_map"/>
<net.osmand.core.samples.android.sample1.customcontrols.OsmandImageButton
android:id="@+id/filterButton"
style="@style/Widget.AppCompat.ActionButton"
android:layout_width="48dp"
android:layout_height="match_parent"
android:visibility="gone"
app:osmandSrc="ic_action_filter"/>
</LinearLayout>
</LinearLayout>
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:id="@+id/search_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone">
</LinearLayout>
</LinearLayout>
</FrameLayout>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@null"
android:dividerHeight="0dp"
android:drawSelectorOnTop="true"/>
</LinearLayout>

View file

@ -3,58 +3,147 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/listPreferredItemHeight"
android:orientation="horizontal"
android:paddingBottom="12dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginRight="8dp"
android:layout_gravity="top"
android:scaleType="centerInside"
android:visibility="visible"/>
android:orientation="vertical">
<LinearLayout
android:id="@+id/searchListItemLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:minHeight="60dp"
android:orientation="horizontal"
android:paddingBottom="8dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp">
<CheckBox
android:id="@+id/toggle_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="20dp"
android:focusable="false"
android:visibility="gone"
tools:visibility="visible"/>
<ImageView
android:id="@+id/imageView"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginRight="8dp"
android:scaleType="centerInside"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="0dp"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingRight="16dp"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
tools:text="Amsterdam"/>
android:orientation="horizontal">
<TextView
android:id="@+id/distance"
android:layout_width="wrap_content"
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingRight="16dp"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
tools:text="Amsterdam"/>
<LinearLayout
android:id="@+id/compass_layout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
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:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_sub_text_size"
tools:text="100500 km"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:text="100 km"/>
android:orientation="horizontal">
<ImageView
android:id="@+id/type_name_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4.5dp"
android:layout_marginRight="4dp"/>
<TextView
android:id="@+id/subtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
tools:text="City"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/time_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="@dimen/gpx_small_icon_margin"/>
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_sub_text_size"
tools:text="10-12 am"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:text="City"/>
</LinearLayout>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/dashboard_divider_light"/>
</LinearLayout>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:orientation="horizontal"
android:paddingBottom="8dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textColor="@color/color_dialog_buttons_light"
android:textSize="@dimen/default_sub_text_size"
tools:text="Amsterdam"/>
</LinearLayout>

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="56dp"
android:focusableInTouchMode="true"
android:gravity="center_vertical"
android:orientation="horizontal">
<EditText
android:id="@+id/searchEditText"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@null"
android:gravity="center_vertical"
android:lines="1"
android:singleLine="true"
android:textColor="?attr/searchbar_text"
android:textColorHint="?attr/searchbar_text_hint"/>
<ProgressBar
android:id="@+id/searchProgressBar"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginRight="8dp"
android:indeterminate="true"
android:visibility="gone"/>
<ImageButton
android:id="@+id/clearButton"
style="@style/Widget.AppCompat.ActionButton"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="@string/shared_string_close"
android:src="@drawable/ic_action_remove_dark"/>
</LinearLayout>

View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="AppTheme">
<!-- list colors -->
<attr name="dashboard_divider" format="reference" />
<attr name="ctx_menu_info_divider" format="color"/>
<attr name="searchbar_text" format="color"/>
<attr name="searchbar_text_hint" format="color"/>
<attr name="list_divider" format="color"/>
<attr name="expandable_list_item_background" format="color"/>
<attr name="expandable_list_background" format="color"/>
<attr name="bg_color" format="reference" />
<attr name="ctx_menu_info_view_bg" format="reference" />
<attr name="expandable_category_color" format="reference"/>
<attr name="bottomToolBarColor" format="color" />
<attr name="spinnerItemTextColor" format="reference" />
<attr name="spinnerListBackground" format="color|reference" />
<attr name="search_background" format="reference" />
<attr name="osmo_header_background" format="color"/>
<attr name="dashboard_subheader_text_color" format="color"/>
<attr name="dashboard_general_button_text_color" format="color"/>
<attr name="dialog_inactive_text_color" format="reference"/>
<attr name="toolbar_theme" format="reference"/>
<attr name="divider_color" format="reference" />
<attr name="contextMenuButtonColor" format="reference" />
<attr name="color_dialog_buttons" format="color"/>
<attr name="secondary_icon_color" format="color"/>
</declare-styleable>
<declare-styleable name="OsmandTextView">
<attr name="osmandText" format="string"/>
</declare-styleable>
<declare-styleable name="OsmandButton" parent="OsmandTextView"/>
<declare-styleable name="OsmandImageButton" parent="OsmandTextView">
<attr name="osmandSrc" format="string"/>
</declare-styleable>
<declare-styleable name="OsmandImageView" parent="OsmandImageButton"/>
</resources>

View file

@ -7,11 +7,235 @@
<color name="dividerColor">#F0F0F0</color>
<color name="windowBackgroundColor">#EAEAEA</color>
<color name="itemBackgroundColor">#FFF</color>
<color name="iconColor">#727272</color>
<color name="dialogTitleBackgroundColor">#2f7af5</color>
<color name="listBackgroundColor">#EAEAEA</color>
<color name="titleTextColor">#FFF</color>
<color name="listTextColor">#000</color>
<color name="gpx_track_width_prop">#853fc5</color>
<color name="xmas_blue">#3f51b5</color>
<color name="disabled_btn_text_color">#a0a0a0</color>
<color name="discount_bar_bg">#357ef2</color>
<color name="searchbar_text_dark">#fff</color>
<color name="searchbar_text_light">#212121</color>
<color name="searchbar_text_hint_dark">#7a8c99</color>
<color name="searchbar_text_hint_light">#727272</color>
<color name="searchbar_tab_inactive_dark">#5b6872</color>
<color name="searchbar_tab_inactive_light">#727272</color>
<color name="markers_top_bar_background">#0f5257</color>
<color name="markers_top_bar_2nd_background">#0c4347</color>
<color name="marker_top_2nd_line_color">#859899</color>
<color name="marker_blue">#2196f3</color>
<color name="marker_green">#73b825</color>
<color name="marker_orange">#ff9800</color>
<color name="marker_red">#e53935</color>
<color name="marker_yellow">#FDD835</color>
<color name="marker_teal">#26a69a</color>
<color name="marker_purple">#ab47bc</color>
<color name="popup_bg_color">#EE666666</color>
<color name="popup_separator_color">#BBBBBB</color>
<color name="popup_text_color">#FFFFFF</color>
<color name="primary_text_light">#de000000</color>
<color name="secondary_text_light">#8a000000</color>
<color name="primary_text_dark">#ffffffff</color>
<color name="secondary_text_dark">#b3ffffff</color>
<color name="audio_video_icon_color">#128a89</color>
<color name="created_poi_icon_color">#4caf50</color>
<color name="osm_bug_unresolved_icon_color">#d44a4a</color>
<color name="osm_bug_resolved_icon_color">#4caf50</color>
<color name="osmand_orange">#ff8f00</color>
<color name="app_mode_icon_color">#33B4E4</color>
<color name="recording_color">#F44336</color>
<color name="dash_search_icon_light">#536DFE</color>
<color name="dash_search_icon_dark">#7a8c99</color>
<color name="parking_outdated_color">#f41a34</color>
<color name="osmo_header_dark">#2d383d</color>
<color name="osmo_header_light">#b36d12</color>
<color name="dashboard_parking_light_selected">#007888</color>
<color name="dashboard_parking_light_color">#009688</color>
<color name="dashboard_parking_dark_color">#54778c</color>
<color name="dashboard_parking_dark_selected">#446072</color>
<color name="plugin_details_install_header_bg_light">#dbdbdb</color>
<color name="plugin_details_install_header_bg_dark">#2d3438</color>
<color name="list_divider_dark">#1f2326</color>
<color name="list_divider_light">@color/color_white</color>
<color name="list_sub_menu_background_dark">#475259</color>
<!-- <color name="list_item_light">@color/color_white</color>
<color name="list_item_background_dark">#333b40</color> -->
<color name="list_item_light">#00000000</color>
<color name="list_item_dark">#00000000</color>
<color name="list_item_light_pressed">#8cd0d0d0</color>
<color name="list_item_dark_pressed">#be39464d</color>
<color name="bg_color_light">#fff</color>
<color name="bg_color_dark">#333b40</color>
<color name="fab_color">#ff8f00</color>
<color name="fab_color_pressed">#e58200</color>
<color name="map_widget_icon_color">#ff8f00</color>
<color name="map_widget_stroke">#4C000000</color>
<color name="map_widget_light">#fff</color>
<color name="map_widget_dark">#a0000000</color>
<color name="map_widget_dark_stroke">#80ffffff</color>
<color name="map_widget_dark_pressed">#80aaaaaa</color>
<color name="map_widget_light_trans">#80ffffff</color>
<color name="map_widget_light_pressed">#e5e5e5</color>
<color name="map_widget_blue">#536dfe</color>
<color name="map_widget_blue_pressed">#485dd9</color>
<color name="actionbar_dark_color">#39464d</color>
<color name="tool_bar_color_dark">#CC080B0D</color>
<color name="actionbar_light_color">#ff8f00</color>
<color name="tool_bar_color_light">#b4ff8f00</color>
<color name="download_pressed_light">#8cff8f00</color>
<color name="download_pressed_dark">#be39464d</color>
<color name="search_background_dark">#292f33</color>
<color name="icon_color">#727272</color>
<color name="icon_color_light">#ccc</color>
<color name="on_map_icon_color">#505050</color>
<color name="ctx_menu_info_view_bg_light">#eaeaea</color>
<color name="ctx_menu_info_view_bg_dark">#292f33</color>
<color name="ctx_menu_info_text_light">#212121</color>
<color name="ctx_menu_info_text_dark">#b4c3cc</color>
<color name="ctx_menu_info_divider_light">#d9d9d9</color>
<color name="ctx_menu_info_divider_dark">#333b40</color>
<color name="dashboard_gpx_on_map">#448AFF</color>
<color name="dashboard_background">#eaeaea</color>
<color name="dashboard_divider_light">#F0F0F0</color>
<color name="dashboard_divider_dark">#3d474c</color>
<color name="dashboard_black">#212121</color>
<color name="dashboard_blue">#536DFE</color>
<color name="dashboard_subheader_text_dark">#b4c3cc</color>
<color name="dashboard_subheader_text_light">#727272</color>
<color name="dashboard_general_button_text_dark">#ff8f00</color>
<color name="dashboard_general_button_text_light">#536DFE</color>
<color name="color_transparent">#0000</color>
<color name="widgettext_night">#ffC8C8C8</color>
<!-- widgettext_shadow_night is the same as widget background color for non-transparent night skin (from box_night_free_simple.9.png) -->
<color name="widgettext_shadow_night">#dc262626</color>
<!-- style colors -->
<color name="group_background">#A5A5A5</color>
<color name="background_tab_pressed">#1AFFFFFF</color>
<!-- <color name="activity_background">#666666</color> -->
<!-- Distance to object suitable for all themes -->
<color name="color_distance">#FD9822</color>
<color name="color_myloc_distance">#0080FF</color>
<color name="wpt_distance_color">#dd6CB336</color>
<!-- Old dialogs colors -->
<color name="color_white">#FFF</color>
<color name="color_black">#000</color>
<color name="row_selection_color">#CC33BBE0</color>
<!-- GPX analysis colors -->
<color name="gpx_color_point">#cd2c33</color>
<color name="gpx_speed">#c79c00</color>
<color name="gpx_altitude_desc">#32CD32</color>
<color name="gpx_altitude_asc">#EE3232</color>
<color name="gpx_distance_color">#ffa500</color>
<color name="gpx_time_span_color">#0080FF</color>
<color name="color_favorite">#eecc22</color>
<!-- Themed color list items -->
<!-- invalid -red, localindex not supported, -->
<color name="color_invalid">#EE3232</color>
<!-- warning -red, localindex is corrupted, poi closed, osm_delete -->
<color name="color_warning">#EE3232</color>
<!-- normal state, localindex unknown, poi unknown, index_unknown -->
<color name="color_unknown">#C8C8C8</color>
<!-- good state, localindex loaded, poi_open, osm_create, index_ok -->
<color name="color_ok">#32CD32</color>
<!-- intermediate state - poi is going to be closed -->
<color name="color_intermediate">#FFDD00</color>
<!-- update good state, osm_modify, index_update -->
<color name="color_update">#0080FF</color>
<!-- Map colors, layers, special purpose consistency colors -->
<color name="pos_heading">#320000FF</color>
<!-- color name="pos_heading_night">#880000FF</color -->
<color name="pos_heading_night">#88536dfe</color>
<color name="pos_area">#280000FF</color>
<!-- color name="pos_area_night">#660000FF</color -->
<color name="pos_area_night">#66536dfe</color>
<color name="pos_around">#707CDC</color> <!-- family blue similar to above -->
<color name="gpx_track">#B4B319FF</color>
<color name="gpx_track_fluorescent">#B400FFFF</color>
<color name="nav_track">#CCaa0088</color>
<color name="nav_track_fluorescent">#CC00ddff</color>
<color name="transport_route_line">#CC2f7af5</color>
<color name="nav_arrow_distant">#C0C0C0</color>
<color name="nav_arrow">#FADE23</color>
<color name="nav_arrow_imminent">#2EFF00</color>
<color name="nav_point">#FA5050</color>
<color name="poi_background">#A0FF8000</color>
<color name="transport_stop">#960000FF</color>
<color name="transport_int">#9632C832</color>
<color name="transport_end">#96FF0000</color>
<color name="osmbug_opened">#C8FF0000</color> <!-- standard RED -->
<color name="osmbug_closed">#C800FF00</color> <!-- standard GREEN -->
<color name="osmbug_not_submitted">#C8FFFF00</color> <!-- standard YELLOW -->
<color name="shadow_color">#33888888</color>
<color name="sherpafy_selection">#ff33b5e5</color>
<color name="sherpafy_add_text">#b9b9b9</color>
<color name="spinner_list_background_light">#eeeeee</color>
<color name="spinner_list_background_dark">#303030</color>
<color name="inactive_item_orange">#ffc87f</color>
<color name="osmand_orange_dark">#e68200</color>
<color name="divider_color">#ccc</color>
<color name="color_dialog_buttons_light">#2f7af5</color>
<color name="color_dialog_buttons_dark">#ff8800</color>
<color name="dialog_inactive_text_color_dark">#78909c</color>
<!-- DownloadedRegionsLayer -->
<color name="region_uptodate">#5532C832</color>
<color name="region_backuped">#55FF8F00</color>
<color name="region_selected">#55FFFF00</color>
<color name="region_downloading">#44FF61FF</color>
<!-- Dialog Live Updates Settings -->
<color name="white_50_transparent">#8FFF</color>
<color name="white_80_transparent">#CFFF</color>
</resources>

View file

@ -2,5 +2,4 @@
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="list_content_padding">16dp</dimen>
</resources>

View file

@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="dialog_button_height">36dp</dimen>
<dimen name="undo_bottom_offset">15dp</dimen>
<dimen name="touch_slop">32dp</dimen>
<dimen name="list_item_height">50dp</dimen>
<dimen name="list_header_height">40dp</dimen>
<dimen name="dashboard_map_top_padding">240dp</dimen>
<dimen name="dashboard_land_width">360dp</dimen>
<dimen name="dashboard_map_toolbar">56dp</dimen>
<dimen name="dash_parking_height">78dp</dimen>
<dimen name="subHeaderPadding">2dp</dimen>
<dimen name="subHeaderMarginLeft">15dp</dimen>
<dimen name="showAllButtonMarginRight">14dp</dimen>
<dimen name="showAllButtonHeight">36dp</dimen>
<dimen name="dashFavIconSize">28dp</dimen>
<dimen name="dashFavIconMargin">12dp</dimen>
<dimen name="dashFavDirectionSize">10dp</dimen>
<dimen name="directionIconSize">14dp</dimen>
<dimen name="dashNoteIconSize">28dp</dimen>
<dimen name="dashPluginPadding">4dp</dimen>
<dimen name="dashPluginMargin">8dp</dimen>
<dimen name="dashSearchBtnHeight">90dp</dimen>
<dimen name="dashSearchPaddingTop">17dp</dimen>
<dimen name="dashSearchPaddingBot">11dp</dimen>
<dimen name="dashPadding">6dp</dimen>
<dimen name="dashCardMargin">4dp</dimen>
<dimen name="abp__shadow_height">4dp</dimen>
<dimen name="dashFABMargin">0dp</dimen>
<dimen name="list_content_padding">16dp</dimen>
<dimen name="list_header_padding">8dp</dimen>
<dimen name="list_header_top_margin">16dp</dimen>
<dimen name="list_header_settings_top_margin">10dp</dimen>
<dimen name="list_header_text_left_margin">12dp</dimen>
<dimen name="list_header_bottom_margin">8dp</dimen>
<dimen name="favorites_icon_right_margin">24dp</dimen>
<dimen name="local_index_check_right_margin">10dp</dimen>
<dimen name="favorites_icon_top_margin">13dp</dimen>
<dimen name="dialog_elements_vertical_margin">16dp</dimen>
<dimen name="dialog_content_margin">24dp</dimen>
<dimen name="dialog_content_bottom_margin">16dp</dimen>
<dimen name="local_size_height">34dp</dimen>
<dimen name="standard_icon_size">24dp</dimen>
<dimen name="gpx_small_icon_margin">3dp</dimen>
<dimen name="gpx_small_text_margin">14dp</dimen>
<dimen name="gpx_text_top_margin">6dp</dimen>
<dimen name="dashboard_parking_left_margin">16dp</dimen>
<dimen name="dashboard_parking_icon_size">48dp</dimen>
<!-- map buttons -->
<dimen name="map_trans_seek_size">80dp</dimen>
<dimen name="map_route_buttons_width">60dp</dimen>
<dimen name="map_route_buttons_height">54dp</dimen>
<dimen name="map_route_buttons_height_land">48dp</dimen>
<dimen name="map_mode_button_width">56dp</dimen>
<dimen name="map_address_height">40dp</dimen>
<dimen name="map_button_size">52dp</dimen>
<dimen name="map_small_button_size">44dp</dimen>
<dimen name="map_small_button_margin">5dp</dimen>
<dimen name="map_ruler_width">120dp</dimen>
<dimen name="map_ruler_bottom_margin">9dp</dimen>
<dimen name="map_alarm_size">78dp</dimen>
<dimen name="map_alarm_bottom_margin">87dp</dimen>
<dimen name="map_alarm_bottom_margin_land">57dp</dimen>
<dimen name="map_button_shadow_height">85dp</dimen>
<dimen name="map_button_shadow_width">56dp</dimen>
<dimen name="map_button_shadow_margin">4dp</dimen>
<dimen name="map_widget_icon">24dp</dimen>
<dimen name="map_widget_height">32dp</dimen>
<dimen name="map_widget_image">80dp</dimen>
<dimen name="map_button_spacing">11dp</dimen>
<dimen name="map_button_spacing_land">6dp</dimen>
<dimen name="map_button_margin">6dp</dimen>
<dimen name="map_routing_progress_width">100dp</dimen>
<dimen name="map_button_inset_shadow">2dp</dimen>
<dimen name="map_button_inset">2dp</dimen>
<dimen name="map_button_rect_rad">3dp</dimen>
<dimen name="map_button_stroke">1dp</dimen>
<dimen name="map_button_stroke_dark">1dp</dimen>
<dimen name="map_route_planning_land_width">320dp</dimen>
<dimen name="map_route_planning_land_width_minus_shadow">306dp</dimen>
<dimen name="map_route_planning_max_height">330dp</dimen>
<dimen name="map_minwidth_widget">100dp</dimen>
<dimen name="map_widget_text_size">23sp</dimen>
<dimen name="map_widget_text_size_small">15sp</dimen>
<dimen name="map_button_text_size">18sp</dimen>
<dimen name="map_alarm_text_size">25sp</dimen>
<dimen name="map_widget_text_bottom_margin">1sp</dimen>
<dimen name="map_widget_text_small_bottom_margin">3sp</dimen>
<dimen name="map_widget_icon_margin">2dp</dimen>
<dimen name="dash_margin">2dp</dimen>
<dimen name="dash_margin_h">6dp</dimen>
<!-- ContextMenu -->
<dimen name="context_menu_top_shadow_h">20dp</dimen>
<dimen name="context_menu_icon_top_padding">17dp</dimen>
<dimen name="context_menu_first_line_top_margin">14dp</dimen>
<dimen name="context_menu_first_line_bottom_margin">16dp</dimen>
<dimen name="context_menu_second_line_top_margin">4dp</dimen>
<dimen name="context_menu_top_right_button_min_width">76dp</dimen>
<dimen name="context_menu_button_padding_x">10dp</dimen>
<dimen name="context_menu_buttons_top_margin">-16dp</dimen>
<dimen name="context_menu_buttons_padding_bottom">4dp</dimen>
<dimen name="context_menu_progress_min_height">54dp</dimen>
<dimen name="context_menu_progress_cancel_button_size">44dp</dimen>
<dimen name="context_menu_action_buttons_h">54dp</dimen>
<dimen name="fab_size_with_shadow">62dp</dimen>
<dimen name="fab_margin_right">12dp</dimen>
<!-- TextSizes -->
<dimen name="default_list_text_size_large">19sp</dimen>
<dimen name="default_list_text_size">16sp</dimen>
<dimen name="default_desc_text_size">14sp</dimen>
<dimen name="default_sub_text_size">12sp</dimen>
<dimen name="welcome_header_text_size">23sp</dimen>
<dimen name="dialog_header_text_size">20sp</dimen>
</resources>

View file

@ -1,5 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="shared_string_search">Search</string>
<string name="yard">yd</string>
<string name="foot">ft</string>
<string name="mile">mi</string>
<string name="km">km</string>
<string name="m">m</string>
<string name="nm">nmi</string>
<string name="min_mile">min/m</string>
<string name="min_km">min/km</string>
<string name="nm_h">nmi/h</string>
<string name="m_s">m/s</string>
<string name="km_h">km/h</string>
<string name="mile_per_hour">mph</string>
<string name="si_kmh">Kilometers per hour</string>
<string name="si_mph">Miles per hour</string>
<string name="si_m_s">Meters per second</string>
<string name="si_min_km">Minutes per kilometer</string>
<string name="si_min_m">Minutes per mile</string>
<string name="si_nm_h">Nautical miles per hour (knot)</string>
<string name="si_mi_feet">Miles/feet</string>
<string name="si_mi_yard">Miles/yards</string>
<string name="si_km_m">Kilometers/meters</string>
<string name="si_nm">Nautical miles</string>
<string name="si_mi_meters">Miles/meters</string>
<string name="shared_string_hour_short">h</string>
<string name="shared_string_minute_short">min</string>
<string name="install_maps_title">Install maps</string>
<string name="install_maps_desc">You do not have maps in the OsmAnd application. Please download map(s) first and restart the Sample.\n\nDo not forget to set OsmAnd General settings > Data storage folder to Shared memory.</string>
<string name="shared_string_cancel">Cancel</string>

View file

@ -2,10 +2,61 @@
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowBackground">@color/windowBackgroundColor</item>
<item name="android:colorBackground">@color/windowBackgroundColor</item>
<item name="toolbar_theme">@style/AppTheme.Toolbar</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="searchbar_text">@color/searchbar_text_light</item>
<item name="searchbar_text_hint">@color/searchbar_text_hint_light</item>
<item name="list_divider">@color/list_divider_dark</item>
<item name="expandable_category_color">?android:attr/colorBackground</item>
<item name="bottomToolBarColor">@color/tool_bar_color_light</item>
<item name="android:windowContentOverlay">@null</item>
<item name="actionModeBackground">@color/actionbar_light_color</item>
<item name="dashboard_divider">@color/dashboard_divider_light</item>
<item name="divider_color">@color/divider_color</item>
<item name="ctx_menu_info_view_bg">@color/ctx_menu_info_view_bg_light</item>
<item name="search_background">@color/search_background_dark</item>
<item name="actionMenuTextColor">@color/color_white</item>
<item name="expandable_list_background">@color/list_item_light</item>
<item name="osmo_header_background">@color/osmo_header_light</item>
<item name="dashboard_subheader_text_color">@color/dashboard_subheader_text_light</item>
<item name="dashboard_general_button_text_color">
@color/dashboard_general_button_text_light
</item>
<item name="android:textColorPrimary">@color/color_black</item>
<item name="spinnerItemTextColor">@color/color_black</item>
<item name="spinnerListBackground">@color/spinner_list_background_light</item>
<item name="colorButtonNormal">@color/color_white</item>
<item name="android:actionModeBackground">@color/actionbar_light_color</item>
<item name="android:actionMenuTextColor">@color/color_white</item>
<item name="dialog_inactive_text_color">@color/icon_color_light</item>
<item name="secondary_icon_color">@color/icon_color_light</item>
<item name="android:textColorSecondary">@color/icon_color</item>
<item name="contextMenuButtonColor">@color/map_widget_blue</item>
<item name="color_dialog_buttons">@color/color_dialog_buttons_light</item>
</style>
<style name="AppTheme.Toolbar">
<item name="android:textColorPrimary">@color/color_white</item>
<item name="android:textColorSecondary">@color/color_white</item>
</style>
<style name="Dialog_Fullscreen" parent="android:Theme">
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@color/color_transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
<style name="OsmandListView" parent="@android:style/Widget.ListView">
</style>
</resources>

View file

@ -0,0 +1,215 @@
package net.osmand;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.PointF;
import android.os.Build;
import android.os.IBinder;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewParent;
import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import net.osmand.core.samples.android.sample1.R;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static android.util.TypedValue.COMPLEX_UNIT_DIP;
public class AndroidUtils {
/**
* @param context
* @return true if Hardware keyboard is available
*/
public static boolean isHardwareKeyboardAvailable(Context context) {
return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS;
}
public static void softKeyboardDelayed(final View view) {
view.post(new Runnable() {
@Override
public void run() {
if (!isHardwareKeyboardAvailable(view.getContext())) {
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
}
}
}
});
}
public static void hideSoftKeyboard(final Activity activity, final View input) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
if (inputMethodManager != null) {
if (input != null) {
IBinder windowToken = input.getWindowToken();
if (windowToken != null) {
inputMethodManager.hideSoftInputFromWindow(windowToken, 0);
}
}
}
}
public static String formatDate(Context ctx, long time) {
return DateFormat.getDateFormat(ctx).format(new Date(time));
}
public static String formatDateTime(Context ctx, long time) {
Date d = new Date(time);
return DateFormat.getDateFormat(ctx).format(d) +
" " + DateFormat.getTimeFormat(ctx).format(d);
}
public static String formatTime(Context ctx, long time) {
return DateFormat.getTimeFormat(ctx).format(new Date(time));
}
public static View findParentViewById(View view, int id) {
ViewParent viewParent = view.getParent();
while (viewParent != null && viewParent instanceof View) {
View parentView = (View)viewParent;
if (parentView.getId() == id)
return parentView;
viewParent = parentView.getParent();
}
return null;
}
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public static void setBackground(Context ctx, View view, boolean night, int lightResId, int darkResId) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
view.setBackground(ctx.getResources().getDrawable(night ? darkResId : lightResId,
ctx.getTheme()));
} else {
view.setBackgroundDrawable(ctx.getResources().getDrawable(night ? darkResId : lightResId));
}
}
public static void setBackgroundColor(Context ctx, View view, boolean night, int lightResId, int darkResId) {
view.setBackgroundColor(ctx.getResources().getColor(night ? darkResId : lightResId));
}
public static void setListItemBackground(Context ctx, View view, boolean night) {
setBackgroundColor(ctx, view, night, R.color.bg_color_light, R.color.bg_color_dark);
}
public static void setListBackground(Context ctx, View view, boolean night) {
setBackgroundColor(ctx, view, night, R.color.ctx_menu_info_view_bg_light, R.color.ctx_menu_info_view_bg_dark);
}
public static void setTextPrimaryColor(Context ctx, TextView textView, boolean night) {
textView.setTextColor(night ?
ctx.getResources().getColor(R.color.primary_text_dark)
: ctx.getResources().getColor(R.color.primary_text_light));
}
public static void setTextSecondaryColor(Context ctx, TextView textView, boolean night) {
textView.setTextColor(night ?
ctx.getResources().getColor(R.color.secondary_text_dark)
: ctx.getResources().getColor(R.color.secondary_text_light));
}
public static void setHintTextSecondaryColor(Context ctx, TextView textView, boolean night) {
textView.setHintTextColor(night ?
ctx.getResources().getColor(R.color.secondary_text_dark)
: ctx.getResources().getColor(R.color.secondary_text_light));
}
public static int dpToPx(Context ctx, float dp) {
Resources r = ctx.getResources();
return (int) TypedValue.applyDimension(
COMPLEX_UNIT_DIP,
dp,
r.getDisplayMetrics()
);
}
public static int getStatusBarHeight(Context ctx) {
int result = 0;
int resourceId = ctx.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = ctx.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
public static int getScreenHeight(Activity activity) {
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
return dm.heightPixels;
}
public static boolean isValidEmail(CharSequence target) {
return !TextUtils.isEmpty(target) && android.util.Patterns.EMAIL_ADDRESS.matcher(target).matches();
}
public static String getFileAsString(File file) {
try {
FileInputStream fin = new FileInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(fin, "UTF-8"));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
if (sb.length() > 0) {
sb.append("\n");
}
sb.append(line);
}
reader.close();
fin.close();
return sb.toString();
} catch (Exception e) {
return null;
}
}
public static PointF centroidForPoly(PointF[] points) {
float centroidX = 0, centroidY = 0;
for (PointF point : points) {
centroidX += point.x / points.length;
centroidY += point.y / points.length;
}
return new PointF(centroidX, centroidY);
}
public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
return (o1.getValue()).compareTo(o2.getValue());
}
});
Map<K, V> result = new LinkedHashMap<>();
for (Map.Entry<K, V> entry : list) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}
}

View file

@ -1,16 +1,28 @@
package net.osmand.core.samples.android.sample1;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import net.osmand.core.android.CoreResourcesFromAndroidAssets;
import gnu.trove.map.hash.TLongObjectHashMap;
public class IconsCache {
private TLongObjectHashMap<Drawable> drawable = new TLongObjectHashMap<>();
private TLongObjectHashMap<Drawable> osmandDrawable = new TLongObjectHashMap<>();
private SampleApplication app;
private CoreResourcesFromAndroidAssets assets;
private float displayDensityFactor;
public IconsCache(CoreResourcesFromAndroidAssets assets) {
public IconsCache(CoreResourcesFromAndroidAssets assets, SampleApplication app) {
this.assets = assets;
this.app = app;
}
public float getDisplayDensityFactor() {
@ -24,4 +36,154 @@ public class IconsCache {
public Drawable getMapIcon(String name) {
return assets.getIcon("map/icons/" + name + ".png", displayDensityFactor);
}
private Drawable getDrawable(@DrawableRes int resId, @ColorRes int clrId) {
long hash = ((long)resId << 31L) + clrId;
Drawable d = drawable.get(hash);
if (d == null) {
d = ContextCompat.getDrawable(app, resId);
d = DrawableCompat.wrap(d);
d.mutate();
if (clrId != 0) {
DrawableCompat.setTint(d, ContextCompat.getColor(app, clrId));
}
drawable.put(hash, d);
}
return d;
}
private Drawable getPaintedDrawable(@DrawableRes int resId, @ColorInt int color){
long hash = ((long)resId << 31L) + color;
Drawable d = drawable.get(hash);
if(d == null) {
d = ContextCompat.getDrawable(app, resId);
d = DrawableCompat.wrap(d);
d.mutate();
DrawableCompat.setTint(d, color);
drawable.put(hash, d);
}
return d;
}
public Drawable getPaintedIcon(@DrawableRes int id, @ColorInt int color){
return getPaintedDrawable(id, color);
}
public Drawable getIcon(@DrawableRes int id, @ColorRes int colorId) {
return getDrawable(id, colorId);
}
public Drawable getIcon(@DrawableRes int backgroundId, @DrawableRes int id, @ColorRes int colorId) {
Drawable b = getDrawable(backgroundId, 0);
Drawable f = getDrawable(id, colorId);
Drawable[] layers = new Drawable[2];
layers[0] = b;
layers[1] = f;
return new LayerDrawable(layers);
}
public Drawable getThemedIcon(@DrawableRes int id) {
return getDrawable(id, R.color.icon_color);
}
public Drawable getIcon(@DrawableRes int id) {
return getDrawable(id, 0);
}
public Drawable getIcon(@DrawableRes int id, boolean light) {
return getDrawable(id, light ? R.color.icon_color : 0);
}
// Osmand resources
private Drawable getOsmandDrawable(int resId, @ColorRes int clrId) {
long hash = ((long)resId << 31L) + clrId;
Drawable d = osmandDrawable.get(hash);
if (d == null) {
d = OsmandResources.getDrawable(resId);
if (d != null) {
d = DrawableCompat.wrap(d);
d.mutate();
if (clrId != 0) {
DrawableCompat.setTint(d, ContextCompat.getColor(app, clrId));
}
osmandDrawable.put(hash, d);
}
}
return d;
}
private Drawable getPaintedOsmandDrawable(int resId, @ColorInt int color){
long hash = ((long)resId << 31L) + color;
Drawable d = osmandDrawable.get(hash);
if(d == null) {
d = OsmandResources.getDrawable(resId);
if (d != null) {
d = DrawableCompat.wrap(d);
d.mutate();
DrawableCompat.setTint(d, color);
osmandDrawable.put(hash, d);
}
}
return d;
}
public Drawable getPaintedIcon(String osmandId, @ColorInt int color){
int id = OsmandResources.getDrawableId(osmandId);
if (id != 0) {
return getPaintedOsmandDrawable(id, color);
}
return null;
}
public Drawable getOsmandIcon(@DrawableRes int id, @ColorRes int colorId) {
return getOsmandDrawable(id, colorId);
}
public Drawable getIcon(String osmandId, @ColorRes int colorId) {
int id = OsmandResources.getDrawableId(osmandId);
if (id != 0) {
return getOsmandDrawable(id, colorId);
}
return null;
}
public Drawable getIcon(String osmandBackgroundId, String osmandId, @ColorRes int colorId) {
int backgroundId = OsmandResources.getDrawableId(osmandBackgroundId);
int id = OsmandResources.getDrawableId(osmandId);
if (backgroundId != 0 && id != 0) {
Drawable b = getOsmandDrawable(backgroundId, 0);
Drawable f = getOsmandDrawable(id, colorId);
Drawable[] layers = new Drawable[2];
layers[0] = b;
layers[1] = f;
return new LayerDrawable(layers);
}
return null;
}
public Drawable getThemedIcon(String osmandId) {
int id = OsmandResources.getDrawableId(osmandId);
if (id != 0) {
return getOsmandDrawable(id, R.color.icon_color);
}
return null;
}
public Drawable getIcon(String osmandId) {
int id = OsmandResources.getDrawableId(osmandId);
if (id != 0) {
return getOsmandDrawable(id, 0);
}
return null;
}
public Drawable getIcon(String osmandId, boolean light) {
int id = OsmandResources.getDrawableId(osmandId);
if (id != 0) {
return getOsmandDrawable(id, light ? R.color.icon_color : 0);
}
return null;
}
}

View file

@ -5,7 +5,6 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
@ -14,8 +13,8 @@ import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatDialogFragment;
import android.view.View;
public class InstallOsmAndAppDialog extends AppCompatDialogFragment {
private static final String TAG = "InstallOsmAndAppDialog";
public class InstallOsmandAppDialog extends AppCompatDialogFragment {
private static final String TAG = "InstallOsmandAppDialog";
private static final String OSMAND_PLUS_PACKAGE_NAME = "net.osmand.plus";
private static final String OSMAND_PACKAGE_NAME = "net.osmand";
private static boolean wasChecked = false;
@ -70,7 +69,7 @@ public class InstallOsmAndAppDialog extends AppCompatDialogFragment {
wasChecked = true;
if (!SampleUtils.isPackageInstalled(OSMAND_PACKAGE_NAME, ctx)
&& !SampleUtils.isPackageInstalled(OSMAND_PLUS_PACKAGE_NAME, ctx)) {
new InstallOsmAndAppDialog().show(manager, TAG);
new InstallOsmandAppDialog().show(manager, TAG);
return true;
} else {
return false;

View file

@ -7,38 +7,24 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager;
import android.graphics.PointF;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorListener;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.core.android.AtlasMapRendererView;
import net.osmand.core.jni.IMapLayerProvider;
import net.osmand.core.jni.IMapStylesCollection;
import net.osmand.core.jni.IQueryController;
import net.osmand.core.jni.ISearch;
import net.osmand.core.jni.Logger;
import net.osmand.core.jni.MapObjectsSymbolsProvider;
import net.osmand.core.jni.MapPresentationEnvironment;
@ -46,34 +32,20 @@ import net.osmand.core.jni.MapPrimitivesProvider;
import net.osmand.core.jni.MapPrimitiviser;
import net.osmand.core.jni.MapRasterLayerProvider_Software;
import net.osmand.core.jni.MapStylesCollection;
import net.osmand.core.jni.NullablePointI;
import net.osmand.core.jni.ObfMapObjectsProvider;
import net.osmand.core.jni.ObfsCollection;
import net.osmand.core.jni.OsmAndCoreJNI;
import net.osmand.core.jni.PointI;
import net.osmand.core.jni.QIODeviceLogSink;
import net.osmand.core.jni.ResolvedMapStyle;
import net.osmand.core.jni.ReverseGeocoder;
import net.osmand.core.jni.RoadLocator;
import net.osmand.core.jni.Utilities;
import net.osmand.core.samples.android.sample1.MultiTouchSupport.MultiTouchZoomListener;
import net.osmand.core.samples.android.sample1.adapters.SearchListAdapter;
import net.osmand.core.samples.android.sample1.adapters.SearchListItem;
import net.osmand.core.samples.android.sample1.search.QuickSearchDialogFragment;
import net.osmand.data.LatLon;
import net.osmand.search.SearchUICore;
import net.osmand.search.SearchUICore.SearchResultCollection;
import net.osmand.search.core.ObjectType;
import net.osmand.search.core.SearchResult;
import net.osmand.search.core.SearchSettings;
import net.osmand.util.MapUtils;
import java.io.File;
import java.io.FilenameFilter;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "OsmAndCoreSample";
@ -95,6 +67,7 @@ public class MainActivity extends AppCompatActivity {
private AtlasMapRendererView mapView;
private TextView textZoom;
private ImageButton searchButton;
private ImageButton azimuthNorthButton;
private GestureDetector gestureDetector;
@ -104,18 +77,6 @@ public class MainActivity extends AppCompatActivity {
private float elevationAngle;
private MultiTouchSupport multiTouchSupport;
private SearchUICore searchUICore;
private EditText searchEditText;
private ImageView searchIcon;
private ProgressBar progressBar;
private final static int MAX_SEARCH_RESULTS_CORE = 0;
private final static int MAX_SEARCH_RESULTS_IU = 150;
private ListView searchListView;
private SearchListAdapter adapter;
private String queryText = "";
private boolean noMapsFound;
// Germany
@ -136,14 +97,8 @@ public class MainActivity extends AppCompatActivity {
private static final String PREF_MAP_ZOOM = "MAP_ZOOM";
private static final String PREF_MAP_ELEVATION_ANGLE = "MAP_ELEVATION_ANGLE";
public static final String LANGUAGE;
static {
String langCode = Locale.getDefault().getLanguage();
if (langCode.isEmpty()) {
langCode = "en";
}
LANGUAGE = langCode;
public SampleApplication getMyApplication() {
return (SampleApplication) getApplication();
}
@Override
@ -179,8 +134,16 @@ public class MainActivity extends AppCompatActivity {
mapView = (AtlasMapRendererView) findViewById(R.id.mapRendererView);
textZoom = (TextView) findViewById(R.id.text_zoom);
azimuthNorthButton = (ImageButton) findViewById(R.id.map_azimuth_north_button);
searchButton = (ImageButton) findViewById(R.id.search_button);
searchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showQuickSearch(ShowQuickSearchMode.NEW_IF_EXPIRED, false);
}
});
azimuthNorthButton = (ImageButton) findViewById(R.id.map_azimuth_north_button);
azimuthNorthButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -237,7 +200,7 @@ public class MainActivity extends AppCompatActivity {
displayDensityFactor,
1.0f,
1.0f,
LANGUAGE);
SampleApplication.LANGUAGE);
//mapPresentationEnvironment->setSettings(configuration.styleSettings);
mapPrimitiviser = new MapPrimitiviser(
mapPresentationEnvironment);
@ -261,94 +224,7 @@ public class MainActivity extends AppCompatActivity {
app.getIconsCache().setDisplayDensityFactor(displayDensityFactor);
setupSearch();
searchEditText = (EditText) findViewById(R.id.searchEditText);
searchEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
String newQueryText = s.toString();
if (!queryText.equalsIgnoreCase(newQueryText)) {
queryText = newQueryText;
showProgressBar();
runSearch();
}
}
});
searchEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
net.osmand.core.jni.LatLon latLon = Utilities.convert31ToLatLon(target31);
SearchSettings settings = searchUICore.getPhrase().getSettings().setOriginalLocation(
new LatLon(latLon.getLatitude(), latLon.getLongitude()));
settings = settings.setLang(LANGUAGE, false);
searchUICore.updateSettings(settings);
adapter.setLocation(new LatLon(latLon.getLatitude(), latLon.getLongitude()));
if (isSearchListHidden()) {
showSearchList();
if (adapter.getCount() > 0) {
adapter.updateDistance(latLon.getLatitude(), latLon.getLongitude());
adapter.notifyDataSetChanged();
} else {
runSearch();
}
}
}
}
});
searchIcon = (ImageView) findViewById(R.id.searchIcon);
progressBar = (ProgressBar) findViewById(R.id.searchProgressBar);
ImageButton clearButton = (ImageButton) findViewById(R.id.clearButton);
clearButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
searchEditText.setText("");
adapter.clear();
adapter.notifyDataSetChanged();
hideSearchList();
}
});
searchListView = (ListView) findViewById(android.R.id.list);
adapter = new SearchListAdapter(this);
searchListView.setAdapter(adapter);
searchListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
SearchListItem item = adapter.getItem(position);
SearchResult sr = item.getSearchResult();
boolean updateEditText = true;
if (sr.objectType == ObjectType.POI
|| sr.objectType == ObjectType.LOCATION
|| sr.objectType == ObjectType.HOUSE
|| sr.objectType == ObjectType.FAVORITE
|| sr.objectType == ObjectType.RECENT_OBJ
|| sr.objectType == ObjectType.WPT
|| sr.objectType == ObjectType.STREET_INTERSECTION) {
hideSearchList();
mapView.requestFocus();
updateEditText = false;
}
completeQueryWithObject(item.getSearchResult(), updateEditText);
}
});
if (!InstallOsmAndAppDialog.showIfNeeded(getSupportFragmentManager(), this)
if (!InstallOsmandAppDialog.showIfNeeded(getSupportFragmentManager(), this)
&& externalStoragePermissionGranted) {
checkMapsInstalled();
}
@ -381,41 +257,6 @@ public class MainActivity extends AppCompatActivity {
}
}
private void setupSearch() {
final SampleApplication app = getSampleApplication();
List<BinaryMapIndexReader> files = new ArrayList<>();
File file = new File(app.getAbsoluteAppPath());
if (file.exists() && file.listFiles() != null) {
for (File obf : file.listFiles()) {
if (!obf.isDirectory() && obf.getName().endsWith(".obf")) {
try {
BinaryMapIndexReader bmir = new BinaryMapIndexReader(new RandomAccessFile(obf, "r"), obf);
files.add(bmir);
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
}
searchUICore = new SearchUICore(app.getPoiTypes(), LANGUAGE, false);
searchUICore.getSearchSettings().setOfflineIndexes(Arrays.asList(files.toArray(new BinaryMapIndexReader[files.size()])));
searchUICore.init();
searchUICore.setOnResultsComplete(new Runnable() {
@Override
public void run() {
app.runInUIThread(new Runnable() {
@Override
public void run() {
hideProgressBar();
updateSearchResult(searchUICore.getCurrentSearchResult(), true);
}
});
}
});
}
@Override
protected void onResume() {
super.onResume();
@ -439,7 +280,7 @@ public class MainActivity extends AppCompatActivity {
return (SampleApplication) getApplication();
}
private void showOnMap(LatLon latLon, int zoom) {
public void showOnMap(LatLon latLon, int zoom) {
if (latLon != null) {
PointI target = Utilities.convertLatLonTo31(
new net.osmand.core.jni.LatLon(latLon.getLatitude(), latLon.getLongitude()));
@ -448,51 +289,17 @@ public class MainActivity extends AppCompatActivity {
}
}
private PointI getScreenCenter31() {
public PointI getScreenCenter31() {
PointI point = new PointI();
mapView.getLocationFromScreenPoint(new PointI(mapView.getWidth() / 2, mapView.getHeight() / 2), point);
return point;
}
private void showProgressBar() {
searchIcon.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
}
private void hideProgressBar() {
progressBar.setVisibility(View.GONE);
searchIcon.setVisibility(View.VISIBLE);
}
private boolean isSearchListHidden() {
return searchListView.getVisibility() != View.VISIBLE;
}
private void showSearchList() {
if (isSearchListHidden()) {
ViewCompat.setAlpha(searchListView, 0f);
searchListView.setVisibility(View.VISIBLE);
ViewCompat.animate(searchListView).alpha(1f).setListener(null);
}
}
private void hideSearchList() {
ViewCompat.animate(searchListView).alpha(0f).setListener(new ViewPropertyAnimatorListener() {
@Override
public void onAnimationStart(View view) {
}
@Override
public void onAnimationEnd(View view) {
searchListView.setVisibility(View.GONE);
}
@Override
public void onAnimationCancel(View view) {
searchListView.setVisibility(View.GONE);
}
});
public LatLon getScreenCenter() {
PointI point = new PointI();
mapView.getLocationFromScreenPoint(new PointI(mapView.getWidth() / 2, mapView.getHeight() / 2), point);
net.osmand.core.jni.LatLon jniLatLon = Utilities.convert31ToLatLon(point);
return new LatLon(jniLatLon.getLatitude(), jniLatLon.getLongitude());
}
public void saveMapState() {
@ -565,126 +372,6 @@ public class MainActivity extends AppCompatActivity {
|| gestureDetector.onTouchEvent(event);
}
private void runSearch() {
runSearch(queryText);
}
private void runSearch(String text) {
SearchSettings settings = searchUICore.getPhrase().getSettings();
if (settings.getRadiusLevel() != 1) {
searchUICore.updateSettings(settings.setRadiusLevel(1));
}
searchUICore.search(text, null);
SearchResultCollection c = searchUICore.search(text, null);
updateSearchResult(c, false);
}
private void completeQueryWithObject(SearchResult sr, boolean updateEditText) {
if (sr.location != null) {
showOnMap(sr.location, sr.preferredZoom);
}
searchUICore.selectSearchResult(sr);
String txt = searchUICore.getPhrase().getText(true);
if (updateEditText) {
queryText = txt;
searchEditText.setText(txt);
searchEditText.setSelection(txt.length());
}
searchUICore.search(txt, null);
}
private void updateSearchResult(SearchResultCollection res, boolean addMore) {
SampleApplication app = getSampleApplication();
if (res.getCurrentSearchResults().size() > 0) {
List<SearchListItem> rows = new ArrayList<>();
for (final SearchResult sr : res.getCurrentSearchResults()) {
int count = 30;
/*
if(addMore) {
JMenuItem mi = new JMenuItem();
mi.setText("Results " + res.getCurrentSearchResults().size() + ", radius " + res.getPhrase().getRadiusLevel()+
" (show more...)");
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SearchSettings settings = searchUICore.getPhrase().getSettings();
searchUICore.updateSettings(settings.setRadiusLevel(settings.getRadiusLevel() + 1));
searchUICore.search(statusField.getText(), null);
updateSearchResult(statusField, new SearchResultCollection(), false);
}
});
popup.add(mi);
}
*/
count--;
if (count == 0) {
// break;
}
//LatLon location = res.getPhrase().getLastTokenLocation();
//String locationString = "";
//if (sr.location != null) {
// locationString = ((int) MapUtils.getDistance(location, sr.location)) + " m";
//}
//mi.setText(sr.localeName + " [" + sr.objectType + "] " + locationString);
SearchListItem listItem = new SearchListItem(app, sr);
if (sr.location != null) {
LatLon location = res.getPhrase().getLastTokenLocation();
listItem.setDistance(MapUtils.getDistance(location, sr.location));
}
rows.add(listItem);
}
updateListAdapter(rows);
showSearchList();
}
}
private void updateListAdapter(List<SearchListItem> listItems) {
adapter.setListItems(listItems);
if (adapter.getCount() > 0) {
searchListView.setSelection(0);
}
}
public void geocode(@NonNull PointI point31) {
new AsyncTask<PointI, Void, String>() {
@Override
protected String doInBackground(PointI... params) {
final String[] resultString = {null};
ReverseGeocoder geocoder = new ReverseGeocoder(obfsCollection, roadLocator);
final ReverseGeocoder.Criteria criteria = new ReverseGeocoder.Criteria();
criteria.setPosition31(new NullablePointI(params[0]));
ISearch.INewResultEntryCallback geocoderResultCallback = new ISearch.INewResultEntryCallback() {
@Override
public void method(ISearch.Criteria criteria, ISearch.IResultEntry resultEntry) {
ReverseGeocoderResultEntry result = new ReverseGeocoderResultEntry(resultEntry);
resultString[0] = result.toString();
}
};
geocoder.performSearch(criteria, geocoderResultCallback.getBinding(), new IQueryController() {
@Override
public boolean isAborted() {
return false;
}
});
return resultString[0];
}
@Override
protected void onPostExecute(String s) {
Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
}
}.execute(point31);
}
private class MapViewOnGestureListener extends SimpleOnGestureListener {
@Override
@ -796,10 +483,68 @@ public class MainActivity extends AppCompatActivity {
}
}
private class ReverseGeocoderResultEntry extends ReverseGeocoder.ResultEntry {
protected ReverseGeocoderResultEntry(ISearch.IResultEntry resultEntry) {
super(OsmAndCoreJNI.ReverseGeocoder_ResultEntry_SWIGUpcast(ISearch.IResultEntry.getCPtr(resultEntry)), false);
public void showQuickSearch(double latitude, double longitude) {
hideContextMenu();
QuickSearchDialogFragment fragment = getQuickSearchDialogFragment();
if (fragment != null) {
fragment.dismiss();
//refreshMap();
}
QuickSearchDialogFragment.showInstance(this, "", null, true, new LatLon(latitude, longitude));
}
public void showQuickSearch(Object object) {
hideContextMenu();
QuickSearchDialogFragment fragment = getQuickSearchDialogFragment();
if (fragment != null) {
fragment.dismiss();
//refreshMap();
}
QuickSearchDialogFragment.showInstance(this, "", object, true, null);
}
public void showQuickSearch(ShowQuickSearchMode mode, boolean showCategories) {
hideContextMenu();
QuickSearchDialogFragment fragment = getQuickSearchDialogFragment();
if (fragment != null) {
if (mode == ShowQuickSearchMode.NEW || (mode == ShowQuickSearchMode.NEW_IF_EXPIRED && fragment.isExpired())) {
fragment.dismiss();
QuickSearchDialogFragment.showInstance(this, "", null, showCategories, null);
} else {
fragment.show();
}
//refreshMap();
} else {
QuickSearchDialogFragment.showInstance(this, "", null, showCategories, null);
}
}
public void closeQuickSearch() {
QuickSearchDialogFragment fragment = getQuickSearchDialogFragment();
if (fragment != null) {
fragment.closeSearch();
//refreshMap();
}
}
public QuickSearchDialogFragment getQuickSearchDialogFragment() {
Fragment fragment = getSupportFragmentManager().findFragmentByTag(QuickSearchDialogFragment.TAG);
return fragment != null && !fragment.isDetached() && !fragment.isRemoving() ? (QuickSearchDialogFragment) fragment : null;
}
private void hideContextMenu() {
/* todo
if (mapContextMenu.isVisible()) {
mapContextMenu.hide();
} else if (mapContextMenu.getMultiSelectionMenu().isVisible()) {
mapContextMenu.getMultiSelectionMenu().hide();
}
*/
}
public enum ShowQuickSearchMode {
NEW,
NEW_IF_EXPIRED,
CURRENT,
}
}

View file

@ -0,0 +1,82 @@
package net.osmand.core.samples.android.sample1;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
public class OsmandResources {
private static Resources osmandResources;
private static String packageName;
public static void init(Context ctx) {
String packageName = "net.osmand";
try {
osmandResources = ctx.getPackageManager().getResourcesForApplication(packageName);
} catch (PackageManager.NameNotFoundException e) {
//ignore
}
if (osmandResources == null) {
packageName = "net.osmand.plus";
try {
osmandResources = ctx.getPackageManager().getResourcesForApplication(packageName);
} catch (PackageManager.NameNotFoundException e) {
//ignore
}
}
if (osmandResources == null) {
packageName = "net.osmand.dev";
try {
osmandResources = ctx.getPackageManager().getResourcesForApplication(packageName);
} catch (PackageManager.NameNotFoundException e) {
//ignore
}
}
if (osmandResources != null) {
OsmandResources.packageName = packageName;
}
}
public static Resources getOsmandResources() {
return osmandResources;
}
public static String getString(String id) {
if (osmandResources != null) {
int resolvedId = osmandResources.getIdentifier(id, "string", packageName);
return osmandResources.getString(resolvedId);
}
return null;
}
public static String getString(String id, Object... formatArgs) {
if (osmandResources != null) {
int resolvedId = osmandResources.getIdentifier(id, "string", packageName);
return osmandResources.getString(resolvedId, formatArgs);
}
return null;
}
public static Drawable getDrawable(String id) {
if (osmandResources != null) {
int resolvedId = osmandResources.getIdentifier(id, "drawable", packageName);
return osmandResources.getDrawable(resolvedId);
}
return null;
}
public static Drawable getDrawable(int id) {
if (osmandResources != null) {
return osmandResources.getDrawable(id);
}
return null;
}
public static int getDrawableId(String id) {
if (osmandResources != null) {
return osmandResources.getIdentifier(id, "drawable", packageName);
}
return 0;
}
}

View file

@ -2,7 +2,10 @@ package net.osmand.core.samples.android.sample1;
import android.Manifest;
import android.app.Application;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.os.Handler;
import android.support.v4.content.ContextCompat;
@ -11,32 +14,58 @@ import net.osmand.core.android.CoreResourcesFromAndroidAssets;
import net.osmand.core.android.NativeCore;
import net.osmand.core.jni.LogSeverityLevel;
import net.osmand.core.jni.Logger;
import net.osmand.core.samples.android.sample1.SampleFormatter.MetricsConstants;
import net.osmand.core.samples.android.sample1.SampleFormatter.SpeedConstants;
import net.osmand.core.samples.android.sample1.search.QuickSearchHelper;
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.MapPoiTypes;
import java.io.File;
import java.lang.reflect.Field;
import java.util.Locale;
import static net.osmand.core.samples.android.sample1.data.PointDescription.FORMAT_DEGREES;
public class SampleApplication extends Application {
public static final int PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 5 ;
private CoreResourcesFromAndroidAssets assetsCustom;
private MapPoiTypes poiTypes;
private IconsCache iconsCache;
Handler uiHandler;
private Handler uiHandler;
private long lastTimeInternetConnectionChecked = 0;
private boolean internetConnectionAvailable = true;
private int coordinatesFormat = FORMAT_DEGREES;
private MetricsConstants metricsConstants = MetricsConstants.KILOMETERS_AND_METERS;
private SpeedConstants speedConstants = SpeedConstants.KILOMETERS_PER_HOUR;
private SampleLocationProvider locationProvider;
private QuickSearchHelper searchUICore;
public static final String LANGUAGE;
static {
String langCode = Locale.getDefault().getLanguage();
if (langCode.isEmpty()) {
langCode = "en";
}
LANGUAGE = langCode;
}
@Override
public void onCreate()
{
public void onCreate() {
super.onCreate();
OsmandResources.init(this);
locationProvider = new SampleLocationProvider(this);
searchUICore = new QuickSearchHelper(this);
uiHandler = new Handler();
poiTypes = MapPoiTypes.getDefaultNoInit();
if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
initPoiTypes();
}
// Initialize native core
if (NativeCore.isAvailable() && !NativeCore.isLoaded()) {
assetsCustom = CoreResourcesFromAndroidAssets.loadFromCurrentApplication(this);
@ -44,7 +73,27 @@ public class SampleApplication extends Application {
}
Logger.get().setSeverityLevelThreshold(LogSeverityLevel.Debug);
iconsCache = new IconsCache(assetsCustom);
iconsCache = new IconsCache(assetsCustom, this);
}
public int getCoordinatesFormat() {
return coordinatesFormat;
}
public MetricsConstants getMetricsConstants() {
return metricsConstants;
}
public SpeedConstants getSpeedConstants() {
return speedConstants;
}
public SampleLocationProvider getLocationProvider() {
return locationProvider;
}
public QuickSearchHelper getSearchUICore() {
return searchUICore;
}
public MapPoiTypes getPoiTypes() {
@ -86,6 +135,8 @@ public class SampleApplication extends Application {
return null;
}
});
searchUICore.initSearchUICore();
}
public String getAbsoluteAppPath() {
@ -119,4 +170,46 @@ public class SampleApplication extends Application {
public void runInUIThread(Runnable run, long delay) {
uiHandler.postDelayed(run, delay);
}
// Check internet connection available every 15 seconds
public boolean isInternetConnectionAvailable() {
return isInternetConnectionAvailable(false);
}
public boolean isInternetConnectionAvailable(boolean update) {
long delta = System.currentTimeMillis() - lastTimeInternetConnectionChecked;
if (delta < 0 || delta > 15000 || update) {
internetConnectionAvailable = isInternetConnected();
}
return internetConnectionAvailable;
}
public boolean isWifiConnected() {
ConnectivityManager mgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = mgr.getActiveNetworkInfo();
return ni != null && ni.getType() == ConnectivityManager.TYPE_WIFI;
}
private boolean isInternetConnected() {
ConnectivityManager mgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo active = mgr.getActiveNetworkInfo();
if (active == null) {
return false;
} else {
NetworkInfo.State state = active.getState();
return state != NetworkInfo.State.DISCONNECTED && state != NetworkInfo.State.DISCONNECTING;
}
}
public static SampleApplication getApp(Context ctx) {
return (SampleApplication) ctx.getApplicationContext();
}
public String getString(String osmandId) {
return OsmandResources.getString(osmandId);
}
public String getString(String osmandId, Object... formatArgs) {
return OsmandResources.getString(osmandId, formatArgs);
}
}

View file

@ -0,0 +1,355 @@
package net.osmand.core.samples.android.sample1;
import android.content.Context;
import net.osmand.data.Amenity;
import net.osmand.data.City.CityType;
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.MapPoiTypes;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
import net.osmand.util.Algorithms;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.util.Map.Entry;
public class SampleFormatter {
public final static float METERS_IN_KILOMETER = 1000f;
public final static float METERS_IN_ONE_MILE = 1609.344f; // 1609.344
public final static float METERS_IN_ONE_NAUTICALMILE = 1852f; // 1852
public final static float YARDS_IN_ONE_METER = 1.0936f;
public final static float FEET_IN_ONE_METER = YARDS_IN_ONE_METER * 3f;
private static final DecimalFormat fixed2 = new DecimalFormat("0.00");
private static final DecimalFormat fixed1 = new DecimalFormat("0.0");
{
fixed2.setMinimumFractionDigits(2);
fixed1.setMinimumFractionDigits(1);
fixed1.setMinimumIntegerDigits(1);
fixed2.setMinimumIntegerDigits(1);
}
public static String getFormattedDuration(int seconds, SampleApplication ctx) {
int hours = seconds / (60 * 60);
int minutes = (seconds / 60) % 60;
if (hours > 0) {
return hours + " "
+ ctx.getString(R.string.shared_string_hour_short)
+ (minutes > 0 ? " " + minutes + " "
+ ctx.getString(R.string.shared_string_minute_short) : "");
} else {
return minutes + " " + ctx.getString(R.string.shared_string_minute_short);
}
}
public static double calculateRoundedDist(double distInMeters, SampleApplication ctx) {
MetricsConstants mc = ctx.getMetricsConstants();
double mainUnitInMeter = 1;
double metersInSecondUnit = METERS_IN_KILOMETER;
if (mc == MetricsConstants.MILES_AND_FEET) {
mainUnitInMeter = FEET_IN_ONE_METER;
metersInSecondUnit = METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.MILES_AND_METERS) {
mainUnitInMeter = 1;
metersInSecondUnit = METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.NAUTICAL_MILES) {
mainUnitInMeter = 1;
metersInSecondUnit = METERS_IN_ONE_NAUTICALMILE;
} else if (mc == MetricsConstants.MILES_AND_YARDS) {
mainUnitInMeter = YARDS_IN_ONE_METER;
metersInSecondUnit = METERS_IN_ONE_MILE;
}
// 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 ...
int generator = 1;
byte pointer = 1;
double point = mainUnitInMeter;
double roundDist = 1;
while (distInMeters * point > generator) {
roundDist = (generator / point);
if (pointer++ % 3 == 2) {
generator = generator * 5 / 2;
} else {
generator *= 2;
}
if (point == mainUnitInMeter && metersInSecondUnit * mainUnitInMeter * 0.9f <= generator) {
point = 1 / metersInSecondUnit;
generator = 1;
pointer = 1;
}
}
//Miles exceptions: 2000ft->0.5mi, 1000ft->0.25mi, 1000yd->0.5mi, 500yd->0.25mi, 1000m ->0.5mi, 500m -> 0.25mi
if (mc == MetricsConstants.MILES_AND_METERS && roundDist == 1000) {
roundDist = 0.5f * METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.MILES_AND_METERS && roundDist == 500) {
roundDist = 0.25f * METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.MILES_AND_FEET && roundDist == 2000 / (double) FEET_IN_ONE_METER) {
roundDist = 0.5f * METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.MILES_AND_FEET && roundDist == 1000 / (double) FEET_IN_ONE_METER) {
roundDist = 0.25f * METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.MILES_AND_YARDS && roundDist == 1000 / (double) YARDS_IN_ONE_METER) {
roundDist = 0.5f * METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.MILES_AND_YARDS && roundDist == 500 / (double) YARDS_IN_ONE_METER) {
roundDist = 0.25f * METERS_IN_ONE_MILE;
}
return roundDist;
}
public static String getFormattedRoundDistanceKm(float meters, int digits, SampleApplication ctx) {
int mainUnitStr = R.string.km;
float mainUnitInMeters = METERS_IN_KILOMETER;
if (digits == 0) {
return (int) (meters / mainUnitInMeters + 0.5) + " " + ctx.getString(mainUnitStr); //$NON-NLS-1$
} else if (digits == 1) {
return fixed1.format(((float) meters) / mainUnitInMeters) + " " + ctx.getString(mainUnitStr);
} else {
return fixed2.format(((float) meters) / mainUnitInMeters) + " " + ctx.getString(mainUnitStr);
}
}
public static String getFormattedDistance(float meters, SampleApplication ctx) {
return getFormattedDistance(meters, ctx, true);
}
public static String getFormattedDistance(float meters, SampleApplication ctx, boolean forceTrailingZeros) {
String format1 = forceTrailingZeros ? "{0,number,0.0} " : "{0,number,0.#} ";
String format2 = forceTrailingZeros ? "{0,number,0.00} " : "{0,number,0.##} ";
MetricsConstants mc = ctx.getMetricsConstants();
int mainUnitStr;
float mainUnitInMeters;
if (mc == MetricsConstants.KILOMETERS_AND_METERS) {
mainUnitStr = R.string.km;
mainUnitInMeters = METERS_IN_KILOMETER;
} else if (mc == MetricsConstants.NAUTICAL_MILES) {
mainUnitStr = R.string.nm;
mainUnitInMeters = METERS_IN_ONE_NAUTICALMILE;
} else {
mainUnitStr = R.string.mile;
mainUnitInMeters = METERS_IN_ONE_MILE;
}
if (meters >= 100 * mainUnitInMeters) {
return (int) (meters / mainUnitInMeters + 0.5) + " " + ctx.getString(mainUnitStr); //$NON-NLS-1$
} else if (meters > 9.99f * mainUnitInMeters) {
return MessageFormat.format(format1 + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters).replace('\n', ' '); //$NON-NLS-1$
} else if (meters > 0.999f * mainUnitInMeters) {
return MessageFormat.format(format2 + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters).replace('\n', ' '); //$NON-NLS-1$
} else if (mc == MetricsConstants.MILES_AND_FEET && meters > 0.249f * mainUnitInMeters) {
return MessageFormat.format(format2 + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters).replace('\n', ' '); //$NON-NLS-1$
} else if (mc == MetricsConstants.MILES_AND_METERS && meters > 0.249f * mainUnitInMeters) {
return MessageFormat.format(format2 + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters).replace('\n', ' '); //$NON-NLS-1$
} else if (mc == MetricsConstants.MILES_AND_YARDS && meters > 0.249f * mainUnitInMeters) {
return MessageFormat.format(format2 + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters).replace('\n', ' '); //$NON-NLS-1$
} else if (mc == MetricsConstants.NAUTICAL_MILES && meters > 0.99f * mainUnitInMeters) {
return MessageFormat.format(format2 + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters).replace('\n', ' '); //$NON-NLS-1$
} else {
if (mc == MetricsConstants.KILOMETERS_AND_METERS || mc == MetricsConstants.MILES_AND_METERS) {
return ((int) (meters + 0.5)) + " " + ctx.getString(R.string.m); //$NON-NLS-1$
} else if (mc == MetricsConstants.MILES_AND_FEET) {
int feet = (int) (meters * FEET_IN_ONE_METER + 0.5);
return feet + " " + ctx.getString(R.string.foot); //$NON-NLS-1$
} else if (mc == MetricsConstants.MILES_AND_YARDS) {
int yards = (int) (meters * YARDS_IN_ONE_METER + 0.5);
return yards + " " + ctx.getString(R.string.yard); //$NON-NLS-1$
}
return ((int) (meters + 0.5)) + " " + ctx.getString(R.string.m); //$NON-NLS-1$
}
}
public static String getFormattedAlt(double alt, SampleApplication ctx) {
MetricsConstants mc = ctx.getMetricsConstants();
if (mc == MetricsConstants.KILOMETERS_AND_METERS) {
return ((int) (alt + 0.5)) + " " + ctx.getString(R.string.m);
} else {
return ((int) (alt * FEET_IN_ONE_METER + 0.5)) + " " + ctx.getString(R.string.foot);
}
}
public static String getFormattedSpeed(float metersperseconds, SampleApplication ctx) {
SpeedConstants mc = ctx.getSpeedConstants();
float kmh = metersperseconds * 3.6f;
if (mc == SpeedConstants.KILOMETERS_PER_HOUR) {
// e.g. car case and for high-speeds: Display rounded to 1 km/h (5% precision at 20 km/h)
if (kmh >= 20) {
return ((int) Math.round(kmh)) + " " + mc.toShortString(ctx);
}
// for smaller values display 1 decimal digit x.y km/h, (0.5% precision at 20 km/h)
int kmh10 = (int) Math.round(kmh * 10f);
return (kmh10 / 10f) + " " + mc.toShortString(ctx);
} else if (mc == SpeedConstants.MILES_PER_HOUR) {
float mph = kmh * METERS_IN_KILOMETER / METERS_IN_ONE_MILE;
if (mph >= 20) {
return ((int) Math.round(mph)) + " " + mc.toShortString(ctx);
} else {
int mph10 = (int) Math.round(mph * 10f);
return (mph10 / 10f) + " " + mc.toShortString(ctx);
}
} else if (mc == SpeedConstants.NAUTICALMILES_PER_HOUR) {
float mph = kmh * METERS_IN_KILOMETER / METERS_IN_ONE_NAUTICALMILE;
if (mph >= 20) {
return ((int) Math.round(mph)) + " " + mc.toShortString(ctx);
} else {
int mph10 = (int) Math.round(mph * 10f);
return (mph10 / 10f) + " " + mc.toShortString(ctx);
}
} else if (mc == SpeedConstants.MINUTES_PER_KILOMETER) {
if (metersperseconds < 0.111111111) {
return "-" + mc.toShortString(ctx);
}
float minperkm = METERS_IN_KILOMETER / (metersperseconds * 60);
if (minperkm >= 10) {
return ((int) Math.round(minperkm)) + " " + mc.toShortString(ctx);
} else {
int mph10 = (int) Math.round(minperkm * 10f);
return (mph10 / 10f) + " " + mc.toShortString(ctx);
}
} else if (mc == SpeedConstants.MINUTES_PER_MILE) {
if (metersperseconds < 0.111111111) {
return "-" + mc.toShortString(ctx);
}
float minperm = (METERS_IN_ONE_MILE) / (metersperseconds * 60);
if (minperm >= 10) {
return ((int) Math.round(minperm)) + " " + mc.toShortString(ctx);
} else {
int mph10 = (int) Math.round(minperm * 10f);
return (mph10 / 10f) + " " + mc.toShortString(ctx);
}
} else /*if (mc == SpeedConstants.METERS_PER_SECOND) */ {
if (metersperseconds >= 10) {
return ((int) Math.round(metersperseconds)) + " " + SpeedConstants.METERS_PER_SECOND.toShortString(ctx);
}
// for smaller values display 1 decimal digit x.y km/h, (0.5% precision at 20 km/h)
int kmh10 = (int) Math.round(metersperseconds * 10f);
return (kmh10 / 10f) + " " + SpeedConstants.METERS_PER_SECOND.toShortString(ctx);
}
}
public static String toPublicString(CityType t, SampleApplication ctx) {
switch (t) {
case CITY:
return ctx.getString("city_type_city");
case HAMLET:
return ctx.getString("city_type_hamlet");
case TOWN:
return ctx.getString("city_type_town");
case VILLAGE:
return ctx.getString("city_type_village");
case SUBURB:
return ctx.getString("city_type_suburb");
default:
break;
}
return "";
}
public static String getPoiStringWithoutType(Amenity amenity, String locale, boolean transliterate) {
PoiCategory pc = amenity.getType();
PoiType pt = pc.getPoiTypeByKeyName(amenity.getSubType());
String nm = amenity.getSubType();
if (pt != null) {
nm = pt.getTranslation();
} else if(nm != null){
nm = Algorithms.capitalizeFirstLetterAndLowercase(nm.replace('_', ' '));
}
String n = amenity.getName(locale, transliterate);
if (n.indexOf(nm) != -1) {
// type is contained in name e.g.
// n = "Bakery the Corner"
// type = "Bakery"
// no need to repeat this
return n;
}
if (n.length() == 0) {
return nm;
}
return nm + " " + n; //$NON-NLS-1$
}
public static String getAmenityDescriptionContent(SampleApplication ctx, Amenity amenity, boolean shortDescription) {
StringBuilder d = new StringBuilder();
if(amenity.getType().isWiki()) {
return "";
}
MapPoiTypes poiTypes = ctx.getPoiTypes();
for(Entry<String, String> e : amenity.getAdditionalInfo().entrySet()) {
String key = e.getKey();
String vl = e.getValue();
if(key.startsWith("name:")) {
continue;
} else if(vl.length() >= 150) {
if(shortDescription) {
continue;
}
} else if(Amenity.OPENING_HOURS.equals(key)) {
d.append(ctx.getString("opening_hours") + ": ");
} else if(Amenity.PHONE.equals(key)) {
d.append(ctx.getString("phone") + ": ");
} else if(Amenity.WEBSITE.equals(key)) {
d.append(ctx.getString("website") + ": ");
} else {
AbstractPoiType pt = poiTypes.getAnyPoiAdditionalTypeByKey(e.getKey());
if (pt != null) {
if(pt instanceof PoiType && !((PoiType) pt).isText()) {
vl = pt.getTranslation();
} else {
vl = pt.getTranslation() + ": " + amenity.unzipContent(e.getValue());
}
} else {
vl = Algorithms.capitalizeFirstLetterAndLowercase(e.getKey()) +
": " + amenity.unzipContent(e.getValue());
}
}
d.append(vl).append('\n');
}
return d.toString().trim();
}
public enum MetricsConstants {
KILOMETERS_AND_METERS(R.string.si_km_m),
MILES_AND_FEET(R.string.si_mi_feet),
MILES_AND_METERS(R.string.si_mi_meters),
MILES_AND_YARDS(R.string.si_mi_yard),
NAUTICAL_MILES(R.string.si_nm);
private final int key;
MetricsConstants(int key) {
this.key = key;
}
public String toHumanString(Context ctx) {
return ctx.getString(key);
}
}
public enum SpeedConstants {
KILOMETERS_PER_HOUR(R.string.km_h, R.string.si_kmh),
MILES_PER_HOUR(R.string.mile_per_hour, R.string.si_mph),
METERS_PER_SECOND(R.string.m_s, R.string.si_m_s),
MINUTES_PER_MILE(R.string.min_mile, R.string.si_min_m),
MINUTES_PER_KILOMETER(R.string.min_km, R.string.si_min_km),
NAUTICALMILES_PER_HOUR(R.string.nm_h, R.string.si_nm_h);
private final int key;
private int descr;
SpeedConstants(int key, int descr) {
this.key = key;
this.descr = descr;
}
public String toHumanString(Context ctx) {
return ctx.getString(descr);
}
public String toShortString(Context ctx) {
return ctx.getString(key);
}
}
}

View file

@ -0,0 +1,571 @@
package net.osmand.core.samples.android.sample1;
import android.Manifest;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.GeomagneticField;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.GpsStatus.Listener;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import net.osmand.PlatformUtil;
import net.osmand.util.MapUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class SampleLocationProvider implements SensorEventListener {
public interface SampleLocationListener {
void updateLocation(net.osmand.Location location);
}
public interface SampleCompassListener {
void updateCompassValue(float value);
}
private static final int INTERVAL_TO_CLEAR_SET_LOCATION = 30 * 1000;
private static final int GPS_TIMEOUT_REQUEST = 0;
private static final int GPS_DIST_REQUEST = 0;
private static final int NOT_SWITCH_TO_NETWORK_WHEN_GPS_LOST_MS = 12000;
private long lastTimeGPSLocationFixed = 0;
private boolean gpsSignalLost;
private boolean sensorRegistered = false;
private float[] mGravs = new float[3];
private float[] mGeoMags = new float[3];
private float previousCorrectionValue = 360;
float avgValSin = 0;
float avgValCos = 0;
float lastValSin = 0;
float lastValCos = 0;
private float[] previousCompassValuesA = new float[50];
private float[] previousCompassValuesB = new float[50];
private int previousCompassIndA = 0;
private int previousCompassIndB = 0;
private boolean inUpdateValue = false;
private Float heading = null;
// Current screen orientation
private int currentScreenOrientation;
private SampleApplication app;
//private CurrentPositionHelper currentPositionHelper;
private net.osmand.Location location = null;
private GPSInfo gpsInfo = new GPSInfo();
private List<SampleLocationListener> locationListeners = new ArrayList<>();
private List<SampleCompassListener> compassListeners = new ArrayList<>();
private Listener gpsStatusListener;
private float[] mRotationM = new float[9];
private static final long AGPS_TO_REDOWNLOAD = 16 * 60 * 60 * 1000; // 16 hours
private long agpsDataLastTimeDownloaded;
private boolean useMagneticFieldSensorCompass = false;
public SampleLocationProvider(SampleApplication app) {
this.app = app;
//currentPositionHelper = new CurrentPositionHelper(app);
}
public void resumeAllUpdates() {
final LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
if (app.isInternetConnectionAvailable()) {
if (System.currentTimeMillis() - agpsDataLastTimeDownloaded > AGPS_TO_REDOWNLOAD) {
//force an updated check for internet connectivity here before destroying A-GPS-data
if (app.isInternetConnectionAvailable(true)) {
redownloadAGPS();
}
}
}
if (isLocationPermissionAvailable(app)) {
service.addGpsStatusListener(getGpsStatusListener(service));
try {
service.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, gpsListener);
} catch (IllegalArgumentException e) {
Log.d(PlatformUtil.TAG, "GPS location provider not available"); //$NON-NLS-1$
}
// try to always ask for network provide : it is faster way to find location
List<String> providers = service.getProviders(true);
if (providers == null) {
return;
}
for (String provider : providers) {
if (provider == null || provider.equals(LocationManager.GPS_PROVIDER)) {
continue;
}
try {
NetworkListener networkListener = new NetworkListener();
service.requestLocationUpdates(provider, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, networkListener);
networkListeners.add(networkListener);
} catch (IllegalArgumentException e) {
Log.d(PlatformUtil.TAG, provider + " location provider not available"); //$NON-NLS-1$
}
}
}
}
public void redownloadAGPS() {
try {
final LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
service.sendExtraCommand(LocationManager.GPS_PROVIDER, "delete_aiding_data", null);
Bundle bundle = new Bundle();
service.sendExtraCommand("gps", "force_xtra_injection", bundle);
service.sendExtraCommand("gps", "force_time_injection", bundle);
agpsDataLastTimeDownloaded = System.currentTimeMillis();
} catch (Exception e) {
agpsDataLastTimeDownloaded = 0L;
e.printStackTrace();
}
}
private Listener getGpsStatusListener(final LocationManager service) {
gpsStatusListener = new Listener() {
private GpsStatus gpsStatus;
@Override
public void onGpsStatusChanged(int event) {
gpsStatus = service.getGpsStatus(gpsStatus);
updateGPSInfo(gpsStatus);
updateLocation(location);
}
};
return gpsStatusListener;
}
private void updateGPSInfo(GpsStatus s) {
boolean fixed = false;
int n = 0;
int u = 0;
if (s != null) {
Iterator<GpsSatellite> iterator = s.getSatellites().iterator();
while (iterator.hasNext()) {
GpsSatellite g = iterator.next();
n++;
if (g.usedInFix()) {
u++;
fixed = true;
}
}
}
gpsInfo.fixed = fixed;
gpsInfo.foundSatellites = n;
gpsInfo.usedSatellites = u;
}
public GPSInfo getGPSInfo() {
return gpsInfo;
}
public void updateScreenOrientation(int orientation) {
currentScreenOrientation = orientation;
}
public void addLocationListener(SampleLocationListener listener) {
if (!locationListeners.contains(listener)) {
locationListeners.add(listener);
}
}
public void removeLocationListener(SampleLocationListener listener) {
locationListeners.remove(listener);
}
public void addCompassListener(SampleCompassListener listener) {
if (!compassListeners.contains(listener)) {
compassListeners.add(listener);
}
}
public void removeCompassListener(SampleCompassListener listener) {
compassListeners.remove(listener);
}
public net.osmand.Location getFirstTimeRunDefaultLocation() {
if (!isLocationPermissionAvailable(app)) {
return null;
}
LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
List<String> ps = service.getProviders(true);
if (ps == null) {
return null;
}
List<String> providers = new ArrayList<String>(ps);
// note, passive provider is from API_LEVEL 8 but it is a constant, we can check for it.
// constant should not be changed in future
int passiveFirst = providers.indexOf("passive"); // LocationManager.PASSIVE_PROVIDER
// put passive provider to first place
if (passiveFirst > -1) {
providers.add(0, providers.remove(passiveFirst));
}
// find location
for (String provider : providers) {
net.osmand.Location location = convertLocation(service.getLastKnownLocation(provider), app);
if (location != null) {
return location;
}
}
return null;
}
public synchronized void registerOrUnregisterCompassListener(boolean register) {
if (sensorRegistered && !register) {
Log.d(PlatformUtil.TAG, "Disable sensor"); //$NON-NLS-1$
((SensorManager) app.getSystemService(Context.SENSOR_SERVICE)).unregisterListener(this);
sensorRegistered = false;
heading = null;
} else if (!sensorRegistered && register) {
Log.d(PlatformUtil.TAG, "Enable sensor"); //$NON-NLS-1$
SensorManager sensorMgr = (SensorManager) app.getSystemService(Context.SENSOR_SERVICE);
if (useMagneticFieldSensorCompass) {
Sensor s = sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (s == null || !sensorMgr.registerListener(this, s, SensorManager.SENSOR_DELAY_UI)) {
Log.e(PlatformUtil.TAG, "Sensor accelerometer could not be enabled");
}
s = sensorMgr.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
if (s == null || !sensorMgr.registerListener(this, s, SensorManager.SENSOR_DELAY_UI)) {
Log.e(PlatformUtil.TAG, "Sensor magnetic field could not be enabled");
}
} else {
Sensor s = sensorMgr.getDefaultSensor(Sensor.TYPE_ORIENTATION);
if (s == null || !sensorMgr.registerListener(this, s, SensorManager.SENSOR_DELAY_UI)) {
Log.e(PlatformUtil.TAG, "Sensor orientation could not be enabled");
}
}
sensorRegistered = true;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
// Attention : sensor produces a lot of events & can hang the system
if (inUpdateValue) {
return;
}
synchronized (this) {
if (!sensorRegistered) {
return;
}
inUpdateValue = true;
try {
float val = 0;
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mGravs, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mGeoMags, 0, 3);
break;
case Sensor.TYPE_ORIENTATION:
val = event.values[0];
break;
default:
return;
}
if (useMagneticFieldSensorCompass) {
if (mGravs != null && mGeoMags != null) {
boolean success = SensorManager.getRotationMatrix(mRotationM, null, mGravs, mGeoMags);
if (!success) {
return;
}
float[] orientation = SensorManager.getOrientation(mRotationM, new float[3]);
val = (float) Math.toDegrees(orientation[0]);
} else {
return;
}
}
val = calcScreenOrientationCorrection(val);
val = calcGeoMagneticCorrection(val);
float valRad = (float) (val / 180f * Math.PI);
lastValSin = (float) Math.sin(valRad);
lastValCos = (float) Math.cos(valRad);
avgValSin = lastValSin;
avgValCos = lastValCos;
updateCompassVal();
} finally {
inUpdateValue = false;
}
}
}
private float calcGeoMagneticCorrection(float val) {
if (previousCorrectionValue == 360 && getLastKnownLocation() != null) {
net.osmand.Location l = getLastKnownLocation();
GeomagneticField gf = new GeomagneticField((float) l.getLatitude(), (float) l.getLongitude(), (float) l.getAltitude(),
System.currentTimeMillis());
previousCorrectionValue = gf.getDeclination();
}
if (previousCorrectionValue != 360) {
val += previousCorrectionValue;
}
return val;
}
private float calcScreenOrientationCorrection(float val) {
if (currentScreenOrientation == 1) {
val += 90;
} else if (currentScreenOrientation == 2) {
val += 180;
} else if (currentScreenOrientation == 3) {
val -= 90;
}
return val;
}
private void filterCompassValue() {
if (heading == null && previousCompassIndA == 0) {
Arrays.fill(previousCompassValuesA, lastValSin);
Arrays.fill(previousCompassValuesB, lastValCos);
avgValSin = lastValSin;
avgValCos = lastValCos;
} else {
int l = previousCompassValuesA.length;
previousCompassIndA = (previousCompassIndA + 1) % l;
previousCompassIndB = (previousCompassIndB + 1) % l;
// update average
avgValSin = avgValSin + (-previousCompassValuesA[previousCompassIndA] + lastValSin) / l;
previousCompassValuesA[previousCompassIndA] = lastValSin;
avgValCos = avgValCos + (-previousCompassValuesB[previousCompassIndB] + lastValCos) / l;
previousCompassValuesB[previousCompassIndB] = lastValCos;
}
}
private void updateCompassVal() {
heading = getAngle(avgValSin, avgValCos);
for (SampleCompassListener c : compassListeners) {
c.updateCompassValue(heading);
}
}
public synchronized Float getHeading() {
// if (heading != null && lastValSin != avgValSin && System.currentTimeMillis() - lastHeadingCalcTime > 700) {
// avgValSin = lastValSin;
// avgValCos = lastValCos;
// Arrays.fill(previousCompassValuesA, avgValSin);
// Arrays.fill(previousCompassValuesB, avgValCos);
// updateCompassVal();
// }
return heading;
}
private float getAngle(float sinA, float cosA) {
return MapUtils.unifyRotationTo360((float) (Math.atan2(sinA, cosA) * 180 / Math.PI));
}
private void updateLocation(net.osmand.Location loc) {
for (SampleLocationListener l : locationListeners) {
l.updateLocation(loc);
}
}
private LocationListener gpsListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
if (location != null) {
lastTimeGPSLocationFixed = location.getTime();
}
setLocation(convertLocation(location, app));
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
private LinkedList<LocationListener> networkListeners = new LinkedList<LocationListener>();
private boolean useOnlyGPS() {
if ((System.currentTimeMillis() - lastTimeGPSLocationFixed) < NOT_SWITCH_TO_NETWORK_WHEN_GPS_LOST_MS) {
return true;
}
return false;
}
// Working with location checkListeners
private class NetworkListener implements LocationListener {
@Override
public void onLocationChanged(Location location) {
if (!useOnlyGPS()) {
setLocation(convertLocation(location, app));
}
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
;
private void stopLocationRequests() {
LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
service.removeGpsStatusListener(gpsStatusListener);
service.removeUpdates(gpsListener);
while (!networkListeners.isEmpty()) {
service.removeUpdates(networkListeners.poll());
}
}
public void pauseAllUpdates() {
stopLocationRequests();
registerOrUnregisterCompassListener(false);
}
public static net.osmand.Location convertLocation(Location l, SampleApplication app) {
if (l == null) {
return null;
}
net.osmand.Location r = new net.osmand.Location(l.getProvider());
r.setLatitude(l.getLatitude());
r.setLongitude(l.getLongitude());
r.setTime(l.getTime());
if (l.hasAccuracy()) {
r.setAccuracy(l.getAccuracy());
}
if (l.hasSpeed()) {
r.setSpeed(l.getSpeed());
}
if (l.hasAltitude()) {
r.setAltitude(l.getAltitude());
}
if (l.hasBearing()) {
r.setBearing(l.getBearing());
}
return r;
}
private void setLocation(net.osmand.Location location) {
if (location == null) {
updateGPSInfo(null);
}
if (location != null) {
if (gpsSignalLost) {
gpsSignalLost = false;
}
}
this.location = location;
// Update information
updateLocation(this.location);
}
public void checkIfLastKnownLocationIsValid() {
net.osmand.Location loc = getLastKnownLocation();
if (loc != null && (System.currentTimeMillis() - loc.getTime()) > INTERVAL_TO_CLEAR_SET_LOCATION) {
setLocation(null);
}
}
/*
public RouteDataObject getLastKnownRouteSegment() {
return currentPositionHelper.getLastKnownRouteSegment(getLastKnownLocation());
}
public boolean getRouteSegment(net.osmand.Location loc, ResultMatcher<RouteDataObject> result) {
return currentPositionHelper.getRouteSegment(loc, result);
}
public boolean getGeocodingResult(net.osmand.Location loc, ResultMatcher<GeocodingResult> result) {
return currentPositionHelper.getGeocodingResult(loc, result);
}
*/
public net.osmand.Location getLastKnownLocation() {
return location;
}
public static class GPSInfo {
public int foundSatellites = 0;
public int usedSatellites = 0;
public boolean fixed = false;
}
public boolean checkGPSEnabled(final Context context) {
LocationManager lm = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
boolean gpsenabled = false;
boolean networkenabled = false;
try {
gpsenabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
}
try {
networkenabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
}
if (!gpsenabled && !networkenabled) {
// notify user
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
dialog.setMessage(app.getString("gps_network_not_enabled"));
dialog.setPositiveButton(app.getString("shared_string_settings"), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
context.startActivity(myIntent);
}
});
dialog.setNegativeButton(context.getString(R.string.shared_string_cancel), null);
dialog.show();
return false;
}
return true;
}
public static boolean isLocationPermissionAvailable(Context context) {
return ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED;
}
}

View file

@ -1,13 +1,22 @@
package net.osmand.core.samples.android.sample1;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.view.WindowManager;
public class SampleUtils {
private static final int ORIENTATION_0 = 0;
private static final int ORIENTATION_90 = 3;
private static final int ORIENTATION_270 = 1;
private static final int ORIENTATION_180 = 2;
public static void doRestart(Context c) {
boolean res = false;
try {
@ -59,4 +68,28 @@ public class SampleUtils {
}
return installed;
}
public static int getScreenOrientation(Activity a) {
int screenOrientation = ((WindowManager) a.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
switch (screenOrientation) {
case ORIENTATION_0: // Device default (normally portrait)
screenOrientation = 0;
break;
case ORIENTATION_90: // Landscape right
screenOrientation = 90;
break;
case ORIENTATION_270: // Landscape left
screenOrientation = 270;
break;
case ORIENTATION_180: // Upside down
screenOrientation = 180;
break;
}
//Looks like screenOrientation correction must not be applied for devices without compass?
Sensor compass = ((SensorManager) a.getSystemService(Context.SENSOR_SERVICE)).getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
if (compass == null) {
screenOrientation = 0;
}
return screenOrientation;
}
}

View file

@ -1,114 +0,0 @@
package net.osmand.core.samples.android.sample1.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import net.osmand.core.samples.android.sample1.R;
import net.osmand.data.LatLon;
import net.osmand.search.core.SearchResult;
import java.text.MessageFormat;
import java.util.List;
public class SearchListAdapter extends ArrayAdapter<SearchListItem> {
private Context ctx;
private LatLon location;
public SearchListAdapter(Context ctx) {
super(ctx, R.layout.search_list_item);
this.ctx = ctx;
}
public void setListItems(List<SearchListItem> items) {
setNotifyOnChange(false);
clear();
for (SearchListItem item : items) {
add(item);
}
setNotifyOnChange(true);
notifyDataSetInvalidated();
}
public LatLon getLocation() {
return location;
}
public void setLocation(LatLon location) {
this.location = location;
}
@Override
public SearchListItem getItem(int position) {
return super.getItem(position);
}
public void updateDistance(double latitude, double longitude) {
/*
for (int i = 0; i < getCount(); i++) {
SearchListItem item = getItem(i);
if (item instanceof SearchListPositionItem) {
SearchListPositionItem positionItem = (SearchListPositionItem) item;
positionItem.setDistance(Utilities.distance(
longitude, latitude, positionItem.getLongitude(), positionItem.getLatitude()));
}
}
*/
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
SearchListItem listItem = getItem(position);
LinearLayout view;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) ctx
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = (LinearLayout) inflater.inflate(
R.layout.search_list_item, null);
} else {
view = (LinearLayout) convertView;
}
ImageView imageView = (ImageView) view.findViewById(R.id.imageView);
TextView title = (TextView) view.findViewById(R.id.title);
TextView subtitle = (TextView) view.findViewById(R.id.subtitle);
TextView distance = (TextView) view.findViewById(R.id.distance);
imageView.setImageDrawable(listItem.getIcon());
title.setText(listItem.getName());
subtitle.setText(listItem.getTypeName());
if (location != null && listItem.getSearchResult().location != null) {
double dist = listItem.getDistance();
if (dist == 0) {
distance.setText("");
} else {
distance.setText(getFormattedDistance(dist));
}
distance.setVisibility(View.VISIBLE);
} else {
distance.setVisibility(View.INVISIBLE);
}
return view;
}
public static String getFormattedDistance(double meters) {
double mainUnitInMeters = 1000;
String mainUnitStr = "km";
if (meters >= 100 * mainUnitInMeters) {
return (int) (meters / mainUnitInMeters + 0.5) + " " + mainUnitStr;
} else if (meters > 9.99f * mainUnitInMeters) {
return MessageFormat.format("{0,number,#.#} " + mainUnitStr, ((float) meters) / mainUnitInMeters).replace('\n', ' ');
} else if (meters > 0.999f * mainUnitInMeters) {
return MessageFormat.format("{0,number,#.##} " + mainUnitStr, ((float) meters) / mainUnitInMeters).replace('\n', ' ');
} else {
return ((int) (meters + 0.5)) + " m";
}
}
}

View file

@ -1,152 +0,0 @@
package net.osmand.core.samples.android.sample1.adapters;
import android.graphics.drawable.Drawable;
import net.osmand.core.samples.android.sample1.SampleApplication;
import net.osmand.data.Amenity;
import net.osmand.data.City;
import net.osmand.data.Street;
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiFilter;
import net.osmand.osm.PoiType;
import net.osmand.search.core.SearchResult;
import net.osmand.util.Algorithms;
public class SearchListItem {
protected SampleApplication app;
private SearchResult searchResult;
private double distance;
public SearchListItem(SampleApplication app, SearchResult searchResult) {
this.app = app;
this.searchResult = searchResult;
}
public SearchResult getSearchResult() {
return searchResult;
}
public String getName() {
return searchResult.localeName;
}
public String getTypeName() {
switch (searchResult.objectType) {
case CITY:
case POSTCODE:
City city = (City) searchResult.object;
return Algorithms.capitalizeFirstLetterAndLowercase(city.getType().toString());
case VILLAGE:
city = (City) searchResult.object;
if (!Algorithms.isEmpty(searchResult.localeRelatedObjectName)) {
return Algorithms.capitalizeFirstLetterAndLowercase(city.getType().toString())
+ " near "
+ searchResult.localeRelatedObjectName
+ (searchResult.distRelatedObjectName > 0 ? " (" + SearchListAdapter.getFormattedDistance(searchResult.distRelatedObjectName) + ")" : "");
} else {
return Algorithms.capitalizeFirstLetterAndLowercase(city.getType().toString());
}
case STREET:
Street street = (Street) searchResult.object;
City streetCity = street.getCity();
if (!Algorithms.isEmpty(searchResult.localeRelatedObjectName)) {
return searchResult.localeRelatedObjectName
+ (searchResult.distRelatedObjectName > 0 ? "(" + SearchListAdapter.getFormattedDistance(searchResult.distRelatedObjectName) + ")" : "");
} else {
return streetCity.getName() + " - " + Algorithms.capitalizeFirstLetterAndLowercase(streetCity.getType().name());
}
case HOUSE:
return "House";
case STREET_INTERSECTION:
return "Street intersection";
case POI_TYPE:
AbstractPoiType abstractPoiType = (AbstractPoiType) searchResult.object;
String res;
if (abstractPoiType instanceof PoiCategory) {
res = "POI category";
} else if (abstractPoiType instanceof PoiFilter) {
PoiFilter poiFilter = (PoiFilter) abstractPoiType;
res = poiFilter.getPoiCategory() != null ? poiFilter.getPoiCategory().getTranslation() : "POI filter";
} else if (abstractPoiType instanceof PoiType) {
PoiType poiType = (PoiType) abstractPoiType;
res = poiType.getParentType() != null ? poiType.getParentType().getTranslation() : null;
if (res == null) {
res = poiType.getCategory() != null ? poiType.getCategory().getTranslation() : null;
}
if (res == null) {
res = "POI type";
}
} else {
res = "POI type";
}
return res;
case POI:
Amenity amenity = (Amenity) searchResult.object;
return amenity.getType().toString();
case LOCATION:
break;
case FAVORITE:
break;
case REGION:
break;
case RECENT_OBJ:
break;
case WPT:
break;
case UNKNOWN_NAME_FILTER:
break;
}
return searchResult.objectType.name();
}
public Drawable getIcon() {
switch (searchResult.objectType) {
case CITY:
break;
case VILLAGE:
break;
case POSTCODE:
break;
case STREET:
break;
case HOUSE:
break;
case STREET_INTERSECTION:
break;
case POI_TYPE:
break;
case POI:
Amenity amenity = (Amenity) searchResult.object;
Drawable drawable = null;
PoiType st = amenity.getType().getPoiTypeByKeyName(amenity.getSubType());
if (st != null) {
drawable = app.getIconsCache().getMapIcon(st.getOsmTag() + "_" + st.getOsmValue());
}
return drawable;
case LOCATION:
break;
case FAVORITE:
break;
case REGION:
break;
case RECENT_OBJ:
break;
case WPT:
break;
case UNKNOWN_NAME_FILTER:
break;
}
return null;
}
public double getDistance() {
return distance;
}
public void setDistance(double distance) {
this.distance = distance;
}
}

View file

@ -0,0 +1,29 @@
package net.osmand.core.samples.android.sample1.customcontrols;
import android.annotation.TargetApi;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Button;
public class OsmandButton extends Button {
public OsmandButton(Context context) {
super(context);
}
public OsmandButton(Context context, AttributeSet attrs) {
super(context, attrs);
OsmandTextView.parseAttributes(this, attrs, 0, 0);
}
public OsmandButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
OsmandTextView.parseAttributes(this, attrs, defStyleAttr, 0);
}
@TargetApi(21)
public OsmandButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
OsmandTextView.parseAttributes(this, attrs, defStyleAttr, defStyleRes);
}
}

View file

@ -0,0 +1,59 @@
package net.osmand.core.samples.android.sample1.customcontrols;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.ImageButton;
import net.osmand.core.samples.android.sample1.OsmandResources;
import net.osmand.core.samples.android.sample1.R;
public class OsmandImageButton extends ImageButton {
public OsmandImageButton(Context context) {
super(context);
}
public OsmandImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
parseAttributes(this, attrs, 0, 0);
}
public OsmandImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
parseAttributes(this, attrs, defStyleAttr, 0);
}
@TargetApi(21)
public OsmandImageButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
parseAttributes(this, attrs, defStyleAttr, defStyleRes);
}
static void parseAttributes(ImageButton target, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
if (attrs == null) {
return;
}
TypedArray resolvedAttrs = target.getContext().getTheme().obtainStyledAttributes(attrs,
R.styleable.OsmandButton, defStyleAttr, defStyleRes);
applyAttributes(resolvedAttrs, target);
resolvedAttrs.recycle();
}
private static void applyAttributes(TypedArray resolvedAttributes, ImageButton target) {
applyAttribute_osmandSrc(resolvedAttributes, target);
}
static void applyAttribute_osmandSrc(TypedArray resolvedAttributes, ImageButton target) {
if (!resolvedAttributes.hasValue(R.styleable.OsmandImageButton_osmandSrc)
|| target.isInEditMode()) {
return;
}
String osmandSrc = resolvedAttributes.getString(R.styleable.OsmandImageButton_osmandSrc);
target.setImageDrawable(OsmandResources.getDrawable(osmandSrc));
}
}

View file

@ -0,0 +1,57 @@
package net.osmand.core.samples.android.sample1.customcontrols;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.ImageView;
import net.osmand.core.samples.android.sample1.OsmandResources;
import net.osmand.core.samples.android.sample1.R;
public class OsmandImageView extends ImageView {
public OsmandImageView(Context context) {
super(context);
}
public OsmandImageView(Context context, AttributeSet attrs) {
super(context, attrs);
parseAttributes(this, attrs, 0, 0);
}
public OsmandImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
parseAttributes(this, attrs, defStyleAttr, 0);
}
@TargetApi(21)
public OsmandImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
parseAttributes(this, attrs, defStyleAttr, defStyleRes);
}
static void parseAttributes(ImageView target, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
if (attrs == null) {
return;
}
TypedArray resolvedAttrs = target.getContext().getTheme().obtainStyledAttributes(attrs,
R.styleable.OsmandButton, defStyleAttr, defStyleRes);
applyAttributes(resolvedAttrs, target);
resolvedAttrs.recycle();
}
private static void applyAttributes(TypedArray resolvedAttributes, ImageView target) {
applyAttribute_osmandSrc(resolvedAttributes, target);
}
static void applyAttribute_osmandSrc(TypedArray resolvedAttributes, ImageView target) {
if (!resolvedAttributes.hasValue(R.styleable.OsmandImageButton_osmandSrc)
|| target.isInEditMode()) {
return;
}
String osmandSrc = resolvedAttributes.getString(R.styleable.OsmandImageButton_osmandSrc);
target.setImageDrawable(OsmandResources.getDrawable(osmandSrc));
}
}

View file

@ -0,0 +1,57 @@
package net.osmand.core.samples.android.sample1.customcontrols;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.TextView;
import net.osmand.core.samples.android.sample1.OsmandResources;
import net.osmand.core.samples.android.sample1.R;
public class OsmandTextView extends TextView {
public OsmandTextView(Context context) {
super(context);
}
public OsmandTextView(Context context, AttributeSet attrs) {
super(context, attrs);
parseAttributes(this, attrs, 0, 0);
}
public OsmandTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
parseAttributes(this, attrs, defStyleAttr, 0);
}
@TargetApi(21)
public OsmandTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
parseAttributes(this, attrs, defStyleAttr, defStyleRes);
}
static void parseAttributes(TextView target, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
if (attrs == null) {
return;
}
TypedArray resolvedAttrs = target.getContext().getTheme().obtainStyledAttributes(attrs,
R.styleable.OsmandTextView, defStyleAttr, defStyleRes);
applyAttributes(resolvedAttrs, target);
resolvedAttrs.recycle();
}
private static void applyAttributes(TypedArray resolvedAttributes, TextView target) {
applyAttribute_osmandText(resolvedAttributes, target);
}
static void applyAttribute_osmandText(TypedArray resolvedAttributes, TextView target) {
if (!resolvedAttributes.hasValue(R.styleable.OsmandTextView_osmandText)
|| target.isInEditMode()) {
return;
}
String osmandText = resolvedAttributes.getString(R.styleable.OsmandTextView_osmandText);
target.setText(OsmandResources.getString(osmandText));
}
}

View file

@ -0,0 +1,24 @@
package net.osmand.core.samples.android.sample1.data;
import android.content.Context;
/**
*/
public interface LocationPoint {
public double getLatitude();
public double getLongitude();
public int getColor();
public boolean isVisible();
public PointDescription getPointDescription(Context ctx);
// public String getSpeakableName();
//public void prepareCommandPlayer(CommandBuilder cmd, String names);
}

View file

@ -0,0 +1,357 @@
package net.osmand.core.samples.android.sample1.data;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.jwetherell.openmap.common.LatLonPoint;
import com.jwetherell.openmap.common.UTMPoint;
import net.osmand.LocationConvert;
import net.osmand.core.samples.android.sample1.SampleApplication;
import net.osmand.data.LatLon;
import net.osmand.util.Algorithms;
public class PointDescription {
private String type = "";
private String name = "";
private String typeName;
private String iconName;
private double lat = 0;
private double lon = 0;
public static final String POINT_TYPE_FAVORITE = "favorite";
public static final String POINT_TYPE_WPT = "wpt";
public static final String POINT_TYPE_POI = "poi";
public static final String POINT_TYPE_ADDRESS = "address";
public static final String POINT_TYPE_OSM_NOTE= "osm_note";
public static final String POINT_TYPE_MARKER = "marker";
public static final String POINT_TYPE_PARKING_MARKER = "parking_marker";
public static final String POINT_TYPE_AUDIO_NOTE = "audionote";
public static final String POINT_TYPE_VIDEO_NOTE = "videonote";
public static final String POINT_TYPE_PHOTO_NOTE = "photonote";
public static final String POINT_TYPE_LOCATION = "location";
public static final String POINT_TYPE_MY_LOCATION = "my_location";
public static final String POINT_TYPE_ALARM = "alarm";
public static final String POINT_TYPE_TARGET = "destination";
public static final String POINT_TYPE_MAP_MARKER = "map_marker";
public static final String POINT_TYPE_OSM_BUG = "bug";
public static final String POINT_TYPE_WORLD_REGION = "world_region";
public static final String POINT_TYPE_GPX_ITEM = "gpx_item";
public static final String POINT_TYPE_WORLD_REGION_SHOW_ON_MAP = "world_region_show_on_map";
public static final String POINT_TYPE_BLOCKED_ROAD = "blocked_road";
public static final String POINT_TYPE_TRANSPORT_ROUTE = "transport_route";
public static final String POINT_TYPE_TRANSPORT_STOP = "transport_stop";
public static final PointDescription LOCATION_POINT = new PointDescription(POINT_TYPE_LOCATION, "");
public PointDescription(double lat, double lon) {
this(POINT_TYPE_LOCATION, "");
this.lat = lat;
this.lon = lon;
}
public PointDescription(String type, String name) {
this.type = type;
this.name = name;
if (this.name == null) {
this.name = "";
}
}
public PointDescription(String type, String typeName, String name) {
this.type = type;
this.name = name;
this.typeName = typeName;
if (this.name == null) {
this.name = "";
}
}
public void setLat(double lat) {
this.lat = lat;
}
public void setLon(double lon) {
this.lon = lon;
}
public void setTypeName(String typeName){
this.typeName = typeName;
}
public void setName(String name){
this.name = name;
if (this.name == null) {
this.name = "";
}
}
public String getTypeName() {
return typeName;
}
@Nullable
public String getIconName() {
return iconName;
}
public void setIconName(String iconName) {
this.iconName = iconName;
}
@NonNull
public String getName() {
return name;
}
@NonNull
public String getSimpleName(SampleApplication ctx, boolean addTypeName) {
if (isLocation()) {
if (!Algorithms.isEmpty(name) && !name.equals(ctx.getString("no_address_found"))) {
return name;
} else {
return getLocationName(ctx, lat, lon, true).replace('\n', ' ');
}
}
if (!Algorithms.isEmpty(typeName)) {
if (Algorithms.isEmpty(name)) {
return typeName;
} else if(addTypeName){
return typeName.trim() + ": " + name;
}
}
return name;
}
public String getFullPlainName(SampleApplication ctx) {
if (isLocation()) {
return getLocationName(ctx, lat, lon, false);
} else {
String typeName = this.typeName;
if (isFavorite()) {
typeName = ctx.getString("favorite");
} else if (isPoi()) {
typeName = ctx.getString("poi");
} else if (isWpt()) {
return ctx.getString("gpx_wpt");
}
if (!Algorithms.isEmpty(typeName)) {
if (Algorithms.isEmpty(name)) {
return typeName;
} else {
return typeName.trim() + ": " + name;
}
}
return name;
}
}
public static String getLocationName(SampleApplication ctx, double lat, double lon, boolean sh) {
SampleApplication app = SampleApplication.getApp(ctx);
int f = app.getCoordinatesFormat();
if (f == PointDescription.UTM_FORMAT) {
UTMPoint pnt = new UTMPoint(new LatLonPoint(lat, lon));
return pnt.zone_number + "" + pnt.zone_letter + " " + ((long) pnt.easting) + " "
+ ((long) pnt.northing);
} else {
try {
return ctx.getString(sh ? "short_location_on_map" : "location_on_map", LocationConvert.convert(lat, f),
LocationConvert.convert(lon, f));
} catch(RuntimeException e) {
e.printStackTrace();
return ctx.getString(sh ? "short_location_on_map" : "location_on_map", 0, 0);
}
}
}
public static String getLocationNamePlain(Context ctx, double lat, double lon) {
SampleApplication app = SampleApplication.getApp(ctx);
int f = app.getCoordinatesFormat();
if (f == PointDescription.UTM_FORMAT) {
UTMPoint pnt = new UTMPoint(new LatLonPoint(lat, lon));
return pnt.zone_number + "" + pnt.zone_letter + " " + ((long) pnt.easting) + " "
+ ((long) pnt.northing);
} else {
try {
return LocationConvert.convert(lat, f) + ", " + LocationConvert.convert(lon, f);
} catch(RuntimeException e) {
e.printStackTrace();
return "0, 0";
}
}
}
public boolean contextMenuDisabled() {
return POINT_TYPE_WORLD_REGION_SHOW_ON_MAP.equals(type);
}
public boolean isLocation() {
return POINT_TYPE_LOCATION.equals(type);
}
public boolean isAddress() {
return POINT_TYPE_ADDRESS.equals(type);
}
public boolean isWpt() {
return POINT_TYPE_WPT.equals(type);
}
public boolean isPoi() {
return POINT_TYPE_POI.equals(type);
}
public boolean isFavorite() {
return POINT_TYPE_FAVORITE.equals(type);
}
public boolean isAudioNote() {
return POINT_TYPE_AUDIO_NOTE.equals(type);
}
public boolean isVideoNote() {
return POINT_TYPE_VIDEO_NOTE.equals(type);
}
public boolean isPhotoNote() {
return POINT_TYPE_PHOTO_NOTE.equals(type);
}
public boolean isDestination() {
return POINT_TYPE_TARGET.equals(type);
}
public boolean isMapMarker() {
return POINT_TYPE_MAP_MARKER.equals(type);
}
public boolean isParking() {
return POINT_TYPE_PARKING_MARKER.equals(type);
}
public boolean isMyLocation() {
return POINT_TYPE_MY_LOCATION.equals(type);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((typeName == null) ? 0 : typeName.hashCode());
result = prime * result + ((lat == 0) ? 0 : new Double(lat).hashCode());
result = prime * result + ((lon == 0) ? 0 : new Double(lon).hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
PointDescription other = (PointDescription) obj;
if (Algorithms.objectEquals(other.name, name)
&& Algorithms.objectEquals(other.type, type)
&& Algorithms.objectEquals(other.lat, lat)
&& Algorithms.objectEquals(other.lon, lon)
&& Algorithms.objectEquals(other.typeName, typeName)) {
return true;
}
return false;
}
public static String getSimpleName(LocationPoint o, SampleApplication ctx) {
PointDescription pd = o.getPointDescription(ctx);
return pd.getSimpleName(ctx, true);
// return o.getPointDescription(ctx).getFullPlainName(ctx, o.getLatitude(), o.getLongitude());
}
public boolean isSearchingAddress(SampleApplication ctx) {
return !Algorithms.isEmpty(name) && isLocation() && name.equals(getSearchAddressStr(ctx));
}
public static String getSearchAddressStr(SampleApplication ctx) {
return ctx.getString("looking_up_address") + ctx.getString("shared_string_ellipsis");
}
public static String getAddressNotFoundStr(SampleApplication ctx) {
return ctx.getString("no_address_found");
}
public static String serializeToString(PointDescription p) {
if (p == null) {
return "";
}
String tp = p.type ;
if(!Algorithms.isEmpty(p.typeName)) {
tp = tp +'.' + p.typeName;
}
String res = tp + "#" + p.name;
if (!Algorithms.isEmpty(p.iconName)) {
res += "#" + p.iconName;
}
return res;
}
public static PointDescription deserializeFromString(String s, LatLon l) {
PointDescription pd = null ;
if (s != null && s.length() > 0) {
int in = s.indexOf('#');
if (in >= 0) {
int ii = s.indexOf('#', in + 1);
String name;
String icon = null;
if (ii > 0) {
name = s.substring(in + 1, ii).trim();
icon = s.substring(ii + 1).trim();
} else {
name = s.substring(in + 1).trim();
}
String tp = s.substring(0, in);
if(tp.contains(".")) {
pd = new PointDescription(tp.substring(0, tp.indexOf('.')), tp.substring(tp.indexOf('.') + 1), name);
} else {
pd = new PointDescription(tp, name);
}
if (!Algorithms.isEmpty(icon)) {
pd.setIconName(icon);
}
}
}
if(pd == null) {
pd = new PointDescription(POINT_TYPE_LOCATION, "");
}
if(pd.isLocation() && l != null) {
pd.setLat(l.getLatitude());
pd.setLon(l.getLongitude());
}
return pd;
}
public static final int FORMAT_DEGREES = LocationConvert.FORMAT_DEGREES;
public static final int FORMAT_MINUTES = LocationConvert.FORMAT_MINUTES;
public static final int FORMAT_SECONDS = LocationConvert.FORMAT_SECONDS;
public static final int UTM_FORMAT = LocationConvert.UTM_FORMAT;
public static String formatToHumanString(SampleApplication ctx, int format) {
switch (format) {
case LocationConvert.FORMAT_DEGREES:
return ctx.getString("navigate_point_format_D");
case LocationConvert.FORMAT_MINUTES:
return ctx.getString("navigate_point_format_DM");
case LocationConvert.FORMAT_SECONDS:
return ctx.getString("navigate_point_format_DMS");
case LocationConvert.UTM_FORMAT:
return "UTM";
default:
return "Unknown format";
}
}
}

View file

@ -0,0 +1,961 @@
package net.osmand.core.samples.android.sample1.search;
import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import net.osmand.AndroidUtils;
import net.osmand.Location;
import net.osmand.ResultMatcher;
import net.osmand.core.samples.android.sample1.MainActivity;
import net.osmand.core.samples.android.sample1.R;
import net.osmand.core.samples.android.sample1.SampleApplication;
import net.osmand.core.samples.android.sample1.SampleFormatter;
import net.osmand.core.samples.android.sample1.SampleLocationProvider.SampleCompassListener;
import net.osmand.core.samples.android.sample1.SampleLocationProvider.SampleLocationListener;
import net.osmand.core.samples.android.sample1.data.PointDescription;
import net.osmand.data.LatLon;
import net.osmand.osm.PoiCategory;
import net.osmand.search.SearchUICore;
import net.osmand.search.SearchUICore.SearchResultCollection;
import net.osmand.search.core.ObjectType;
import net.osmand.search.core.SearchCoreAPI;
import net.osmand.search.core.SearchCoreFactory.SearchAmenityTypesAPI;
import net.osmand.search.core.SearchPhrase;
import net.osmand.search.core.SearchResult;
import net.osmand.search.core.SearchSettings;
import net.osmand.search.core.SearchWord;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.search.core.ObjectType.POI_TYPE;
import static net.osmand.search.core.SearchCoreFactory.SEARCH_AMENITY_TYPE_PRIORITY;
public class QuickSearchDialogFragment extends DialogFragment implements SampleCompassListener, SampleLocationListener {
public static final String TAG = "QuickSearchDialogFragment";
private static final String QUICK_SEARCH_QUERY_KEY = "quick_search_query_key";
private static final String QUICK_SEARCH_LAT_KEY = "quick_search_lat_key";
private static final String QUICK_SEARCH_LON_KEY = "quick_search_lon_key";
private static final String QUICK_SEARCH_INTERRUPTED_SEARCH_KEY = "quick_search_interrupted_search_key";
private static final String QUICK_SEARCH_SHOW_CATEGORIES_KEY = "quick_search_show_categories_key";
private static final String QUICK_SEARCH_HIDDEN_KEY = "quick_search_hidden_key";
private static final String QUICK_SEARCH_TOOLBAR_TITLE_KEY = "quick_search_toolbar_title_key";
private static final String QUICK_SEARCH_TOOLBAR_VISIBLE_KEY = "quick_search_toolbar_visible_key";
private static final String QUICK_SEARCH_RUN_SEARCH_FIRST_TIME_KEY = "quick_search_run_search_first_time_key";
private static final String QUICK_SEARCH_PHRASE_DEFINED_KEY = "quick_search_phrase_defined_key";
private Toolbar toolbar;
private View searchView;
private View buttonToolbarView;
private ImageView buttonToolbarImage;
private TextView buttonToolbarText;
private QuickSearchMainListFragment mainSearchFragment;
private QuickSearchCategoriesListFragment categoriesSearchFragment;
//private QuickSearchToolbarController toolbarController;
private EditText searchEditText;
private ProgressBar progressBar;
private ImageButton clearButton;
private SampleApplication app;
private QuickSearchHelper searchHelper;
private SearchUICore searchUICore;
private String searchQuery;
private LatLon centerLatLon;
private Location location = null;
private Float heading = null;
private boolean useMapCenter;
private boolean paused;
private boolean cancelPrev;
private boolean searching;
private boolean hidden;
private String toolbarTitle;
private boolean toolbarVisible;
private boolean newSearch;
private boolean interruptedSearch;
private long hideTimeMs;
private boolean runSearchFirstTime;
private boolean phraseDefined;
private static final double DISTANCE_THRESHOLD = 70000; // 70km
private static final int EXPIRATION_TIME_MIN = 10; // 10 minutes
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = getMyApplication();
setStyle(STYLE_NO_FRAME, R.style.AppTheme);
}
@Override
@SuppressLint("PrivateResource, ValidFragment")
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final MainActivity mainActivity = getMainActivity();
final View view = inflater.inflate(R.layout.search_dialog_fragment, container, false);
/*
toolbarController = new QuickSearchToolbarController();
toolbarController.setOnBackButtonClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mainActivity.showQuickSearch(ShowQuickSearchMode.CURRENT, false);
}
});
toolbarController.setOnTitleClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mainActivity.showQuickSearch(ShowQuickSearchMode.CURRENT, false);
}
});
toolbarController.setOnCloseButtonClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mainActivity.closeQuickSearch();
}
});
*/
Bundle arguments = getArguments();
if (savedInstanceState != null) {
searchQuery = savedInstanceState.getString(QUICK_SEARCH_QUERY_KEY);
double lat = savedInstanceState.getDouble(QUICK_SEARCH_LAT_KEY, Double.NaN);
double lon = savedInstanceState.getDouble(QUICK_SEARCH_LON_KEY, Double.NaN);
if (!Double.isNaN(lat) && !Double.isNaN(lon)) {
centerLatLon = new LatLon(lat, lon);
}
interruptedSearch = savedInstanceState.getBoolean(QUICK_SEARCH_INTERRUPTED_SEARCH_KEY, false);
hidden = savedInstanceState.getBoolean(QUICK_SEARCH_HIDDEN_KEY, false);
toolbarTitle = savedInstanceState.getString(QUICK_SEARCH_TOOLBAR_TITLE_KEY);
toolbarVisible = savedInstanceState.getBoolean(QUICK_SEARCH_TOOLBAR_VISIBLE_KEY, false);
}
if (searchQuery == null && arguments != null) {
searchQuery = arguments.getString(QUICK_SEARCH_QUERY_KEY);
runSearchFirstTime = arguments.getBoolean(QUICK_SEARCH_RUN_SEARCH_FIRST_TIME_KEY, false);
phraseDefined = arguments.getBoolean(QUICK_SEARCH_PHRASE_DEFINED_KEY, false);
double lat = arguments.getDouble(QUICK_SEARCH_LAT_KEY, Double.NaN);
double lon = arguments.getDouble(QUICK_SEARCH_LON_KEY, Double.NaN);
if (!Double.isNaN(lat) && !Double.isNaN(lon)) {
centerLatLon = new LatLon(lat, lon);
}
newSearch = true;
}
if (searchQuery == null)
searchQuery = "";
boolean showCategories = false;
if (arguments != null) {
showCategories = arguments.getBoolean(QUICK_SEARCH_SHOW_CATEGORIES_KEY, false);
}
searchView = view.findViewById(R.id.search_view);
buttonToolbarView = view.findViewById(R.id.button_toolbar_layout);
buttonToolbarImage = (ImageView) view.findViewById(R.id.buttonToolbarImage);
buttonToolbarImage.setImageDrawable(app.getIconsCache().getThemedIcon("ic_action_marker_dark"));
buttonToolbarText = (TextView) view.findViewById(R.id.buttonToolbarTitle);
view.findViewById(R.id.buttonToolbar).setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
SearchPhrase searchPhrase = searchUICore.getPhrase();
if (!searchPhrase.isNoSelectedType() && !searchPhrase.isLastWord(POI_TYPE)) {
SearchWord word = searchPhrase.getLastSelectedWord();
if (word != null && word.getLocation() != null) {
SearchResult searchResult = word.getResult();
String name = QuickSearchListItem.getName(app, searchResult);
String typeName = QuickSearchListItem.getTypeName(app, searchResult);
PointDescription pointDescription = new PointDescription(PointDescription.POINT_TYPE_ADDRESS, typeName, name);
mainActivity.showOnMap(searchResult.location, searchResult.preferredZoom);
/* todo
app.getSettings().setMapLocationToShow(
searchResult.location.getLatitude(), searchResult.location.getLongitude(),
searchResult.preferredZoom, pointDescription, true, searchResult.object);
hideToolbar();
MainActivity.launchMainActivityMoveToTop(getActivity());
*/
hide();
}
}
}
}
);
toolbar = (Toolbar) view.findViewById(R.id.toolbar);
toolbar.setNavigationIcon(app.getIconsCache().getThemedIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha));
toolbar.setNavigationContentDescription(app.getString("access_shared_string_navigate_up"));
toolbar.setNavigationOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
}
);
searchEditText = (EditText) view.findViewById(R.id.searchEditText);
searchEditText.addTextChangedListener(
new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
String newQueryText = s.toString();
updateClearButtonAndHint();
updateClearButtonVisibility(true);
boolean textEmpty = newQueryText.length() == 0;
updateTabbarVisibility(textEmpty);
if (!searchQuery.equalsIgnoreCase(newQueryText)) {
searchQuery = newQueryText;
if (Algorithms.isEmpty(searchQuery)) {
searchUICore.resetPhrase();
} else {
runSearch();
}
} else if (runSearchFirstTime) {
runSearchFirstTime = false;
runSearch();
}
}
}
);
progressBar = (ProgressBar) view.findViewById(R.id.searchProgressBar);
clearButton = (ImageButton) view.findViewById(R.id.clearButton);
clearButton.setImageDrawable(app.getIconsCache().getThemedIcon(R.drawable.ic_action_remove_dark));
clearButton.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
if (searchEditText.getText().length() > 0) {
String newText = searchUICore.getPhrase().getTextWithoutLastWord();
searchEditText.setText(newText);
searchEditText.setSelection(newText.length());
} else if (useMapCenter && location != null) {
useMapCenter = false;
centerLatLon = null;
updateUseMapCenterUI();
LatLon centerLatLon = new LatLon(location.getLatitude(), location.getLongitude());
SearchSettings ss = searchUICore.getSearchSettings().setOriginalLocation(
new LatLon(centerLatLon.getLatitude(), centerLatLon.getLongitude()));
searchUICore.updateSettings(ss);
updateClearButtonAndHint();
updateClearButtonVisibility(true);
startLocationUpdate();
}
updateToolbarButton();
}
}
);
setupSearch(mainActivity);
return view;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
updateToolbarButton();
updateClearButtonAndHint();
updateClearButtonVisibility(true);
addMainSearchFragment();
if (centerLatLon == null) {
searchEditText.requestFocus();
AndroidUtils.softKeyboardDelayed(searchEditText);
}
}
public void restoreToolbar() {
if (toolbarVisible) {
if (toolbarTitle != null) {
showToolbar(toolbarTitle);
} else {
showToolbar();
}
}
}
public void showToolbar() {
showToolbar(getText());
}
public void showToolbar(String title) {
toolbarVisible = true;
toolbarTitle = title;
//todo
//toolbarController.setTitle(toolbarTitle);
//getMainActivity().showTopToolbar(toolbarController);
}
public void hideToolbar() {
toolbarVisible = false;
//getMainActivity().hideTopToolbar(toolbarController); todo
}
public String getText() {
return searchEditText.getText().toString();
}
public void hideKeyboard() {
if (searchEditText.hasFocus()) {
AndroidUtils.hideSoftKeyboard(getActivity(), searchEditText);
}
}
public boolean isSearchHidden() {
return hidden;
}
public boolean isExpired() {
return hideTimeMs > 0 && System.currentTimeMillis() - hideTimeMs > EXPIRATION_TIME_MIN * 60 * 1000;
}
public void show() {
if (useMapCenter) {
LatLon mapCenter = getMainActivity().getScreenCenter();
SearchSettings ss = searchUICore.getSearchSettings().setOriginalLocation(
new LatLon(mapCenter.getLatitude(), mapCenter.getLongitude()));
searchUICore.updateSettings(ss);
updateUseMapCenterUI();
updateLocationUI(mapCenter, null);
}
getDialog().show();
paused = false;
hidden = false;
if (interruptedSearch) {
interruptedSearch = false;
addMoreButton();
}
}
public void hide() {
paused = true;
hidden = true;
hideTimeMs = System.currentTimeMillis();
interruptedSearch = searching;
searching = false;
hideProgressBar();
updateClearButtonVisibility(true);
getDialog().hide();
}
public void closeSearch() {
dismiss();
}
public void addMainSearchFragment() {
mainSearchFragment = (QuickSearchMainListFragment) Fragment.instantiate(this.getContext(), QuickSearchMainListFragment.class.getName());
FragmentManager childFragMan = getChildFragmentManager();
FragmentTransaction childFragTrans = childFragMan.beginTransaction();
childFragTrans.replace(R.id.search_view, mainSearchFragment);
childFragTrans.commit();
}
private void updateToolbarButton() {
SearchWord word = searchUICore.getPhrase().getLastSelectedWord();
if (searchEditText.getText().length() > 0) {
if (word != null && word.getResult() != null) {
buttonToolbarText.setText(app.getString("show_something_on_map", word.getResult().localeName).toUpperCase());
} else {
buttonToolbarText.setText(app.getString("shared_string_show_on_map").toUpperCase());
}
} else {
buttonToolbarText.setText(app.getString("shared_string_show_on_map").toUpperCase());
}
}
private void setupSearch(final MainActivity mainActivity) {
// Setup search core
String locale = ""; //app.getSettings().MAP_PREFERRED_LOCALE.get();
boolean transliterate = false; //app.getSettings().MAP_TRANSLITERATE_NAMES.get();
searchHelper = app.getSearchUICore();
searchUICore = searchHelper.getCore();
if (newSearch) {
setResultCollection(null);
if (!phraseDefined) {
searchUICore.resetPhrase();
}
phraseDefined = false;
}
location = app.getLocationProvider().getLastKnownLocation();
LatLon searchLatLon;
if (centerLatLon == null) {
LatLon clt = mainActivity.getScreenCenter();
searchLatLon = clt;
searchEditText.setHint(app.getString("search_poi_category_hint"));
if (location != null) {
double d = MapUtils.getDistance(clt, location.getLatitude(), location.getLongitude());
if (d < DISTANCE_THRESHOLD) {
searchLatLon = new LatLon(location.getLatitude(), location.getLongitude());
} else {
useMapCenter = true;
}
} else {
useMapCenter = true;
}
} else {
searchLatLon = centerLatLon;
useMapCenter = true;
}
SearchSettings settings = searchUICore.getSearchSettings().setOriginalLocation(
new LatLon(searchLatLon.getLatitude(), searchLatLon.getLongitude()));
settings = settings.setLang(locale, transliterate);
searchUICore.updateSettings(settings);
searchUICore.setOnSearchStart(new Runnable() {
@Override
public void run() {
cancelPrev = false;
}
});
searchUICore.setOnResultsComplete(new Runnable() {
@Override
public void run() {
app.runInUIThread(new Runnable() {
@Override
public void run() {
searching = false;
if (!paused && !cancelPrev) {
hideProgressBar();
if (searchUICore.isSearchMoreAvailable(searchUICore.getPhrase())) {
addMoreButton();
}
}
}
});
}
});
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setShowsDialog(true);
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString(QUICK_SEARCH_QUERY_KEY, searchQuery);
outState.putBoolean(QUICK_SEARCH_INTERRUPTED_SEARCH_KEY, interruptedSearch = searching);
outState.putBoolean(QUICK_SEARCH_HIDDEN_KEY, hidden);
if (toolbarTitle != null) {
outState.putString(QUICK_SEARCH_TOOLBAR_TITLE_KEY, toolbarTitle);
}
outState.putBoolean(QUICK_SEARCH_TOOLBAR_VISIBLE_KEY, toolbarVisible);
if (centerLatLon != null) {
outState.putDouble(QUICK_SEARCH_LAT_KEY, centerLatLon.getLatitude());
outState.putDouble(QUICK_SEARCH_LON_KEY, centerLatLon.getLongitude());
}
}
@Override
public void onResume() {
super.onResume();
if (!useMapCenter) {
startLocationUpdate();
}
paused = false;
}
@Override
public void onPause() {
super.onPause();
paused = true;
hideTimeMs = System.currentTimeMillis();
stopLocationUpdate();
hideProgressBar();
}
@Override
public void onDismiss(DialogInterface dialog) {
MainActivity mainActivity = getMainActivity();
if (mainActivity != null) {
hideToolbar();
getChildFragmentManager().popBackStack();
}
super.onDismiss(dialog);
}
public Toolbar getToolbar() {
return toolbar;
}
public boolean isUseMapCenter() {
return useMapCenter;
}
private void startLocationUpdate() {
app.getLocationProvider().addCompassListener(this);
app.getLocationProvider().addLocationListener(this);
location = app.getLocationProvider().getLastKnownLocation();
updateLocation(location);
}
private void stopLocationUpdate() {
app.getLocationProvider().removeLocationListener(this);
app.getLocationProvider().removeCompassListener(this);
}
private void showProgressBar() {
updateClearButtonVisibility(false);
progressBar.setVisibility(View.VISIBLE);
}
private void hideProgressBar() {
updateClearButtonVisibility(true);
progressBar.setVisibility(View.GONE);
}
private void updateClearButtonAndHint() {
if (useMapCenter && location != null && searchEditText.length() == 0) {
LatLon latLon = searchUICore.getSearchSettings().getOriginalLocation();
double d = MapUtils.getDistance(latLon, location.getLatitude(), location.getLongitude());
String dist = SampleFormatter.getFormattedDistance((float) d, app);
searchEditText.setHint(app.getString("dist_away_from_my_location", dist));
clearButton.setImageDrawable(app.getIconsCache().getIcon("ic_action_get_my_location", R.color.color_myloc_distance));
} else {
searchEditText.setHint(app.getString("search_poi_category_hint"));
clearButton.setImageDrawable(app.getIconsCache().getThemedIcon(R.drawable.ic_action_remove_dark));
}
}
private void updateClearButtonVisibility(boolean show) {
if (show) {
clearButton.setVisibility(searchEditText.length() > 0 || (useMapCenter && location != null) ? View.VISIBLE : View.GONE);
} else {
clearButton.setVisibility(View.GONE);
}
}
private void updateTabbarVisibility(boolean show) {
if (show) {
buttonToolbarView.setVisibility(View.GONE);
searchView.setVisibility(View.GONE);
} else {
buttonToolbarView.setVisibility(View.VISIBLE);
searchView.setVisibility(View.VISIBLE);
}
}
public void setResultCollection(SearchResultCollection resultCollection) {
searchHelper.setResultCollection(resultCollection);
}
public SearchResultCollection getResultCollection() {
return searchHelper.getResultCollection();
}
public void onSearchListFragmentResume(QuickSearchListFragment searchListFragment) {
switch (searchListFragment.getType()) {
case CATEGORIES:
categoriesSearchFragment = (QuickSearchCategoriesListFragment) searchListFragment;
reloadCategories();
break;
case MAIN:
if (!Algorithms.isEmpty(searchQuery)) {
searchEditText.setText(searchQuery);
searchEditText.setSelection(searchQuery.length());
}
if (getResultCollection() != null) {
updateSearchResult(getResultCollection(), false);
if (interruptedSearch || searchUICore.isSearchMoreAvailable(searchUICore.getPhrase())) {
addMoreButton();
}
}
break;
}
LatLon mapCenter = getMainActivity().getScreenCenter();
if (useMapCenter) {
updateUseMapCenterUI();
searchListFragment.updateLocation(mapCenter, null);
}
}
public void reloadCategories() {
try {
SearchResultCollection res = searchUICore.shallowSearch(SearchAmenityTypesAPI.class,
"", null);
if (res != null) {
List<QuickSearchListItem> rows = new ArrayList<>();
for (SearchResult sr : res.getCurrentSearchResults()) {
rows.add(new QuickSearchListItem(app, sr));
}
categoriesSearchFragment.updateListAdapter(rows, false);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void runSearch() {
runSearch(searchQuery);
}
private void runSearch(String text) {
showProgressBar();
SearchSettings settings = searchUICore.getPhrase().getSettings();
if (settings.getRadiusLevel() != 1) {
searchUICore.updateSettings(settings.setRadiusLevel(1));
}
runCoreSearch(text, true, false);
}
private void runCoreSearch(final String text, final boolean updateResult, final boolean searchMore) {
showProgressBar();
updateToolbarButton();
interruptedSearch = false;
searching = true;
cancelPrev = true;
runCoreSearchInternal(text, updateResult, searchMore);
}
private void runCoreSearchInternal(String text, boolean updateResult, boolean searchMore) {
SearchResultCollection c = searchUICore.search(text, new ResultMatcher<SearchResult>() {
SearchResultCollection regionResultCollection = null;
SearchCoreAPI regionResultApi = null;
List<SearchResult> results = new ArrayList<>();
@Override
public boolean publish(SearchResult object) {
if (paused || cancelPrev) {
if (results.size() > 0) {
getResultCollection().addSearchResults(results, true, true);
}
return false;
}
switch (object.objectType) {
case SEARCH_API_FINISHED:
final SearchCoreAPI searchApi = (SearchCoreAPI) object.object;
final List<SearchResult> apiResults;
final SearchPhrase phrase = object.requiredSearchPhrase;
final SearchCoreAPI regionApi = regionResultApi;
final SearchResultCollection regionCollection = regionResultCollection;
final boolean hasRegionCollection = (searchApi == regionApi && regionCollection != null);
if (hasRegionCollection) {
apiResults = regionCollection.getCurrentSearchResults();
} else {
apiResults = results;
}
regionResultApi = null;
regionResultCollection = null;
results = new ArrayList<>();
showApiResults(apiResults, phrase, hasRegionCollection);
break;
case SEARCH_API_REGION_FINISHED:
regionResultApi = (SearchCoreAPI) object.object;
final SearchPhrase regionPhrase = object.requiredSearchPhrase;
regionResultCollection =
new SearchResultCollection(regionPhrase).addSearchResults(results, true, true);
showRegionResults(regionResultCollection);
break;
case PARTIAL_LOCATION:
showLocationToolbar();
break;
default:
results.add(object);
}
return false;
}
@Override
public boolean isCancelled() {
return paused || cancelPrev;
}
});
if (!searchMore) {
setResultCollection(null);
if (!updateResult) {
updateSearchResult(null, false);
}
}
if (updateResult) {
updateSearchResult(c, false);
}
}
private void showLocationToolbar() {
app.runInUIThread(new Runnable() {
@Override
public void run() {
updateToolbarButton();
}
});
}
private void showApiResults(final List<SearchResult> apiResults, final SearchPhrase phrase,
final boolean hasRegionCollection) {
app.runInUIThread(new Runnable() {
@Override
public void run() {
if (!paused && !cancelPrev) {
boolean append = getResultCollection() != null;
if (append) {
getResultCollection().addSearchResults(apiResults, true, true);
} else {
SearchResultCollection resCollection = new SearchResultCollection(phrase);
resCollection.addSearchResults(apiResults, true, true);
setResultCollection(resCollection);
}
if (!hasRegionCollection) {
updateSearchResult(getResultCollection(), append);
}
}
}
});
}
private void showRegionResults(final SearchResultCollection regionResultCollection) {
app.runInUIThread(new Runnable() {
@Override
public void run() {
if (!paused && !cancelPrev) {
if (getResultCollection() != null) {
SearchResultCollection resCollection =
getResultCollection().combineWithCollection(regionResultCollection, true, true);
updateSearchResult(resCollection, true);
} else {
updateSearchResult(regionResultCollection, false);
}
}
}
});
}
public void completeQueryWithObject(SearchResult sr) {
searchUICore.selectSearchResult(sr);
String txt = searchUICore.getPhrase().getText(true);
searchQuery = txt;
searchEditText.setText(txt);
searchEditText.setSelection(txt.length());
updateToolbarButton();
SearchSettings settings = searchUICore.getPhrase().getSettings();
if (settings.getRadiusLevel() != 1) {
searchUICore.updateSettings(settings.setRadiusLevel(1));
}
runCoreSearch(txt, false, false);
}
public void clearLastWord() {
if (searchEditText.getText().length() > 0) {
String newText = searchUICore.getPhrase().getTextWithoutLastWord();
searchEditText.setText(newText);
searchEditText.setSelection(newText.length());
}
}
private void addMoreButton() {
QuickSearchMoreListItem moreListItem =
new QuickSearchMoreListItem(app, app.getString("search_POI_level_btn").toUpperCase(), new OnClickListener() {
@Override
public void onClick(View v) {
if (!interruptedSearch) {
SearchSettings settings = searchUICore.getPhrase().getSettings();
searchUICore.updateSettings(settings.setRadiusLevel(settings.getRadiusLevel() + 1));
}
runCoreSearch(searchQuery, false, true);
}
});
if (!paused && !cancelPrev && mainSearchFragment != null) {
mainSearchFragment.addListItem(moreListItem);
}
}
private void updateSearchResult(SearchResultCollection res, boolean append) {
if (!paused && mainSearchFragment != null) {
List<QuickSearchListItem> rows = new ArrayList<>();
if (res != null && res.getCurrentSearchResults().size() > 0) {
for (final SearchResult sr : res.getCurrentSearchResults()) {
rows.add(new QuickSearchListItem(app, sr));
}
}
mainSearchFragment.updateListAdapter(rows, append);
}
}
public static boolean showInstance(@NonNull MainActivity mainActivity,
@NonNull String searchQuery,
@Nullable Object object,
boolean showCategories,
@Nullable LatLon latLon) {
try {
Bundle bundle = new Bundle();
if (object != null) {
bundle.putBoolean(QUICK_SEARCH_RUN_SEARCH_FIRST_TIME_KEY, true);
String objectLocalizedName = searchQuery;
if (object instanceof PoiCategory) {
PoiCategory c = (PoiCategory) object;
objectLocalizedName = c.getTranslation();
SearchUICore searchUICore = mainActivity.getMyApplication().getSearchUICore().getCore();
SearchPhrase phrase = searchUICore.resetPhrase(objectLocalizedName + " ");
SearchResult sr = new SearchResult(phrase);
sr.localeName = objectLocalizedName;
sr.object = c;
sr.priority = SEARCH_AMENITY_TYPE_PRIORITY;
sr.priorityDistance = 0;
sr.objectType = ObjectType.POI_TYPE;
searchUICore.selectSearchResult(sr);
bundle.putBoolean(QUICK_SEARCH_PHRASE_DEFINED_KEY, true);
}
searchQuery = objectLocalizedName.trim() + " ";
} else if (!Algorithms.isEmpty(searchQuery)) {
bundle.putBoolean(QUICK_SEARCH_RUN_SEARCH_FIRST_TIME_KEY, true);
}
bundle.putString(QUICK_SEARCH_QUERY_KEY, searchQuery);
bundle.putBoolean(QUICK_SEARCH_SHOW_CATEGORIES_KEY, showCategories);
if (latLon != null) {
bundle.putDouble(QUICK_SEARCH_LAT_KEY, latLon.getLatitude());
bundle.putDouble(QUICK_SEARCH_LON_KEY, latLon.getLongitude());
}
QuickSearchDialogFragment fragment = new QuickSearchDialogFragment();
fragment.setArguments(bundle);
fragment.show(mainActivity.getSupportFragmentManager(), TAG);
return true;
} catch (RuntimeException e) {
return false;
}
}
private MainActivity getMainActivity() {
return (MainActivity) getActivity();
}
private SampleApplication getMyApplication() {
return (SampleApplication) getActivity().getApplication();
}
@Override
public void updateCompassValue(final float value) {
// 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) {
final Location location = this.location;
app.runInUIThread(new Runnable() {
@Override
public void run() {
updateLocationUI(location, value);
}
});
} else {
heading = lastHeading;
}
}
@Override
public void updateLocation(final Location location) {
final Float heading = this.heading;
app.runInUIThread(new Runnable() {
@Override
public void run() {
updateLocationUI(location, heading);
}
});
}
private void updateLocationUI(Location location, Float heading) {
this.location = location;
LatLon latLon = null;
if (location != null) {
latLon = new LatLon(location.getLatitude(), location.getLongitude());
}
updateLocationUI(latLon, heading);
}
private void updateLocationUI(LatLon latLon, Float heading) {
if (latLon != null && !paused && !cancelPrev) {
if (mainSearchFragment != null && searchView.getVisibility() == View.VISIBLE) {
mainSearchFragment.updateLocation(latLon, heading);
} else if (categoriesSearchFragment != null) {
categoriesSearchFragment.updateLocation(latLon, heading);
}
}
}
private void updateUseMapCenterUI() {
if (!paused && !cancelPrev) {
if (mainSearchFragment != null) {
mainSearchFragment.getListAdapter().setUseMapCenter(useMapCenter);
}
if (categoriesSearchFragment != null) {
categoriesSearchFragment.getListAdapter().setUseMapCenter(useMapCenter);
}
}
}
public static class QuickSearchCategoriesListFragment extends QuickSearchListFragment {
@Override
public SearchListFragmentType getType() {
return SearchListFragmentType.CATEGORIES;
}
}
public static class QuickSearchMainListFragment extends QuickSearchListFragment {
@Override
public SearchListFragmentType getType() {
return SearchListFragmentType.MAIN;
}
}
/*
public static class QuickSearchToolbarController extends TopToolbarController {
public QuickSearchToolbarController() {
super(TopToolbarControllerType.QUICK_SEARCH);
}
}
*/
}

View file

@ -0,0 +1,80 @@
package net.osmand.core.samples.android.sample1.search;
import net.osmand.IndexConstants;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.core.samples.android.sample1.SampleApplication;
import net.osmand.search.SearchUICore;
import net.osmand.search.SearchUICore.SearchResultCollection;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class QuickSearchHelper {
private SampleApplication app;
private SearchUICore core;
private SearchResultCollection resultCollection;
public QuickSearchHelper(SampleApplication app) {
this.app = app;
core = new SearchUICore(app.getPoiTypes(), SampleApplication.LANGUAGE, false);
}
public SearchUICore getCore() {
return core;
}
public SearchResultCollection getResultCollection() {
return resultCollection;
}
public void setResultCollection(SearchResultCollection resultCollection) {
this.resultCollection = resultCollection;
}
public void initSearchUICore() {
setRepositoriesForSearchUICore(app);
core.setPoiTypes(app.getPoiTypes());
core.init();
}
public void setRepositoriesForSearchUICore(final SampleApplication app) {
ArrayList<File> files = new ArrayList<File>();
File appPath = app.getAppPath(null);
collectFiles(appPath, IndexConstants.BINARY_MAP_INDEX_EXT, files);
collectFiles(app.getAppPath(IndexConstants.WIKI_INDEX_DIR), IndexConstants.BINARY_MAP_INDEX_EXT, files);
List<BinaryMapIndexReader> readers = new ArrayList<>();
for (File f : files) {
try {
RandomAccessFile mf = new RandomAccessFile(f.getPath(), "r");
BinaryMapIndexReader reader = new BinaryMapIndexReader(mf, f);
readers.add(reader);
} catch (IOException e) {
e.printStackTrace();
}
}
core.getSearchSettings().setOfflineIndexes(readers);
}
private List<File> collectFiles(File dir, String ext, List<File> files) {
if (dir.exists() && dir.canRead()) {
File[] lf = dir.listFiles();
if (lf == null || lf.length == 0) {
return files;
}
for (File f : lf) {
if (f.getName().endsWith(ext)) {
files.add(f);
}
}
}
return files;
}
}

View file

@ -0,0 +1,331 @@
package net.osmand.core.samples.android.sample1.search;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import net.osmand.AndroidUtils;
import net.osmand.Location;
import net.osmand.core.samples.android.sample1.R;
import net.osmand.core.samples.android.sample1.SampleApplication;
import net.osmand.core.samples.android.sample1.SampleFormatter;
import net.osmand.core.samples.android.sample1.view.DirectionDrawable;
import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
import net.osmand.search.core.SearchPhrase;
import net.osmand.util.Algorithms;
import net.osmand.util.OpeningHoursParser;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
public class QuickSearchListAdapter extends ArrayAdapter<QuickSearchListItem> {
private SampleApplication app;
private Activity activity;
private LatLon location;
private Float heading;
private boolean useMapCenter;
private int searchMoreItemPosition;
private int screenOrientation;
private int dp56;
private int dp1;
private static final int ITEM_TYPE_REGULAR = 0;
private static final int ITEM_TYPE_SEARCH_MORE = 1;
public interface OnSelectionListener {
void onUpdateSelectionMode(List<QuickSearchListItem> selectedItems);
void reloadData();
}
public QuickSearchListAdapter(SampleApplication app, Activity activity) {
super(app, R.layout.search_list_item);
this.app = app;
this.activity = activity;
dp56 = AndroidUtils.dpToPx(app, 56f);
dp1 = AndroidUtils.dpToPx(app, 1f);
}
public int getScreenOrientation() {
return screenOrientation;
}
public void setScreenOrientation(int screenOrientation) {
this.screenOrientation = screenOrientation;
}
public LatLon getLocation() {
return location;
}
public void setLocation(LatLon location) {
this.location = location;
}
public Float getHeading() {
return heading;
}
public void setHeading(Float heading) {
this.heading = heading;
}
public boolean isUseMapCenter() {
return useMapCenter;
}
public void setUseMapCenter(boolean useMapCenter) {
this.useMapCenter = useMapCenter;
}
public void setListItems(List<QuickSearchListItem> items) {
setNotifyOnChange(false);
clear();
for (QuickSearchListItem item : items) {
add(item);
}
acquireAdditionalItemsPositions();
setNotifyOnChange(true);
notifyDataSetChanged();
}
public void addListItem(QuickSearchListItem item) {
if (searchMoreItemPosition != -1 && item instanceof QuickSearchMoreListItem) {
return;
}
setNotifyOnChange(false);
add(item);
acquireAdditionalItemsPositions();
setNotifyOnChange(true);
notifyDataSetChanged();
}
public void insertListItem(QuickSearchListItem item, int index) {
setNotifyOnChange(false);
insert(item, index);
acquireAdditionalItemsPositions();
setNotifyOnChange(true);
notifyDataSetChanged();
}
private void acquireAdditionalItemsPositions() {
searchMoreItemPosition = -1;
if (getCount() > 0) {
QuickSearchListItem first = getItem(0);
QuickSearchListItem last = getItem(getCount() - 1);
searchMoreItemPosition = last instanceof QuickSearchMoreListItem ? getCount() - 1 : -1;
}
}
@Override
public QuickSearchListItem getItem(int position) {
return super.getItem(position);
}
@Override
public int getItemViewType(int position) {
if (position == searchMoreItemPosition) {
return ITEM_TYPE_SEARCH_MORE;
} else {
return ITEM_TYPE_REGULAR;
}
}
@Override
public int getViewTypeCount() {
return 4;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final QuickSearchListItem listItem = getItem(position);
int viewType = getItemViewType(position);
LinearLayout view;
if (viewType == ITEM_TYPE_SEARCH_MORE) {
if (convertView == null) {
LayoutInflater inflater = activity.getLayoutInflater();
view = (LinearLayout) inflater.inflate(R.layout.search_more_list_item, null);
} else {
view = (LinearLayout) convertView;
}
((TextView) view.findViewById(R.id.title)).setText(listItem.getName());
} else {
if (convertView == null) {
LayoutInflater inflater = activity.getLayoutInflater();
view = (LinearLayout) inflater.inflate(R.layout.search_list_item, null);
} else {
view = (LinearLayout) convertView;
}
ImageView imageView = (ImageView) view.findViewById(R.id.imageView);
TextView title = (TextView) view.findViewById(R.id.title);
TextView subtitle = (TextView) view.findViewById(R.id.subtitle);
imageView.setImageDrawable(listItem.getIcon());
String name = listItem.getName();
title.setText(name);
String desc = listItem.getTypeName();
boolean hasDesc = false;
if (!Algorithms.isEmpty(desc) && !desc.equals(name)) {
subtitle.setText(desc);
subtitle.setVisibility(View.VISIBLE);
hasDesc = true;
} else {
subtitle.setVisibility(View.GONE);
}
view.findViewById(R.id.type_name_icon).setVisibility(View.GONE);
TextView timeText = (TextView) view.findViewById(R.id.time);
ImageView timeIcon = (ImageView) view.findViewById(R.id.time_icon);
if (listItem.getSearchResult().object instanceof Amenity
&& ((Amenity) listItem.getSearchResult().object).getOpeningHours() != null) {
Amenity amenity = (Amenity) listItem.getSearchResult().object;
OpeningHoursParser.OpeningHours rs = OpeningHoursParser.parseOpenedHours(amenity.getOpeningHours());
if (rs != null) {
Calendar inst = Calendar.getInstance();
inst.setTimeInMillis(System.currentTimeMillis());
boolean worksNow = rs.isOpenedForTime(inst);
inst.setTimeInMillis(System.currentTimeMillis() + 30 * 60 * 1000); // 30 minutes later
boolean worksLater = rs.isOpenedForTime(inst);
int colorId = worksNow ? worksLater ? R.color.color_ok : R.color.color_intermediate : R.color.color_warning;
timeIcon.setVisibility(View.VISIBLE);
timeText.setVisibility(View.VISIBLE);
timeIcon.setImageDrawable(app.getIconsCache().getIcon("ic_small_time", colorId));
timeText.setTextColor(app.getResources().getColor(colorId));
String rt = rs.getCurrentRuleTime(inst);
timeText.setText(rt == null ? "" : rt);
} else {
timeIcon.setVisibility(View.GONE);
timeText.setVisibility(View.GONE);
}
} else {
timeIcon.setVisibility(View.GONE);
timeText.setVisibility(View.GONE);
}
updateCompassVisibility(view, listItem);
}
view.setBackgroundColor(app.getResources().getColor(R.color.bg_color_light));
View divider = view.findViewById(R.id.divider);
if (divider != null) {
if (position == getCount() - 1) {
divider.setVisibility(View.GONE);
} else {
divider.setVisibility(View.VISIBLE);
if (position + 1 == searchMoreItemPosition) {
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp1);
p.setMargins(0, 0, 0 ,0);
divider.setLayoutParams(p);
} else {
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp1);
p.setMargins(dp56, 0, 0 ,0);
divider.setLayoutParams(p);
}
}
}
return view;
}
private void updateCompassVisibility(View view, QuickSearchListItem listItem) {
View compassView = view.findViewById(R.id.compass_layout);
Location ll = app.getLocationProvider().getLastKnownLocation();
boolean showCompass = location != null && listItem.getSearchResult().location != null;
boolean gpsFixed = ll != null && System.currentTimeMillis() - ll.getTime() < 1000 * 60 * 60 * 20;
if ((gpsFixed || useMapCenter) && showCompass) {
updateDistanceDirection(view, listItem);
compassView.setVisibility(View.VISIBLE);
} else {
if (!showCompass) {
compassView.setVisibility(View.GONE);
} else {
compassView.setVisibility(View.INVISIBLE);
}
}
}
private void updateDistanceDirection(View view, QuickSearchListItem listItem) {
TextView distanceText = (TextView) view.findViewById(R.id.distance);
ImageView direction = (ImageView) view.findViewById(R.id.direction);
SearchPhrase phrase = listItem.getSearchResult().requiredSearchPhrase;
LatLon loc = location;
if(phrase != null && useMapCenter) {
LatLon ol = phrase.getSettings().getOriginalLocation();
if(ol != null) {
loc = ol;
}
}
updateLocationView(useMapCenter, loc,
heading, direction, distanceText,
listItem.getSearchResult().location.getLatitude(),
listItem.getSearchResult().location.getLongitude(),
screenOrientation, app, activity);
}
public static void updateLocationView(boolean useCenter, LatLon fromLoc, Float h,
ImageView arrow, TextView txt, double toLat, double toLon,
int screenOrientation, SampleApplication app, Context ctx) {
updateLocationView(useCenter, fromLoc, h, arrow, 0, txt, new LatLon(toLat, toLon), screenOrientation, app, ctx, true);
}
public static void updateLocationView(boolean useCenter, LatLon fromLoc, Float h,
ImageView arrow, int arrowResId, TextView txt, LatLon toLoc,
int screenOrientation, SampleApplication app, Context ctx, boolean paint) {
float[] mes = new float[2];
if (fromLoc != null && toLoc != null) {
Location.distanceBetween(toLoc.getLatitude(), toLoc.getLongitude(), fromLoc.getLatitude(), fromLoc.getLongitude(), mes);
}
if (arrow != null) {
boolean newImage = false;
if (arrowResId == 0) {
arrowResId = R.drawable.ic_direction_arrow;
}
DirectionDrawable dd;
if(!(arrow.getDrawable() instanceof DirectionDrawable)) {
newImage = true;
dd = new DirectionDrawable(ctx, arrow.getWidth(), arrow.getHeight());
} else {
dd = (DirectionDrawable) arrow.getDrawable();
}
dd.setImage(arrowResId, useCenter ? R.color.color_distance : R.color.color_myloc_distance);
if (fromLoc == null || h == null || toLoc == null) {
dd.setAngle(0);
} else {
dd.setAngle(mes[1] - h + 180 + screenOrientation);
}
if (newImage) {
arrow.setImageDrawable(dd);
}
arrow.invalidate();
}
if (txt != null) {
if (fromLoc != null && toLoc != null) {
if (paint) {
txt.setTextColor(app.getResources().getColor(
useCenter ? R.color.color_distance : R.color.color_myloc_distance));
}
txt.setText(SampleFormatter.getFormattedDistance(mes[0], app));
} else {
txt.setText("");
}
}
}
}

View file

@ -0,0 +1,237 @@
package net.osmand.core.samples.android.sample1.search;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import net.osmand.core.samples.android.sample1.MainActivity;
import net.osmand.core.samples.android.sample1.R;
import net.osmand.core.samples.android.sample1.SampleApplication;
import net.osmand.core.samples.android.sample1.SampleFormatter;
import net.osmand.core.samples.android.sample1.SampleUtils;
import net.osmand.core.samples.android.sample1.data.PointDescription;
import net.osmand.data.Amenity;
import net.osmand.data.City;
import net.osmand.data.LatLon;
import net.osmand.data.Street;
import net.osmand.search.core.ObjectType;
import net.osmand.search.core.SearchResult;
import net.osmand.util.Algorithms;
import java.util.List;
public abstract class QuickSearchListFragment extends ListFragment {
private QuickSearchDialogFragment dialogFragment;
private QuickSearchListAdapter listAdapter;
private boolean touching;
private boolean scrolling;
enum SearchListFragmentType {
CATEGORIES,
MAIN
}
public abstract SearchListFragmentType getType();
public SampleApplication getMyApplication() {
return (SampleApplication) getActivity().getApplication();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.search_dialog_list_layout, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ListView listView = getListView();
if (listView != null) {
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
public void onScrollStateChanged(AbsListView view, int scrollState) {
scrolling = (scrollState != AbsListView.OnScrollListener.SCROLL_STATE_IDLE);
if (scrolling) {
dialogFragment.hideKeyboard();
}
}
});
View header = getLayoutInflater(savedInstanceState).inflate(R.layout.list_shadow_header, null);
View footer = getLayoutInflater(savedInstanceState).inflate(R.layout.list_shadow_footer, null);
listView.addHeaderView(header, null, false);
listView.addFooterView(footer, null, false);
}
}
@Override
public void onListItemClick(ListView l, View view, int position, long id) {
int index = position - l.getHeaderViewsCount();
if (index < listAdapter.getCount()) {
QuickSearchListItem item = listAdapter.getItem(index);
if (item != null) {
if (item instanceof QuickSearchMoreListItem) {
((QuickSearchMoreListItem) item).getOnClickListener().onClick(view);
} else {
SearchResult sr = item.getSearchResult();
if (sr.objectType == ObjectType.POI
|| sr.objectType == ObjectType.LOCATION
|| sr.objectType == ObjectType.HOUSE
|| sr.objectType == ObjectType.FAVORITE
|| sr.objectType == ObjectType.RECENT_OBJ
|| sr.objectType == ObjectType.WPT
|| sr.objectType == ObjectType.STREET_INTERSECTION) {
showOnMap(sr);
} else {
dialogFragment.completeQueryWithObject(item.getSearchResult());
}
}
}
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
dialogFragment = (QuickSearchDialogFragment) getParentFragment();
listAdapter = new QuickSearchListAdapter(getMyApplication(), getActivity());
listAdapter.setUseMapCenter(dialogFragment.isUseMapCenter());
setListAdapter(listAdapter);
ListView listView = getListView();
listView.setBackgroundColor(getResources().getColor(R.color.ctx_menu_info_view_bg_light));
listView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
touching = true;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:
touching = false;
break;
}
return false;
}
});
}
@Override
public QuickSearchListAdapter getListAdapter() {
return listAdapter;
}
public ArrayAdapter<?> getAdapter() {
return listAdapter;
}
public QuickSearchDialogFragment getDialogFragment() {
return dialogFragment;
}
@Override
public void onResume() {
super.onResume();
int screenOrientation = SampleUtils.getScreenOrientation(getActivity());
listAdapter.setScreenOrientation(screenOrientation);
dialogFragment.onSearchListFragmentResume(this);
}
private void showOnMap(SearchResult searchResult) {
if (searchResult.location != null) {
SampleApplication app = getMyApplication();
String lang = searchResult.requiredSearchPhrase.getSettings().getLang();
boolean transliterate = searchResult.requiredSearchPhrase.getSettings().isTransliterate();
PointDescription pointDescription = null;
Object object = searchResult.object;
switch (searchResult.objectType) {
case POI:
Amenity a = (Amenity) object;
String poiSimpleFormat = SampleFormatter.getPoiStringWithoutType(a, lang, transliterate);
pointDescription = new PointDescription(PointDescription.POINT_TYPE_POI, poiSimpleFormat);
pointDescription.setIconName(QuickSearchListItem.getAmenityIconName(a));
break;
case HOUSE:
String typeNameHouse = null;
String name = searchResult.localeName;
if (searchResult.relatedObject instanceof City) {
name = ((City) searchResult.relatedObject).getName(searchResult.requiredSearchPhrase.getSettings().getLang(), true) + " " + name;
} else if (searchResult.relatedObject instanceof Street) {
String s = ((Street) searchResult.relatedObject).getName(searchResult.requiredSearchPhrase.getSettings().getLang(), true);
typeNameHouse = ((Street) searchResult.relatedObject).getCity().getName(searchResult.requiredSearchPhrase.getSettings().getLang(), true);
name = s + " " + name;
} else if (searchResult.localeRelatedObjectName != null) {
name = searchResult.localeRelatedObjectName + " " + name;
}
pointDescription = new PointDescription(PointDescription.POINT_TYPE_ADDRESS, typeNameHouse, name);
pointDescription.setIconName("ic_action_building");
break;
case LOCATION:
LatLon latLon = (LatLon) object;
pointDescription = new PointDescription(latLon.getLatitude(), latLon.getLongitude());
pointDescription.setIconName("ic_action_world_globe");
break;
case STREET_INTERSECTION:
String typeNameIntersection = QuickSearchListItem.getTypeName(app, searchResult);
if (Algorithms.isEmpty(typeNameIntersection)) {
typeNameIntersection = null;
}
pointDescription = new PointDescription(PointDescription.POINT_TYPE_ADDRESS,
typeNameIntersection, QuickSearchListItem.getName(app, searchResult));
pointDescription.setIconName("ic_action_intersection");
break;
}
dialogFragment.hideToolbar();
dialogFragment.hide();
getMainActivity().showOnMap(searchResult.location, searchResult.preferredZoom);
/* todo
getMyApplication().getSettings().setMapLocationToShow(
searchResult.location.getLatitude(), searchResult.location.getLongitude(),
searchResult.preferredZoom, pointDescription, true, object);
MapActivity.launchMapActivityMoveToTop(getActivity());
*/
}
}
public MainActivity getMainActivity() {
return (MainActivity) getActivity();
}
public void updateLocation(LatLon latLon, Float heading) {
if (listAdapter != null && !touching && !scrolling) {
listAdapter.setLocation(latLon);
listAdapter.setHeading(heading);
listAdapter.notifyDataSetChanged();
}
}
public void updateListAdapter(List<QuickSearchListItem> listItems, boolean append) {
if (listAdapter != null) {
listAdapter.setListItems(listItems);
if (!append) {
getListView().setSelection(0);
}
}
}
public void addListItem(QuickSearchListItem listItem) {
if (listItem != null) {
listAdapter.addListItem(listItem);
}
}
}

View file

@ -0,0 +1,291 @@
package net.osmand.core.samples.android.sample1.search;
import android.graphics.drawable.Drawable;
import net.osmand.binary.BinaryMapIndexReader;
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.SampleFormatter;
import net.osmand.core.samples.android.sample1.data.PointDescription;
import net.osmand.data.Amenity;
import net.osmand.data.City;
import net.osmand.data.City.CityType;
import net.osmand.data.LatLon;
import net.osmand.data.Street;
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiFilter;
import net.osmand.osm.PoiType;
import net.osmand.search.core.CustomSearchPoiFilter;
import net.osmand.search.core.SearchResult;
import net.osmand.util.Algorithms;
public class QuickSearchListItem {
protected SampleApplication app;
private SearchResult searchResult;
public QuickSearchListItem(SampleApplication app, SearchResult searchResult) {
this.app = app;
this.searchResult = searchResult;
}
public SearchResult getSearchResult() {
return searchResult;
}
public static String getCityTypeStr(SampleApplication ctx, CityType type) {
switch (type) {
case CITY:
return ctx.getString("city_type_city");
case TOWN:
return ctx.getString("city_type_town");
case VILLAGE:
return ctx.getString("city_type_village");
case HAMLET:
return ctx.getString("city_type_hamlet");
case SUBURB:
return ctx.getString("city_type_suburb");
case DISTRICT:
return ctx.getString("city_type_district");
case NEIGHBOURHOOD:
return ctx.getString("city_type_neighbourhood");
default:
return ctx.getString("city_type_city");
}
}
public String getName() {
return getName(app, searchResult);
}
public static String getName(SampleApplication app, SearchResult searchResult) {
switch (searchResult.objectType) {
case STREET:
if (searchResult.localeName.endsWith(")")) {
int i = searchResult.localeName.indexOf('(');
if (i > 0) {
return searchResult.localeName.substring(0, i).trim();
}
}
break;
case STREET_INTERSECTION:
if (!Algorithms.isEmpty(searchResult.localeRelatedObjectName)) {
return searchResult.localeName + " - " + searchResult.localeRelatedObjectName;
}
break;
case LOCATION:
LatLon latLon = (LatLon) searchResult.object;
return PointDescription.getLocationNamePlain(app, latLon.getLatitude(), latLon.getLongitude());
}
return searchResult.localeName;
}
public String getTypeName() {
return getTypeName(app, searchResult);
}
public static String getTypeName(SampleApplication app, SearchResult searchResult) {
switch (searchResult.objectType) {
case CITY:
City city = (City) searchResult.object;
return getCityTypeStr(app, city.getType());
case POSTCODE:
return app.getString("postcode");
case VILLAGE:
city = (City) searchResult.object;
if (!Algorithms.isEmpty(searchResult.localeRelatedObjectName)) {
if (searchResult.distRelatedObjectName > 0) {
return getCityTypeStr(app, city.getType())
+ ""
+ SampleFormatter.getFormattedDistance((float) searchResult.distRelatedObjectName, app)
+ " " + app.getString("shared_string_from") + " "
+ searchResult.localeRelatedObjectName;
} else {
return getCityTypeStr(app, city.getType())
+ ", "
+ searchResult.localeRelatedObjectName;
}
} else {
return getCityTypeStr(app, city.getType());
}
case STREET:
StringBuilder streetBuilder = new StringBuilder();
if (searchResult.localeName.endsWith(")")) {
int i = searchResult.localeName.indexOf('(');
if (i > 0) {
streetBuilder.append(searchResult.localeName.substring(i + 1, searchResult.localeName.length() - 1));
}
}
if (!Algorithms.isEmpty(searchResult.localeRelatedObjectName)) {
if (streetBuilder.length() > 0) {
streetBuilder.append(", ");
}
streetBuilder.append(searchResult.localeRelatedObjectName);
}
return streetBuilder.toString();
case HOUSE:
if (searchResult.relatedObject != null) {
Street relatedStreet = (Street) searchResult.relatedObject;
if (relatedStreet.getCity() != null) {
return searchResult.localeRelatedObjectName + ", "
+ relatedStreet.getCity().getName(searchResult.requiredSearchPhrase.getSettings().getLang(), true);
} else {
return searchResult.localeRelatedObjectName;
}
}
return "";
case STREET_INTERSECTION:
Street street = (Street) searchResult.object;
if (street.getCity() != null) {
return street.getCity().getName(searchResult.requiredSearchPhrase.getSettings().getLang(), true);
}
return "";
case POI_TYPE:
String res = "";
if (searchResult.object instanceof AbstractPoiType) {
AbstractPoiType abstractPoiType = (AbstractPoiType) searchResult.object;
if (abstractPoiType instanceof PoiCategory) {
res = "";
} else if (abstractPoiType instanceof PoiFilter) {
PoiFilter poiFilter = (PoiFilter) abstractPoiType;
res = poiFilter.getPoiCategory() != null ? poiFilter.getPoiCategory().getTranslation() : "";
} else if (abstractPoiType instanceof PoiType) {
PoiType poiType = (PoiType) abstractPoiType;
res = poiType.getParentType() != null ? poiType.getParentType().getTranslation() : null;
if (res == null) {
res = poiType.getCategory() != null ? poiType.getCategory().getTranslation() : null;
}
if (res == null) {
res = "";
}
} else {
res = "";
}
} else if (searchResult.object instanceof CustomSearchPoiFilter) {
res = ((CustomSearchPoiFilter) searchResult.object).getName();
}
return res;
case POI:
Amenity amenity = (Amenity) searchResult.object;
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;
case LOCATION:
LatLon latLon = (LatLon) searchResult.object;
if (searchResult.localeRelatedObjectName == null) {
// todo
//String locationCountry = app.getRegions().getCountryName(latLon);
//searchResult.localeRelatedObjectName = locationCountry == null ? "" : locationCountry;
}
return searchResult.localeRelatedObjectName;
case REGION:
BinaryMapIndexReader binaryMapIndexReader = (BinaryMapIndexReader) searchResult.object;
System.out.println(binaryMapIndexReader.getFile().getAbsolutePath() + " " + binaryMapIndexReader.getCountryName());
break;
case UNKNOWN_NAME_FILTER:
break;
}
return searchResult.objectType.name();
}
public Drawable getIcon() {
return getIcon(app, searchResult);
}
public static int getPoiTypeIconId(SampleApplication app, AbstractPoiType abstractPoiType) {
int res = OsmandResources.getDrawableId("mx_" + abstractPoiType.getIconKeyName());
if (res != 0) {
return res;
} else if (abstractPoiType instanceof PoiType) {
res = OsmandResources.getDrawableId("mx_" + ((PoiType) abstractPoiType).getOsmTag()
+ "_" + ((PoiType) abstractPoiType).getOsmValue());
if (res != 0) {
return res;
}
}
if (abstractPoiType instanceof PoiType && ((PoiType) abstractPoiType).getParentType() != null) {
return getPoiTypeIconId(app, ((PoiType) abstractPoiType).getParentType());
}
return 0;
}
public static int getAmenityIconId(Amenity amenity) {
int res = 0;
PoiType st = amenity.getType().getPoiTypeByKeyName(amenity.getSubType());
if (st != null) {
res = OsmandResources.getDrawableId("mx_" + st.getIconKeyName());
if (res == 0) {
res = OsmandResources.getDrawableId("mx_" + st.getOsmTag() + "_" + st.getOsmValue());
}
}
return res;
}
public static String getAmenityIconName(Amenity amenity) {
PoiType st = amenity.getType().getPoiTypeByKeyName(amenity.getSubType());
if (st != null) {
String id = st.getIconKeyName();
if (OsmandResources.getDrawableId("mx_" + id) == 0) {
id = st.getOsmTag() + "_" + st.getOsmValue();
if (OsmandResources.getDrawableId("mx_" + id) != 0) {
return id;
}
} else {
return id;
}
}
return null;
}
public static Drawable getIcon(SampleApplication app, SearchResult searchResult) {
if (searchResult == null || searchResult.objectType == null) {
return null;
}
int iconId;
switch (searchResult.objectType) {
case CITY:
return app.getIconsCache().getIcon("ic_action_building_number", R.color.osmand_orange);
case VILLAGE:
return app.getIconsCache().getIcon("ic_action_home_dark", R.color.osmand_orange);
case POSTCODE:
case STREET:
return app.getIconsCache().getIcon("ic_action_street_name", R.color.osmand_orange);
case HOUSE:
return app.getIconsCache().getIcon("ic_action_building", R.color.osmand_orange);
case STREET_INTERSECTION:
return app.getIconsCache().getIcon("ic_action_intersection", R.color.osmand_orange);
case POI_TYPE:
iconId = getPoiTypeIconId(app, (AbstractPoiType) searchResult.object);
if (iconId != 0) {
return app.getIconsCache().getOsmandIcon(iconId, R.color.osmand_orange);
} else {
return null;
}
case POI:
Amenity amenity = (Amenity) searchResult.object;
iconId = getAmenityIconId(amenity);
if (iconId != 0) {
return app.getIconsCache().getOsmandIcon(iconId, R.color.osmand_orange);
} else {
return null;
}
case LOCATION:
return app.getIconsCache().getIcon("ic_action_world_globe", R.color.osmand_orange);
case REGION:
return app.getIconsCache().getIcon("ic_world_globe_dark", R.color.osmand_orange);
case UNKNOWN_NAME_FILTER:
break;
}
return null;
}
}

View file

@ -0,0 +1,26 @@
package net.osmand.core.samples.android.sample1.search;
import android.view.View.OnClickListener;
import net.osmand.core.samples.android.sample1.SampleApplication;
public class QuickSearchMoreListItem extends QuickSearchListItem {
private String name;
private OnClickListener onClickListener;
public QuickSearchMoreListItem(SampleApplication app, String name, OnClickListener onClickListener) {
super(app, null);
this.name = name;
this.onClickListener = onClickListener;
}
@Override
public String getName() {
return name;
}
public OnClickListener getOnClickListener() {
return onClickListener;
}
}

View file

@ -0,0 +1,166 @@
package net.osmand.core.samples.android.sample1.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import net.osmand.core.samples.android.sample1.IconsCache;
import net.osmand.core.samples.android.sample1.R;
import net.osmand.core.samples.android.sample1.SampleApplication;
public class DirectionDrawable extends Drawable {
Paint paintRouteDirection;
float width;
float height;
Context ctx;
private float angle;
int resourceId = -1;
Drawable arrowImage ;
public DirectionDrawable(Context ctx, float width, float height, int resourceId, int clrId) {
this(ctx, width, height);
IconsCache iconsCache = ((SampleApplication) ctx.getApplicationContext()).getIconsCache();
arrowImage = iconsCache.getIcon(resourceId, clrId);
this.resourceId = resourceId;
}
public DirectionDrawable(Context ctx, float width, float height) {
this.ctx = ctx;
this.width = width;
this.height = height;
paintRouteDirection = new Paint();
paintRouteDirection.setStyle(Paint.Style.FILL_AND_STROKE);
paintRouteDirection.setColor(ctx.getResources().getColor(R.color.color_unknown));
paintRouteDirection.setAntiAlias(true);
}
public void setImage(int resourceId, int clrId) {
IconsCache iconsCache = ((SampleApplication) ctx.getApplicationContext()).getIconsCache();
arrowImage = iconsCache.getIcon(resourceId, clrId);
this.resourceId = resourceId;
onBoundsChange(getBounds());
}
public void setImage(int resourceId) {
IconsCache iconsCache = ((SampleApplication) ctx.getApplicationContext()).getIconsCache();
arrowImage = iconsCache.getIcon(resourceId, 0);
this.resourceId = resourceId;
onBoundsChange(getBounds());
}
public void setColorId(int clrId) {
// R.color.color_ok, R.color.color_unknown, R.color.color_warning
if(arrowImage != null) {
IconsCache iconsCache = ((SampleApplication) ctx.getApplicationContext()).getIconsCache();
arrowImage = iconsCache.getIcon(resourceId, clrId);
} else {
paintRouteDirection.setColor(ctx.getResources().getColor(clrId));
}
}
public void setAngle(float angle) {
this.angle = angle;
}
@Override
public int getIntrinsicWidth() {
if (arrowImage != null) {
return arrowImage.getIntrinsicWidth();
}
return super.getIntrinsicWidth();
}
@Override
public int getIntrinsicHeight() {
if (arrowImage != null) {
return arrowImage.getIntrinsicHeight();
}
return super.getIntrinsicHeight();
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
if (arrowImage != null) {
Rect r = bounds;
int w = arrowImage.getIntrinsicWidth();
int h = arrowImage.getIntrinsicHeight();
int dx = Math.max(0, r.width() - w);
int dy = Math.max(0, r.height() - h);
if(r.width() == 0 && r.height() == 0) {
arrowImage.setBounds(0, 0, w, h);
} else {
arrowImage.setBounds(r.left + dx / 2, r.top + dy / 2, r.right - dx / 2, r.bottom - dy / 2);
}
}
}
@Override
public void draw(Canvas canvas) {
canvas.save();
if (arrowImage != null) {
Rect r = getBounds();
canvas.rotate(angle, r.centerX(), r.centerY());
arrowImage.draw(canvas);
} else {
canvas.rotate(angle, canvas.getWidth() / 2, canvas.getHeight() / 2);
Path directionPath = createDirectionPath();
canvas.drawPath(directionPath, paintRouteDirection);
}
canvas.restore();
}
@Override
public int getOpacity() {
return 0;
}
@Override
public void setAlpha(int alpha) {
paintRouteDirection.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
paintRouteDirection.setColorFilter(cf);
}
private Path createDirectionPath() {
int h = 15;
int w = 4;
float sarrowL = 8; // side of arrow
float harrowL = (float) Math.sqrt(2) * sarrowL; // hypotenuse of arrow
float hpartArrowL = (harrowL - w) / 2;
Path path = new Path();
path.moveTo(width / 2, height - (height - h) / 3);
path.rMoveTo(w / 2, 0);
path.rLineTo(0, -h);
path.rLineTo(hpartArrowL, 0);
path.rLineTo(-harrowL / 2, -harrowL / 2); // center
path.rLineTo(-harrowL / 2, harrowL / 2);
path.rLineTo(hpartArrowL, 0);
path.rLineTo(0, h);
DisplayMetrics dm = new DisplayMetrics();
Matrix pathTransform = new Matrix();
WindowManager mgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
mgr.getDefaultDisplay().getMetrics(dm);
pathTransform.postScale(dm.density, dm.density);
path.transform(pathTransform);
width *= dm.density;
height *= dm.density;
return path;
}
}