Merge branch 'feature/v1.0.0' of gitlab.zhidaoauto.com:ecos/yycp-service/Launcher into feature/v1.0.0

This commit is contained in:
wangcongtao
2020-01-02 18:41:52 +08:00
49 changed files with 4684 additions and 111 deletions

View File

@@ -0,0 +1,28 @@
package com.mogo.module.common;
import android.text.Editable;
import android.text.TextWatcher;
/**
* @author congtaowang
* @since 2019-10-02
* <p>
* 描述
*/
public class TextWatcherAdapter implements 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 ) {
}
}

View File

@@ -36,16 +36,16 @@ dependencies {
implementation rootProject.ext.dependencies.arouter
annotationProcessor rootProject.ext.dependencies.aroutercompiler
if (Boolean.valueOf(RELEASE)) {
implementation rootProject.ext.dependencies.mogomap
implementation rootProject.ext.dependencies.mogomapapi
implementation rootProject.ext.dependencies.mogoutils
api rootProject.ext.dependencies.mogomap
api rootProject.ext.dependencies.mogomapapi
api rootProject.ext.dependencies.mogoutils
api rootProject.ext.dependencies.mogocommons
api rootProject.ext.dependencies.mogoserviceapi
implementation rootProject.ext.dependencies.modulecommon
} else {
implementation project(":libraries:mogo-map")
implementation project(":libraries:mogo-map-api")
implementation project(":foudations:mogo-utils")
api project(":libraries:mogo-map")
api project(":libraries:mogo-map-api")
api project(":foudations:mogo-utils")
api project(":foudations:mogo-commons")
api project(':services:mogo-service-api')
implementation project(':modules:mogo-module-common')

View File

@@ -0,0 +1,131 @@
package com.mogo.module.map.location;
import android.content.Context;
import android.util.Log;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.model.LatLng;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class AMapLocationManager {
private static final String TAG = "AMapLocationManager";
private static final Set< AMapLocationListener > mLocationChangeListeners = new HashSet<>();
private static final InternalLocationListener mInternalLocationListener = new InternalLocationListener();
private AMapLocationClient mLocationClient;
private static AMapLocation sLastKnowLocation = null;
private static volatile AMapLocationManager sInstance;
public static AMapLocationManager getInstance( Context context ) {
if ( sInstance == null ) {
synchronized ( AMapLocationManager.class ) {
if ( sInstance == null ) {
sInstance = new AMapLocationManager( context );
}
}
}
return sInstance;
}
public synchronized void release() {
stop();
mLocationChangeListeners.clear();
mLocationClient = null;
sLastKnowLocation = null;
sInstance = null;
}
private AMapLocationManager( Context context ) {
if ( context == null ) {
throw new NullPointerException( "context can't be null." );
}
mLocationClient = new AMapLocationClient( context.getApplicationContext() );
mLocationClient.setLocationListener( mInternalLocationListener );
}
private void setLocationOptions( long locateInterval ) {
AMapLocationClientOption option = new AMapLocationClientOption();
option.setLocationMode( AMapLocationClientOption.AMapLocationMode.Hight_Accuracy );
option.setNeedAddress( true );
option.setInterval( locateInterval );
if ( mLocationClient != null ) {
mLocationClient.setLocationOption( option );
}
}
public synchronized void start() {
start( 2000L );
}
public synchronized void start( long locateInterval ) {
if ( mLocationClient != null && mLocationClient.isStarted() ) {
stop();
}
setLocationOptions( locateInterval );
mLocationClient.startLocation();
Log.d( TAG, "start location, location interval is " + locateInterval );
}
public synchronized void stop() {
if ( mLocationClient != null ) {
mLocationClient.stopLocation();
}
Log.d( TAG, "stop location" );
}
public static AMapLocation getAMapLastKnowLocation() {
return sLastKnowLocation;
}
public static LatLng getLastKnowPoint() {
final AMapLocation location = getAMapLastKnowLocation();
if ( location != null ) {
return new LatLng( location.getLatitude(), location.getLongitude() );
}
return null;
}
public void addLocationListener( AMapLocationListener listener ) {
if ( listener != null ) {
synchronized ( mLocationChangeListeners ) {
mLocationChangeListeners.add( listener );
}
}
}
public void removeLocationListener( AMapLocationListener listener ) {
synchronized ( mLocationChangeListeners ) {
mLocationChangeListeners.remove( listener );
}
}
/**
* 定位SDK监听函数
*/
private static class InternalLocationListener implements AMapLocationListener {
@Override
public void onLocationChanged( AMapLocation aMapLocation ) {
if ( aMapLocation == null ||
aMapLocation.getLatitude() == 0.0D ||
aMapLocation.getLongitude() == 0.0D ) {
return;
}
sLastKnowLocation = aMapLocation.clone();
synchronized ( mLocationChangeListeners ) {
Iterator iterator = mLocationChangeListeners.iterator();
while ( iterator.hasNext() ) {
AMapLocationListener listener = ( AMapLocationListener ) iterator.next();
listener.onLocationChanged( sLastKnowLocation );
}
}
}
}
}

View File

@@ -0,0 +1,29 @@
package com.mogo.module.map.location;
/**
* @author congtaowang
* @since 2019-09-27
* <p>
* 描述
*/
public class LocationUtils {
public static float bearing( double lat1, double lon1, double lat2, double lon2 ) {
double longitude1 = lon1;
double longitude2 = lon2;
double latitude1 = Math.toRadians( lat1 );
double latitude2 = Math.toRadians( lat2 );
double longDiff = Math.toRadians( longitude2 - longitude1 );
double y = Math.sin( longDiff ) * Math.cos( latitude2 );
double x = Math.cos( latitude1 ) * Math.sin( latitude2 ) - Math.sin( latitude1 ) * Math.cos( latitude2 ) * Math
.cos( longDiff );
double result = ( Math.toDegrees( Math.atan2( y, x ) ) + 360 ) % 360;
if ( ( ( int ) result ) == ( ( int ) ( result + 0.5 ) ) ) {
return ( ( int ) result );
} else {
return ( ( int ) result ) + 0.5f;
}
}
}

View File

@@ -0,0 +1,53 @@
package com.mogo.module.map.location;
import com.amap.api.maps.model.MyLocationStyle;
/**
* @author congtaowang
* @since 2019-10-17
* <p>
* 描述
*/
public class MyLocationUtils {
public static final long INTERVAL_FAST_SPEED = 2_000L;
public static final long INTERVAL_MIDDLE_SPEED = 2_000L;
public static final long INTERVAL_SLOW_SPEED = 10_000L;
/**
* 前台快速定位
*
* @return
*/
public static MyLocationStyle wrapperAsFast( MyLocationStyle style ) {
if ( style != null ) {
style.interval( INTERVAL_FAST_SPEED );
}
return style;
}
/**
* 后台慢速定位
*
* @return
*/
public static MyLocationStyle wrapperAsMiddleSpeed( MyLocationStyle style ) {
if ( style != null ) {
style.interval( INTERVAL_MIDDLE_SPEED );
}
return style;
}
/**
* 后台慢速定位
*
* @return
*/
public static MyLocationStyle wrapperAsSlow( MyLocationStyle style ) {
if ( style != null ) {
style.interval( INTERVAL_SLOW_SPEED );
}
return style;
}
}

View File

@@ -27,6 +27,11 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
@@ -38,8 +43,13 @@ dependencies {
implementation rootProject.ext.dependencies.room
annotationProcessor rootProject.ext.dependencies.roomAnnotationProcessor
implementation rootProject.ext.dependencies.roomRxjava
implementation rootProject.ext.dependencies.androidxrecyclerview
annotationProcessor rootProject.ext.dependencies.aroutercompiler
implementation rootProject.ext.dependencies.jetbrainsannotationsjava5
implementation rootProject.ext.dependencies.rxandroid
// api project(path: ':modules:mogo-module-common')
// api project(path: ':foudations:mogo-utils')
// api project(path: ':modules:mogo-module-map')
if( Boolean.valueOf(RELEASE) ){
implementation rootProject.ext.dependencies.mogomap
@@ -55,7 +65,7 @@ dependencies {
implementation project(":foudations:mogo-utils")
api project(":foudations:mogo-commons")
api project(':services:mogo-service-api')
implementation project(':modules:mogo-module-common')
api project(':modules:mogo-module-common')
implementation project(':modules:mogo-module-map')
}
}

View File

@@ -0,0 +1,95 @@
package com.mogo.module.navi.bean;
import com.amap.api.location.AMapLocation;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.geocoder.RegeocodeAddress;
import com.amap.api.services.help.Tip;
import java.util.ArrayList;
import java.util.List;
/**
* @author congtaowang
* @since 2019-10-02
* <p>
* 实体类操作工具
*/
public class EntityConvertUtils {
public static List< Tip > pois2Tips( List< SearchPoi > datums ) {
final List< Tip > output = new ArrayList<>();
if ( datums == null || datums.isEmpty() ) {
return output;
}
for ( SearchPoi poi : datums ) {
Tip tip = poi2Tip( poi );
if ( tip != null ) {
output.add( tip );
}
}
return output;
}
public static Tip poi2Tip( SearchPoi poi ) {
if ( poi == null ) {
return null;
}
Tip tip = new Tip();
tip.setID( poi.pId );
tip.setAdcode( poi.getAdCode() );
tip.setAddress( poi.getAddress() );
tip.setDistrict( poi.getDistrict() );
tip.setName( poi.getName() );
tip.setTypeCode( poi.getTypeCode() );
tip.setPostion( new LatLonPoint( poi.getLat(), poi.getLng() ) );
return tip;
}
public static SearchPoi tipToPoi( Tip tip ) {
if ( tip == null ) {
return null;
}
double lat = 0.0;
double lng = 0.0;
if ( tip.getPoint() != null ) {
lat = tip.getPoint().getLatitude();
lng = tip.getPoint().getLongitude();
}
return new SearchPoi( tip.getPoiID(),
tip.getName(),
tip.getAddress(),
lat,
lng,
tip.getDistrict(),
tip.getAdcode(),
tip.getTypeCode() );
}
public static SearchPoi aMapLocation2Poi( AMapLocation location ) {
if ( location == null || location.getErrorCode() != AMapLocation.LOCATION_SUCCESS ) {
return null;
}
return new SearchPoi( System.currentTimeMillis() + "",
location.getPoiName(),
location.getAddress(),
location.getLatitude(),
location.getLongitude(),
location.getDistrict(),
location.getAdCode(),
location.getCoordType() );
}
public static SearchPoi geocodeAddress2Poi( RegeocodeAddress address, CameraPosition position ) {
if ( address == null || position == null ) {
return null;
}
return new SearchPoi( System.currentTimeMillis() + "",
address.getFormatAddress(),
address.getFormatAddress(),
position.target.latitude,
position.target.longitude,
address.getDistrict(),
address.getAdCode(),
"" );
}
}

View File

@@ -0,0 +1,236 @@
package com.mogo.module.navi.bean;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import com.mogo.module.navi.constants.DataConstants;
/**
* @author congtaowang
* @since 2019-10-02
* <p>
* 搜索地址表数据结构
*/
@Entity( tableName = DataConstants.T_SEARCH_POI )
public class SearchPoi implements Parcelable {
public static final SearchPoi NULL = new SearchPoi( null,
null,
null,
0.0,
0.0,
null,
null,
null );
@PrimaryKey
@NonNull
public String pId;
private String name;
private String address;
private double lat;
private double lng;
private String district;
private String adCode;
private String typeCode;
private String province;
private String city;
/**
* 插入poi数据类型
* <p>
* {@link DataConstants#TYPE_COMPANY_ADDRESS}
* {@link DataConstants#TYPE_HOME_ADDRESS}
* {@link DataConstants#TYPE_POI}
*/
private int type;
/**
* 数据记录时间,自动赋值
*/
private long time;
public SearchPoi( String pId,
String name,
String address,
double lat,
double lng,
String district,
String adCode,
String typeCode ) {
this( pId, name, address, lat, lng, district, adCode, typeCode, "", "", DataConstants.TYPE_POI );
}
private SearchPoi( String pId,
String name,
String address,
double lat,
double lng,
String district,
String adCode,
String typeCode,
String province,
String city,
int type ) {
this.pId = pId;
this.name = name;
this.address = address;
this.lat = lat;
this.lng = lng;
this.district = district;
this.adCode = adCode;
this.typeCode = typeCode;
this.province = province;
this.city = city;
this.type = type;
this.time = System.currentTimeMillis();
}
@NonNull
public String getpId() {
return pId;
}
public void setpId( @NonNull String pId ) {
this.pId = pId;
}
public String getName() {
return name;
}
public void setName( String name ) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress( String address ) {
this.address = address;
}
public double getLat() {
return lat;
}
public void setLat( double lat ) {
this.lat = lat;
}
public double getLng() {
return lng;
}
public void setLng( double lng ) {
this.lng = lng;
}
public String getDistrict() {
return district;
}
public void setDistrict( String district ) {
this.district = district;
}
public String getAdCode() {
return adCode;
}
public void setAdCode( String adCode ) {
this.adCode = adCode;
}
public String getTypeCode() {
return typeCode;
}
public void setTypeCode( String typeCode ) {
this.typeCode = typeCode;
}
public String getProvince() {
return province;
}
public void setProvince( String province ) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity( String city ) {
this.city = city;
}
public int getType() {
return type;
}
public void setType( int type ) {
this.type = type;
}
public long getTime() {
return time;
}
public void setTime( long time ) {
this.time = time;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel( Parcel dest, int flags ) {
dest.writeString( this.pId );
dest.writeString( this.name );
dest.writeString( this.address );
dest.writeDouble( this.lat );
dest.writeDouble( this.lng );
dest.writeString( this.district );
dest.writeString( this.adCode );
dest.writeString( this.typeCode );
dest.writeString( this.province );
dest.writeString( this.city );
dest.writeInt( this.type );
dest.writeLong( this.time );
}
protected SearchPoi( Parcel in ) {
this.pId = in.readString();
this.name = in.readString();
this.address = in.readString();
this.lat = in.readDouble();
this.lng = in.readDouble();
this.district = in.readString();
this.adCode = in.readString();
this.typeCode = in.readString();
this.province = in.readString();
this.city = in.readString();
this.type = in.readInt();
this.time = in.readLong();
}
public static final Creator< SearchPoi > CREATOR = new Creator< SearchPoi >() {
@Override
public SearchPoi createFromParcel( Parcel source ) {
return new SearchPoi( source );
}
@Override
public SearchPoi[] newArray( int size ) {
return new SearchPoi[size];
}
};
}

View File

@@ -0,0 +1,29 @@
package com.mogo.module.navi.constants;
import com.amap.api.navi.enums.PathPlanningStrategy;
/**
* @author congtaowang
* @since 2019-10-04
* <p>
* 地图基本参数配置
*/
public class AMapConstants {
/**
* 初始化地图缩放级别
*/
public static final float AMAP_ZOOM_COMMON_LEVEL = 15.0f;
/**
* 点击当前位置按钮的地图缩放级别
*/
public static final float AMAP_ZOOM_CURRENT_LOCATION_LEVEL = AMAP_ZOOM_COMMON_LEVEL;
public static final float AMPA_BEARING = 0.0f;
public static final int DEFAULT_ROUTE_STRATEGY = PathPlanningStrategy.DRIVING_MULTIPLE_ROUTES_DEFAULT;
public static final float AMAP_ROUTE_OVERLAY_TRANSPARENCY_SELECTED = 1f;
public static final float AMAP_ROUTE_OVERLAY_TRANSPARENCY_UNSELECTED = 0.3f;
}

View File

@@ -0,0 +1,16 @@
package com.mogo.module.navi.constants;
/**
* @author congtaowang
* @since 2019-12-12
* <p>
* 自定义地图样式
*/
public class CustomMapStyle {
public static final String STYLE_ID = "e3e33a3423230b219494b40c4d71d93a";
public static final String ASSET_STYLE_DATA = "style.data";
public static final String ASSET_STYLE_EXTRA_DATA = "style_extra.data";
}

View File

@@ -0,0 +1,45 @@
package com.mogo.module.navi.constants;
import android.net.Uri;
/**
* @author zyz
* @since 2019-10-02
* <p>
* 描述
*/
public class DataConstants {
public static final int DB_VERSION = 1;
public static final String DB_NAME = "zhidao.amap.db";
public static final String T_SEARCH_POI = "t_search_poi";
public static final int TYPE_POI = 0; // 普通搜索的类型
public static final int TYPE_HOME_ADDRESS = 1; // 家地址
public static final int TYPE_COMPANY_ADDRESS = 2; // 公司地址
public static final String POI_ID_HOME = "common_address_home";
public static final String POI_ID_COMPANY = "common_address_company";
public static final String CP_AUTHORITY = "com.zhidao.amap";
// 家的地址
public static final Uri CONTENT_HOME_ADDRESS_URI = Uri.parse( "content://com.zhidao.amap/homeAddress" );
public static final int HOME_ADDRESS_CODE = TYPE_HOME_ADDRESS;
public static final String HOME_ADDRESS_PATH = "homeAddress";
public static final String HOME_ADDRESS = "homeAddress";
public static final String HOME_ADDRESS_NAME = "homeAddressName";
public static final String HOME_ADDRESS_LATITUDE = "homeAddressLatitude";
public static final String HOME_ADDRESS_LONGITUDE = "homeAddressLongitude";
// 公司地址
public static final Uri CONTENT_COMPANY_ADDRESS_URI = Uri.parse( "content://com.zhidao.amap/companyAddress" );
public static final int COMPANY_ADDRESS_CODE = TYPE_COMPANY_ADDRESS;
public static final String COMPANY_ADDRESS_PATH = "companyAddress";
public static final String COMPANY_ADDRESS = "companyAddress";
public static final String COMPANY_ADDRESS_NAME = "companyAddressName";
public static final String COMPANY_ADDRESS_LATITUDE = "companyAddressLatitude";
public static final String COMPANY_ADDRESS_LONGITUDE = "companyAddressLongitude";
}

View File

@@ -0,0 +1,42 @@
package com.mogo.module.navi.dao;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import com.mogo.module.navi.bean.SearchPoi;
import com.mogo.module.navi.constants.DataConstants;
import io.reactivex.Single;
import java.util.List;
/**
* @author congtaowang
* @since 2019-10-02
* <p>
* 搜索页面数据操作
*/
@Dao
public interface SearchPoiDao {
@Insert( onConflict = OnConflictStrategy.REPLACE )
List<Long> insert(SearchPoi... datums);
@Query( "SELECT * FROM " + DataConstants.T_SEARCH_POI + " WHERE type=" + DataConstants.TYPE_POI + " ORDER BY time DESC LIMIT :limit" )
Single<List< SearchPoi >> getLastN(int limit);
@Query( "SELECT * FROM " + DataConstants.T_SEARCH_POI + " WHERE type=" + DataConstants.TYPE_POI )
Single<List< SearchPoi >> getAll();
@Query( "SELECT * FROM " + DataConstants.T_SEARCH_POI + " WHERE type=" + DataConstants.TYPE_HOME_ADDRESS )
Single<List< SearchPoi >> getHomeAddress();
@Query( "SELECT * FROM " + DataConstants.T_SEARCH_POI + " WHERE type=" + DataConstants.TYPE_COMPANY_ADDRESS )
Single<List< SearchPoi >> getCompanyAddress();
@Delete
int delete(SearchPoi poi);
@Delete
int deleteAll(List<SearchPoi> list);
}

View File

@@ -4,17 +4,17 @@ import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import com.mogo.module.navi.database.bean.POIInfo;
import com.mogo.module.navi.database.dao.POIDao;
import com.mogo.module.navi.bean.SearchPoi;
import com.mogo.module.navi.dao.SearchPoiDao;
/**
* @author zyz
* 2019-08-15.
*/
@Database(entities = { POIInfo.class}, version = 1, exportSchema = false)
@Database(entities = { SearchPoi.class}, version = 1, exportSchema = false)
public abstract class AppDataBase extends RoomDatabase {
public abstract POIDao poiDao();
public abstract SearchPoiDao poiDao();
private static volatile AppDataBase INSTANCE;

View File

@@ -1,65 +0,0 @@
package com.mogo.module.navi.database.bean;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import org.jetbrains.annotations.NotNull;
/**
* @author zyz
* 2019-08-15.
*/
@Entity
public class POIInfo {
@PrimaryKey
@NotNull
public String pId;
private String name;
private String address;
private double lat;
private double lot;
public POIInfo(String pId, String name, String address, double lat, double lot) {
this.pId = pId;
this.name = name;
this.address = address;
this.lat = lat;
this.lot = lot;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLot() {
return lot;
}
public void setLot(double lot) {
this.lot = lot;
}
}

View File

@@ -1,32 +0,0 @@
package com.mogo.module.navi.database.dao;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import com.mogo.module.navi.database.bean.POIInfo;
import io.reactivex.Flowable;
import java.util.List;
/**
* @author zyz
* 2019-08-15.
*/
@Dao
public interface POIDao {
/**
* 插入地址信息
* @param poiInfos GEO信息
* @return
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
List<Long> insert(POIInfo... poiInfos);
/**
* 获取地址列表
* @return
*/
@Query("SELECT * from poiinfo")
Flowable<List<POIInfo>> load();
}

View File

@@ -0,0 +1,19 @@
package com.mogo.module.navi.lib;
import com.amap.api.maps.AMap;
import com.amap.api.navi.AMapNaviListener;
import com.amap.api.navi.AMapNaviViewListener;
import com.mogo.module.navi.database.wrapper.NaviInfoWrapper;
/**
* @author congtaowang
* @since 2019-09-27
* <p>
* 描述
*/
public interface AMapNaviStatusChangedListener extends AMapNaviListener,
AMapNaviViewListener,
AMap.OnCameraChangeListener {
void onNaviInfoUpdate(NaviInfoWrapper wrapper);
}

View File

@@ -0,0 +1,281 @@
package com.mogo.module.navi.lib;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.navi.model.AMapCalcRouteResult;
import com.amap.api.navi.model.AMapLaneInfo;
import com.amap.api.navi.model.AMapModelCross;
import com.amap.api.navi.model.AMapNaviCameraInfo;
import com.amap.api.navi.model.AMapNaviCross;
import com.amap.api.navi.model.AMapNaviInfo;
import com.amap.api.navi.model.AMapNaviLocation;
import com.amap.api.navi.model.AMapNaviRouteNotifyData;
import com.amap.api.navi.model.AMapNaviTrafficFacilityInfo;
import com.amap.api.navi.model.AMapServiceAreaInfo;
import com.amap.api.navi.model.AimLessModeCongestionInfo;
import com.amap.api.navi.model.AimLessModeStat;
import com.amap.api.navi.model.NaviInfo;
import com.autonavi.tbt.TrafficFacilityInfo;
import com.mogo.module.navi.database.wrapper.NaviInfoWrapper;
/**
* @author congtaowang
* @since 2019-10-01
* <p>
*/
public abstract class AMapNaviStatusChangedListenerDefault implements AMapNaviStatusChangedListener {
@Override
public void onNaviInfoUpdate( NaviInfoWrapper wrapper ) {
}
@Override
public void onCameraChange( CameraPosition cameraPosition ) {
}
@Override
public void onCameraChangeFinish( CameraPosition cameraPosition ) {
}
@Override
public void onInitNaviFailure() {
}
@Override
public void onInitNaviSuccess() {
}
@Override
public void onStartNavi( int i ) {
}
@Override
public void onTrafficStatusUpdate() {
}
@Override
public void onLocationChange( AMapNaviLocation aMapNaviLocation ) {
}
@Override
public void onGetNavigationText( int i, String s ) {
}
@Override
public void onGetNavigationText( String s ) {
}
@Override
public void onEndEmulatorNavi() {
}
@Override
public void onArriveDestination() {
}
@Override
public void onCalculateRouteFailure( int i ) {
}
@Override
public void onReCalculateRouteForYaw() {
}
@Override
public void onReCalculateRouteForTrafficJam() {
}
@Override
public void onArrivedWayPoint( int i ) {
}
@Override
public void onGpsOpenStatus( boolean b ) {
}
@Override
public void onNaviInfoUpdate( NaviInfo naviInfo ) {
}
@Override
public void onNaviInfoUpdated( AMapNaviInfo aMapNaviInfo ) {
}
@Override
public void updateCameraInfo( AMapNaviCameraInfo[] aMapNaviCameraInfos ) {
}
@Override
public void updateIntervalCameraInfo( AMapNaviCameraInfo aMapNaviCameraInfo, AMapNaviCameraInfo aMapNaviCameraInfo1, int i ) {
}
@Override
public void onServiceAreaUpdate( AMapServiceAreaInfo[] aMapServiceAreaInfos ) {
}
@Override
public void showCross( AMapNaviCross aMapNaviCross ) {
}
@Override
public void hideCross() {
}
@Override
public void showModeCross( AMapModelCross aMapModelCross ) {
}
@Override
public void hideModeCross() {
}
@Override
public void showLaneInfo( AMapLaneInfo[] aMapLaneInfos, byte[] bytes, byte[] bytes1 ) {
}
@Override
public void showLaneInfo( AMapLaneInfo aMapLaneInfo ) {
}
@Override
public void hideLaneInfo() {
}
@Override
public void onCalculateRouteSuccess( int[] ints ) {
}
@Override
public void notifyParallelRoad( int i ) {
}
@Override
public void OnUpdateTrafficFacility( AMapNaviTrafficFacilityInfo aMapNaviTrafficFacilityInfo ) {
}
@Override
public void OnUpdateTrafficFacility( AMapNaviTrafficFacilityInfo[] aMapNaviTrafficFacilityInfos ) {
}
@Override
public void OnUpdateTrafficFacility( TrafficFacilityInfo trafficFacilityInfo ) {
}
@Override
public void updateAimlessModeStatistics( AimLessModeStat aimLessModeStat ) {
}
@Override
public void updateAimlessModeCongestionInfo( AimLessModeCongestionInfo aimLessModeCongestionInfo ) {
}
@Override
public void onPlayRing( int i ) {
}
@Override
public void onCalculateRouteSuccess( AMapCalcRouteResult aMapCalcRouteResult ) {
}
@Override
public void onCalculateRouteFailure( AMapCalcRouteResult aMapCalcRouteResult ) {
}
@Override
public void onNaviRouteNotify( AMapNaviRouteNotifyData aMapNaviRouteNotifyData ) {
}
@Override
public void onNaviSetting() {
}
@Override
public void onNaviCancel() {
}
@Override
public boolean onNaviBackClick() {
return false;
}
@Override
public void onNaviMapMode( int i ) {
}
@Override
public void onNaviTurnClick() {
}
@Override
public void onNextRoadClick() {
}
@Override
public void onScanViewButtonClick() {
}
@Override
public void onLockMap( boolean b ) {
}
@Override
public void onNaviViewLoaded() {
}
@Override
public void onMapTypeChanged( int i ) {
}
@Override
public void onNaviViewShowMode( int i ) {
}
}

View File

@@ -0,0 +1,70 @@
package com.mogo.module.navi.ui.adapter;
import android.content.Context;
import android.view.View;
import com.amap.api.services.help.Tip;
import com.mogo.module.navi.R;
import com.mogo.module.navi.ui.adapter.base.RecycleBaseAdapter;
import com.mogo.module.navi.ui.adapter.base.RecycleViewHolder;
import com.mogo.utils.OnItemClickedListener;
import java.util.List;
/**
* @author zyz
* 2019-08-13.
*/
public class SearchPoiAdapter extends RecycleBaseAdapter<Tip> {
/**
* @param context
* @param list
*/
public SearchPoiAdapter(Context context, List<Tip> list) {
super(context, list, R.layout.item_search_poi);
}
private OnItemClickedListener< Tip > mOnItemClickedListener;
private OnItemClickedListener< Tip > mOnDeleteAllClickedListener;
private OnItemClickedListener< Tip > mOnActionButtonClickedListener;
private boolean mShowDelete = false;
private View.OnClickListener onClickListener;
@Override
public void onBindViewHolder(RecycleViewHolder holder, Tip tip) {
holder.setText(R.id.tv_position, tip.getName());
holder.setText(R.id.tv_position_des, tip.getAddress());
holder.itemView.setTag(R.id.tag_position, tip);
holder.itemView.setOnClickListener(onClickListener);
}
public void setOnClickListener(View.OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
public void setOnItemClickedListener( OnItemClickedListener< Tip > onItemClickedListener ) {
this.mOnItemClickedListener = onItemClickedListener;
}
public void setOnDeleteAllClickedListener( OnItemClickedListener< Tip > onDeleteAllClickedListener ) {
this.mOnDeleteAllClickedListener = onDeleteAllClickedListener;
}
public void setOnActionButtonClickedListener( OnItemClickedListener< Tip > onActionButtonClickedListener ) {
this.mOnActionButtonClickedListener = onActionButtonClickedListener;
}
public void setShowDelete( boolean showDelete ) {
this.mShowDelete = showDelete;
}
public void refresh( List< Tip > datums, boolean showDelete ) {
//this.da = datums;
setShowDelete( showDelete );
setDatas(datums);
//notifyDataSetChanged();
}
public void clear(){
mOnItemClickedListener = null;
mOnDeleteAllClickedListener = null;
mOnActionButtonClickedListener = null;
}
}

View File

@@ -0,0 +1,112 @@
package com.mogo.module.navi.ui.adapter.base;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
/**
* <p>
* Title: adapter
* </p>
* <p>
* Description:
* </p>
* <p>
* Copyright: Copyright (c) 2015
* </p>
* <p>
* </p>
*/
public abstract class RecycleBaseAdapter<T> extends
RecyclerView.Adapter<RecycleViewHolder>
{
protected Context context;
protected List<T> list;
private int resourceID;
private Toast toast;
/**
* @param context
*/
public RecycleBaseAdapter(Context context, List<T> list, int resourceID)
{
super();
this.context = context;
this.list = list;
this.resourceID = resourceID;
}
@Override
public RecycleViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType)
{
View v = LayoutInflater.from(context).inflate(resourceID, viewGroup,
false);
RecycleViewHolder holder = RecycleViewHolder
.get(v);
initHolder(holder);
return holder;
}
@Override
public void onBindViewHolder(
RecycleViewHolder viewHolder, int position)
{
onBindViewHolder(viewHolder, list.get(position % list.size()));
}
@Override
public int getItemCount()
{
return list == null ? 0 : list.size();
}
public abstract void onBindViewHolder(
RecycleViewHolder holder, T t);
public void initHolder(RecycleViewHolder holder)
{
}
public void setDatas(List<T> list)
{
setDatas(list, false);
}
public void setDatas(List<T> list, boolean add)
{
if (add)
{
this.list.addAll(list);
}
else
{
this.list = list;
}
notifyDataSetChanged();
}
public void messageShow(String mes)
{
if (toast==null){
toast= Toast.makeText(context,mes, Toast.LENGTH_LONG);
}
else{
toast.setText(mes);
}
toast.show();
}
public T getItem(int position){
if (list==null||list.size()==0){
return null;
}
return list.get(position);
}
}

View File

@@ -0,0 +1,138 @@
package com.mogo.module.navi.ui.adapter.base;
import android.graphics.Bitmap;
import android.text.SpannableString;
import android.util.SparseArray;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
public class RecycleViewHolder extends RecyclerView.ViewHolder {
private SparseArray<View> mViews;
private View mConvertView;
public RecycleViewHolder(View itemView) {
super(itemView);
this.mConvertView = itemView;
mViews = new SparseArray<View>();
// TODO Auto-generated constructor stub
}
public static RecycleViewHolder get(View itemView) {
return new RecycleViewHolder(itemView);
}
public View getConvertView() {
return mConvertView;
}
public <T extends View> T getView(int viewId) {
View view = mViews.get(viewId);
if (view == null) {
view = mConvertView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
/**
*
* @param viewId
* @param text
* @return
*/
public RecycleViewHolder setText(int viewId, String text) {
TextView tv = getView(viewId);
if (tv==null)return this;
tv.setText(text);
return this;
}
/**
*
* @param viewId
* @param text
* @return
*/
public RecycleViewHolder setText(int viewId, SpannableString text) {
TextView tv = getView(viewId);
tv.setText(text);
return this;
}
/**
*
* @param viewId
* @param resId
* @return
*/
public RecycleViewHolder setImageResource(int viewId, int resId) {
ImageView view = getView(viewId);
view.setImageResource(resId);
return this;
}
/**
*
* @param viewId
* @return
*/
public RecycleViewHolder setImageBitmap(int viewId, Bitmap bitmap) {
ImageView view = getView(viewId);
view.setImageBitmap(bitmap);
return this;
}
/**
*
* @param viewId
* @param resId
* @return
*/
// public ViewHolder setImageURI(int viewId, String url) {
// ImageView view = getView(viewId);
// // ImageLoader.getInstance.loadImg(view,url);
// return this;
// }
/**
*
* @param viewId
* @param resId
* @return
*/
public RecycleViewHolder setBackgroundImage(int viewId, int resId) {
View view = getView(viewId);
view.setBackgroundResource(resId);
return this;
}
/**
*
* @param viewId
* @param resId
* @return
*/
public RecycleViewHolder setTextColor(int viewId, int resId) {
TextView view = getView(viewId);
view.setTextColor(resId);
return this;
}
/**
*
* @param viewId
* @return
*/
public RecycleViewHolder setOnClickListener(int viewId,
OnClickListener listener) {
getView(viewId).setOnClickListener(listener);
return this;
}
}

View File

@@ -0,0 +1,50 @@
package com.mogo.module.navi.ui.base;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
* @author congtaowang
* @since 2019-10-04
* <p>
* 描述
*/
public abstract class AMapBaseFragment extends com.mogo.module.navi.database.ui.base.BaseFragment {
private static final String TAG = "amap.AMapBaseFragment";
@Override
public void onActivityCreated( @Nullable Bundle savedInstanceState ) {
super.onActivityCreated( savedInstanceState );
initViews();
}
protected abstract void initViews();
@Override
public void onResume() {
super.onResume();
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onSaveInstanceState( @NonNull Bundle outState ) {
super.onSaveInstanceState( outState );
}
@Override
public void onLowMemory() {
super.onLowMemory();
}
}

View File

@@ -0,0 +1,48 @@
package com.mogo.module.navi.ui.base;
import com.amap.api.maps.AMap;
import com.amap.api.navi.AMapNavi;
import com.amap.api.navi.AMapNaviView;
import com.amap.api.navi.model.AMapNaviPath;
import com.mogo.module.navi.lib.AMapNaviStatusChangedListener;
/**
* @author congtaowang
* @since 2019-10-01
* <p>
* 描述
*/
public interface AMapServiceVisitor {
AMapNaviView getNaviView();
AMap getMap();
AMapNavi getAMapNavi();
void registerNaviListener(AMapNaviStatusChangedListener listener);
/**
* 是否正在导航
*/
boolean isNaving();
void stopNavi();
void setHost(String host);
/**
* 将导航路线发送给launcher
*
* @param path
*/
void pushNaviPathToLauncher(AMapNaviPath path);
/**
* 将导航路线发送给launcher
*
* @param path 导航路线
* @param directly 是否直接发送
*/
void pushNaviPathToLauncher(AMapNaviPath path, boolean directly);
}

View File

@@ -0,0 +1,65 @@
package com.mogo.module.navi.ui.base;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.mogo.utils.SoftKeyBoardJobber;
import com.mogo.utils.statusbar.Eyes;
/**
* @author congtaowang
* @since 2019-10-02
* <p>
* 地图 activity 基类
*/
public class BaseActivity extends AppCompatActivity {
//@Override
//public Context getContext() {
// return this;
//}
@Override
protected void onCreate( @Nullable Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
Eyes.setStatusBarStyle( this, false, Color.parseColor( "#66000000" ), true );
getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN );
hideSystemUI();
}
protected void hideSystemUI() {
//隐藏虚拟按键
if ( Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19 ) { // lower api
View v = this.getWindow().getDecorView();
v.setSystemUiVisibility( View.GONE );
} else if ( Build.VERSION.SDK_INT >= 19 ) {
//for new api versions.
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView.setSystemUiVisibility( uiOptions );
}
}
protected boolean enableDispatchTouchEventToDismissSoftKeyBoard() {
return true;
}
@Override
public boolean dispatchTouchEvent( MotionEvent ev ) {
if ( ev.getAction() == MotionEvent.ACTION_DOWN && enableDispatchTouchEventToDismissSoftKeyBoard() ) {
SoftKeyBoardJobber.hideIfNecessary( this, ev );
return super.dispatchTouchEvent( ev );
}
// 必不可少否则所有的组件都不会有TouchEvent了
if ( getWindow().superDispatchTouchEvent( ev ) ) {
return true;
}
return onTouchEvent( ev );
}
}

View File

@@ -0,0 +1,73 @@
package com.mogo.module.navi.ui.base;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.mogo.utils.NetworkUtils;
/**
* @author congtaowang
* @since 2019-10-03
* <p>
* 描述
*/
public abstract class BaseFragment extends Fragment {
protected Context mContext;
private View mRootView;
@Override
public void onAttach( Context context ) {
super.onAttach( context );
mContext = context;
}
@Nullable
@Override
public View onCreateView( @NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable
Bundle savedInstanceState ) {
mRootView = inflater.inflate( getLayoutId(), container, false );
return mRootView;
}
protected abstract int getLayoutId();
protected < T extends View> T findViewById( @IdRes int id ) {
if ( mRootView != null ) {
return mRootView.findViewById( id );
}
if ( getView() != null ) {
return getView().findViewById( id );
}
return null;
}
protected void overridePendingTransition( int enter, int exit ) {
if ( getActivity() != null ) {
getActivity().overridePendingTransition( enter, exit );
}
}
protected boolean checkNetwork() {
return NetworkUtils.isConnected( mContext );
}
protected void shortToast( CharSequence msg ) {
if ( mContext != null && msg != null ) {
Toast.makeText( mContext, msg, Toast.LENGTH_SHORT ).show();
}
}
protected void longToast( CharSequence msg ) {
if ( mContext != null && msg != null ) {
Toast.makeText( mContext, msg, Toast.LENGTH_LONG ).show();
}
}
}

View File

@@ -0,0 +1,430 @@
package com.mogo.module.navi.ui.base;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.util.Log;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.CustomMapStyleOptions;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.navi.AMapNaviView;
import com.amap.api.navi.AMapNaviViewOptions;
import com.mogo.module.navi.R;
import com.mogo.module.navi.constants.AMapConstants;
import com.mogo.module.navi.constants.CustomMapStyle;
import com.mogo.utils.AssetsUtils;
/**
* @author congtaowang
* @since 2019-10-27
* <p>
* 描述
*/
public class MapUIController {
private static final String TAG = "MapUIController";
private static volatile MapUIController sInstance;
private int mLastZoomLevel;
private MapUIController() {
}
public static MapUIController getInstance() {
if ( sInstance == null ) {
synchronized ( MapUIController.class ) {
if ( sInstance == null ) {
sInstance = new MapUIController();
}
}
}
return sInstance;
}
public synchronized void release() {
mContext = null;
mMapView = null;
mAMap = null;
sInstance = null;
}
private Context mContext;
private AMapNaviView mMapView;
private AMap mAMap;
public synchronized void init( Context context, AMapNaviView mapView, AMap aMap ) {
this.mContext = context;
this.mMapView = mapView;
this.mAMap = aMap;
initMap();
changeMyLocationVisibility( true );
}
private boolean checkAMap() {
return mAMap != null;
}
private boolean checkAMapView() {
return mMapView != null;
}
/**
* 移除所有导航mapView的默认UI
*/
private void initMap() {
if ( mMapView != null ) {
AMapNaviViewOptions options = mMapView.getViewOptions();
if ( options != null ) {
// 设置是否开启自动黑夜模式切换默认为false不自动切换
options.setAutoNaviViewNightMode( false );
// 设置6秒后是否自动锁车
options.setAutoLockCar( true );
// 设置路线上的摄像头气泡是否显示
options.setCameraBubbleShow( true );
// 设置路线相关的配置属性,如:路线的路况颜色,路线上是否显示摄像头气泡等。
// options.setRouteOverlayOptions( MapStyleUtils.getRouteOverlayOptions() );
// 设置自车的图片对象
options.setCarBitmap( BitmapFactory.decodeResource( mContext.getResources(), R.drawable.ic_amap_navi_cursor ) );
// 设置指南针图标否在导航界面显示默认显示。true显示false隐藏。
options.setCompassEnabled( false );
//设置路况光柱条是否显示(只适用于驾车导航,需要联网)。
options.setTrafficBarEnabled( false );
// 设置[实时交通图层开关按钮]是否显示(只适用于驾车导航,需要联网)。
options.setTrafficLayerEnabled( false );
// 设置导航界面是否显示路线全览按钮。
options.setRouteListButtonShow( false );
// 设置起点位图,须在画路前设置
options.setStartPointBitmap( BitmapFactory.decodeResource( mContext.getResources(), R.drawable.ic_current_location_cursor ) );
// 设置终点位图,须在画路前设置
options.setEndPointBitmap( BitmapFactory.decodeResource( mContext.getResources(), R.drawable.ic_search_choice_point ) );
// 设置导航状态下屏幕是否一直开启。
options.setScreenAlwaysBright( true );
// 设置交通播报是否打开(只适用于驾车导航,需要联网)。
options.setTrafficInfoUpdateEnabled( true );
// 设置摄像头播报是否打开(只适用于驾车导航)。
options.setCameraInfoUpdateEnabled( true );
// 设置菜单按钮是否在导航界面显示。
options.setSettingMenuEnabled( false );
// 设置是否绘制显示交通路况的线路(彩虹线),拥堵-红色,畅通-绿色,缓慢-黄色,未知-蓝色。默认不绘制彩虹线。
options.setTrafficLine( true );
// 设置是否绘制牵引线(当前位置到目的地的指引线)。默认不绘制牵引线。
options.setLeaderLineEnabled( -1 );
// 设置导航界面UI是否显示。
options.setLayoutVisible( false );
// 设置是否自动画路
options.setAutoDrawRoute( false );
// 设置是否显示路口放大图(实景图)
options.setRealCrossDisplayShow( false );
// 设置是否显示路口放大图(路口模型图)
options.setModeCrossDisplayShow( false );
// 设置是否显示道路信息view
options.setLaneInfoShow( false );
// 设置是否自动改变缩放等级
options.setAutoChangeZoom( false );
// 设置是否自动全览模式,即在算路成功后自动进入全览模式
options.setAutoDisplayOverview( false );
// 设置路线转向箭头隐藏和显示
options.setNaviArrowVisible( false );
// 通过路线是否自动置灰,仅支持驾车导航
options.setAfterRouteAutoGray( true );
options.setPointToCenter( 0.5D, 0.5D );
mMapView.setViewOptions( options );
}
mMapView.setNaviMode( AMapNaviView.CAR_UP_MODE );
}
if ( mAMap != null ) {
mAMap.setTrafficEnabled( true );
UiSettings uiSettings = mAMap.getUiSettings();
if ( uiSettings != null ) {
//设置所有手势是否可用
uiSettings.setAllGesturesEnabled( true );
//设置指南针是否可见。
uiSettings.setCompassEnabled( false );
//设置是否以地图中心点缩放
uiSettings.setGestureScaleByMapCenter( true );
//设置室内地图楼层切换控件是否可见。
uiSettings.setIndoorSwitchEnabled( true );
//设置定位按钮是否可见。
uiSettings.setMyLocationButtonEnabled( false );
//设置旋转手势是否可用。
uiSettings.setRotateGesturesEnabled( false );
//设置比例尺控件是否可见
uiSettings.setScaleControlsEnabled( false );
//设置拖拽手势是否可用。
uiSettings.setScrollGesturesEnabled( true );
//设置倾斜手势是否可用。
uiSettings.setTiltGesturesEnabled( true );
//设置缩放按钮是否可见。
uiSettings.setZoomControlsEnabled( false );
//设置双指缩放手势是否可用。
uiSettings.setZoomGesturesEnabled( true );
}
mAMap.setCustomMapStyle( new CustomMapStyleOptions()
.setEnable( true )
.setStyleId( CustomMapStyle.STYLE_ID )
.setStyleData( AssetsUtils.read( mContext, CustomMapStyle.ASSET_STYLE_DATA ) )
.setStyleExtraData( AssetsUtils.read( mContext, CustomMapStyle.ASSET_STYLE_EXTRA_DATA ) )
);
}
}
/**
* 控制我的位置图层及定位回调能力
*
* @param visibility
*/
public void changeMyLocationVisibility( boolean visibility ) {
if ( mAMap == null ) {
return;
}
mAMap.setMyLocationEnabled( visibility );
Log.d( TAG, visibility ? "开启定位" : "关闭定位" );
if ( visibility ) {
MyLocationStyle style = mAMap.getMyLocationStyle();
if ( style == null ) {
style = new MyLocationStyle();
}
style.myLocationType( MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER )
.strokeWidth( 0 )
.interval( 2_000L )
.showMyLocation( visibility )
.myLocationIcon( BitmapDescriptorFactory.fromResource( R.drawable.ic_current_location_cursor ) )
.radiusFillColor( Color.TRANSPARENT );
mAMap.setMyLocationStyle( style );
}
}
/**
* 导航模式:中心点偏下
*/
public void showNaviUI() {
changeMyLocationVisibility( false );
changeCarOverlayVisibility( true );
changeRouteOverlayVisibility( false );
if ( mMapView != null ) {
mMapView.setNaviMode( AMapNaviView.CAR_UP_MODE );
mMapView.post( () -> {
AMapNaviViewOptions options = mMapView.getViewOptions();
if ( options != null ) {
Log.d( TAG, "中心点切换到页面偏下" );
options.setPointToCenter( 0.5D, 0.6666666666666666D );
mMapView.setViewOptions( options );
if ( checkAMap() ) {
mAMap.moveCamera( CameraUpdateFactory.zoomBy( 15 ) );
}
}
} );
}
}
/**
* 正常地图模式:中心点居中
*/
public void showMapUI() {
changeMyLocationVisibility( true );
changeCarOverlayVisibility( false );
changeRouteOverlayVisibility( false );
if ( mMapView != null ) {
AMapNaviViewOptions options = mMapView.getViewOptions();
if ( options != null ) {
Log.d( TAG, "中心点切换到页面中心" );
options.setPointToCenter( 0.5D, 0.5D );
mMapView.setViewOptions( options );
}
}
}
/**
* 显示规划UI样式中心点右移
*/
public void showCalculateUI() {
changeMyLocationVisibility( false );
}
/**
* 控制自车marker
*
* @param visibility
*/
public void changeCarOverlayVisibility( boolean visibility ) {
try {
mMapView.setCarOverlayVisible( visibility );
} catch ( Exception e ) {
}
}
/**
* 控制导航路线图层
*
* @param visibility
*/
public void changeRouteOverlayVisibility( boolean visibility ) {
try {
mMapView.setRouteOverlayVisible( visibility );
} catch ( Exception e ) {
}
}
/**
* 将地图移动到中心点,正北方向
*
* @param latlng
*/
public void moveCurrentPositionToCenter( LatLng latlng ) {
if ( checkAMap() ) {
mAMap.animateCamera( CameraUpdateFactory.newCameraPosition( new CameraPosition.Builder()
.tilt( mMapView.getLockTilt() )
.zoom( mMapView.getLockZoom() )
.target( latlng )
.bearing( AMapConstants.AMPA_BEARING )
.build() ) );
}
}
/**
* 改变地图缩放级别
*
* @param level
*/
public void changeCameraZoomLevel( float level, boolean animate ) {
if ( checkAMap() ) {
if ( animate ) {
mAMap.animateCamera( CameraUpdateFactory.zoomTo( level ) );
} else {
mAMap.moveCamera( CameraUpdateFactory.zoomTo( level ) );
}
}
}
/**
* 添加marker
*
* @param options
* @return
*/
public Marker addMarker( MarkerOptions options ) {
return mAMap.addMarker( options );
}
/**
* 缓存上次地图缩放级别
*
* @return
*/
public boolean storeMapZoomLevel() {
if ( checkAMapView() ) {
final AMapNaviViewOptions options = mMapView.getViewOptions();
if ( options != null ) {
mLastZoomLevel = options.getZoom();
return true;
}
}
return false;
}
/**
* 还原上次的缩放级别
*/
public void restoreMapZoomLevel() {
if ( checkAMapView() ) {
final AMapNaviViewOptions options = mMapView.getViewOptions();
if ( options != null ) {
options.setZoom( mLastZoomLevel );
mMapView.setViewOptions( options );
}
}
}
/**
* 交通态势开关
*
* @param enable
*/
public void setTrafficEnabled( boolean enable ) {
if ( checkAMap() ) {
mAMap.setTrafficEnabled( enable );
}
}
/**
* 缩放地图
*
* @param zoomIn 放大
*/
public void changeZoom( boolean zoomIn ) {
if ( checkAMapView() ) {
if ( zoomIn ) {
mMapView.zoomIn();
} else {
mMapView.zoomOut();
}
}
}
/**
* 设置地图类型
*
* @param type
*/
public void setMapType( int type ) {
if ( checkAMap() ) {
mAMap.setMapType( type );
}
}
/**
* 导航样式:
*
* @param naviMode
*/
public void setNaviMode( int naviMode ) {
if ( checkAMapView() ) {
mMapView.setNaviMode( naviMode );
}
}
/**
* 地图倾斜度
*
* @param tile
*/
public void setTilt( int tile ) {
if ( checkAMapView() ) {
final AMapNaviViewOptions options = mMapView.getViewOptions();
if ( options != null ) {
options.setTilt( tile );
mMapView.setViewOptions( options );
}
}
}
/**
* 预览全程
*/
public void displayOverview() {
if ( checkAMapView() ) {
mMapView.displayOverview();
}
}
/**
* 关闭全程预览
*/
public void recoverLockMode() {
if ( checkAMapView() ) {
mMapView.recoverLockMode();
}
}
}

View File

@@ -0,0 +1,53 @@
package com.mogo.module.navi.ui.base;
import androidx.fragment.app.FragmentManager;
/**
* @author congtaowang
* @since 2019-10-04
* <p>
* 描述
*/
public interface UiController {
/**
* 显示地图模式
*/
void onMapMode();
/**
* 显示导航模式
*/
void onNaviMode();
/**
* 搜索地址
*
* @param searchType {@link com.zhidao.amap.splitunit.ui.search.SearchConstants}
*/
void onSearchMode(int searchType);
/**
* 规划路径
*/
void onCalculateMode();
/**
* 设置
*/
void onSettingsMode();
/**
* 直接退出应用
*/
void finishDirectly();
FragmentManager _getSupportFragmentManager();
AMapServiceVisitor getAMapServiceVisitor();
//CommonAddressModel getCommonAddressModel();
void popBackStackImmediate();
}

View File

@@ -0,0 +1,54 @@
package com.mogo.module.navi.ui.search;
import com.mogo.module.navi.constants.DataConstants;
/**
* @author congtaowang
* @since 2019-12-08
* <p>
* 搜索页面常量字段
*/
public class SearchConstants {
/**
* 搜索页面类型
*/
public static final String KEY_SEARCH_TYPE = "type";
/**
* 普通搜索:首页搜索按钮点击
*/
public static final int SEARCH_TYPE_COMMON = DataConstants.TYPE_POI;
/**
* 设置家:多种搜索方式:普通搜索、我的位置、地图选点
*/
public static final int SEARCH_TYPE_MULTI_HOME = DataConstants.TYPE_HOME_ADDRESS;
/**
* 设置公司:多种搜索方式:普通搜索、我的位置、地图选点
*/
public static final int SEARCH_TYPE_MULTI_COMPANY = DataConstants.TYPE_COMPANY_ADDRESS;
/**
* 搜索页面当前状态
*/
public static final int UI_MODE_COMMON = 1;
/**
* 搜索页面当前状态:常用地址搜索模式
*/
public static final int UI_MODE_MULTI = 2;
/**
* 搜索页面当前状态:常用地址搜索模式
*/
public static final int UI_MODE_MULTI_SEARCH = 5;
/**
* 搜索页面当前状态:我的位置模式
*/
public static final int UI_MODE_MULTI_MY_LOCATION = 3;
/**
* 搜索页面当前状态:选点模式
*/
public static final int UI_MODE_MULTI_CHOICE_POINT = 4;
}

View File

@@ -0,0 +1,569 @@
package com.mogo.module.navi.ui.search;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.animation.Animation;
import com.amap.api.maps.model.animation.TranslateAnimation;
import com.amap.api.services.geocoder.RegeocodeAddress;
import com.amap.api.services.help.Tip;
import com.mogo.module.map.location.AMapLocationManager;
import com.mogo.module.navi.R;
import com.mogo.module.navi.bean.EntityConvertUtils;
import com.mogo.module.navi.bean.SearchPoi;
import com.mogo.module.navi.ui.adapter.SearchPoiAdapter;
import com.mogo.module.navi.ui.base.BaseFragment;
import com.mogo.module.navi.ui.base.MapUIController;
import com.mogo.module.navi.ui.base.UiController;
import com.mogo.utils.WindowUtils;
import io.reactivex.disposables.Disposable;
import java.util.List;
/**
* 搜索页面
* <p>
* 普通搜索:从首页点击搜索按钮进入:包含:仅输入搜索(列表不包含设置按钮)
* {@link SearchConstants#SEARCH_TYPE_COMMON}
* <p>
* 地址设置搜索:设置家、公司、其他的地址:包含当前位置、选点、搜索列表(列表包含设置按钮)、普通页面
* {@link SearchConstants#SEARCH_TYPE_MULTI_COMPANY}
* {@link SearchConstants#SEARCH_TYPE_MULTI_HOME}
*/
@Route( path = "/amap/search" )
public class SearchFragment extends BaseFragment implements SearchView,
AMapLocationListener {
public static final String TAG = "search";
public int mSearchType;
private SearchPresenter mSearchPresenter;
private View mClose;
private EditText mSearchBox;
private RecyclerView mSearchResult;
private SearchPoiAdapter mPoiAdapter;
private View mMyLocation;
private View mChoicePoint;
private View mCurrentLocation;
/**
* 设置常用地址(我的位置、选点)时的设置按钮
*/
private TextView mActionButton;
private UiController mUiController;
private Bitmap mSearchBoxRightDrawableBitmap = null;
/**
* 地址设置是否完成
*/
private boolean mActionSuccess = false;
/**
* 当前UI的样式具体是哪个操作
*/
private int mUiMode = SearchConstants.UI_MODE_COMMON;
/**
* 地图选点的marker
*/
private Marker mChoicePointMaker = null;
private AMapLocation mLastAMapLocation;
@Override
public void onAttach( Context context ) {
super.onAttach( context );
if ( context instanceof UiController) {
mUiController = ( ( UiController ) context );
}
}
@Override
protected int getLayoutId() {
return R.layout.fragment_search;
}
@Override
public void onActivityCreated( @Nullable Bundle savedInstanceState ) {
super.onActivityCreated( savedInstanceState );
initViews();
getLifecycle().addObserver( mSearchPresenter = new SearchPresenter( this ) );
}
private void initViews() {
mClose = findViewById( R.id.amap_search_close );
mClose.setOnClickListener( view -> {
exitSearch();
} );
mSearchBox = findViewById( R.id.amap_search_search_box );
mSearchResult = findViewById( R.id.amap_search_poi_result );
mSearchResult.setLayoutManager( new LinearLayoutManager( mContext, LinearLayoutManager.VERTICAL, false ) );
mMyLocation = findViewById( R.id.amap_search_poi_my_location );
mMyLocation.setOnClickListener( view -> {
if ( !checkNetwork() ) {
shortToast( "网络未连接,请检查网络" );
return;
}
multiSearchMyLocationUI();
AMapLocationManager.getInstance( mContext ).addLocationListener( this );
AMapLocationManager.getInstance( mContext ).start();
} );
mChoicePoint = findViewById( R.id.amap_search_poi_choice_point );
mChoicePoint.setOnClickListener( view -> {
multiSearchChoicePointUI();
} );
mCurrentLocation = findViewById( R.id.amap_search_current_location );
mCurrentLocation.setOnClickListener( view -> {
if ( !checkNetwork() ) {
shortToast( "网络未连接,请检查网络" );
return;
}
AMapLocationManager.getInstance( mContext ).addLocationListener( this );
AMapLocationManager.getInstance( mContext ).start();
} );
mActionButton = findViewById( R.id.amap_search_action_setting );
mActionButton.setOnClickListener( view -> {
if ( mUiMode == SearchConstants.UI_MODE_MULTI_MY_LOCATION ) {
saveCurrentLocationAsCommonAddress();
} else if ( mUiMode == SearchConstants.UI_MODE_MULTI_CHOICE_POINT ) {
saveRegeoAddressAsCommonAddress();
}
} );
switch ( mSearchType ) {
case SearchConstants.SEARCH_TYPE_COMMON:
commonSearchUI();
break;
case SearchConstants.SEARCH_TYPE_MULTI_HOME:
case SearchConstants.SEARCH_TYPE_MULTI_COMPANY:
multiSearchUI();
break;
}
}
/**
* 普通搜索UI不显示我的位置、地图选点、我的定位
*/
private void commonSearchUI() {
mUiMode = SearchConstants.UI_MODE_COMMON;
mSearchBox.setEnabled( true );
mMyLocation.setVisibility( View.GONE );
mChoicePoint.setVisibility( View.GONE );
mCurrentLocation.setVisibility( View.GONE );
mActionButton.setVisibility( View.INVISIBLE );
mSearchResult.setVisibility( View.GONE );
if ( mSearchBox.getCompoundDrawables()[2] == null ) {
Drawable rightDrawable = null;
if ( mSearchBoxRightDrawableBitmap == null ) {
mSearchBoxRightDrawableBitmap = BitmapFactory.decodeResource( getResources(), R.drawable.ic_search_unshadow );
}
rightDrawable = new BitmapDrawable( getResources(), mSearchBoxRightDrawableBitmap );
mSearchBox.setCompoundDrawables( null, null, rightDrawable, null );
rightDrawable.setBounds( 0, 0, rightDrawable.getIntrinsicWidth(), rightDrawable.getIntrinsicHeight() );
}
removeChoicePointMarker();
mSearchBox.setTag( null );
if ( mSearchBox.getLayoutParams() instanceof RelativeLayout.LayoutParams ) {
final RelativeLayout.LayoutParams params = ( ( RelativeLayout.LayoutParams ) mSearchBox.getLayoutParams() );
params.removeRule( RelativeLayout.LEFT_OF );
mSearchBox.setPadding( 0, 0, WindowUtils.dip2px( mContext, 0 ), 0 );
mSearchBox.setLayoutParams( params );
}
mLastAMapLocation = null;
}
/**
* 多项搜索:显示我的位置、地图选点、我的定位
*/
private void multiSearchUI() {
mUiMode = SearchConstants.UI_MODE_MULTI;
mSearchBox.setText( "" );
mSearchBox.setEnabled( true );
mMyLocation.setVisibility( View.VISIBLE );
mChoicePoint.setVisibility( View.VISIBLE );
mCurrentLocation.setVisibility( View.VISIBLE );
mSearchResult.setVisibility( View.GONE );
if ( mSearchBox.getCompoundDrawables()[2] == null ) {
Drawable rightDrawable = null;
if ( mSearchBoxRightDrawableBitmap == null ) {
mSearchBoxRightDrawableBitmap = BitmapFactory.decodeResource( getResources(), R.drawable.ic_search_unshadow );
}
rightDrawable = new BitmapDrawable( getResources(), mSearchBoxRightDrawableBitmap );
rightDrawable.setBounds( 0, 0, rightDrawable.getIntrinsicWidth(), rightDrawable.getIntrinsicHeight() );
mSearchBox.setCompoundDrawables( null, null, rightDrawable, null );
}
mActionButton.setVisibility( View.INVISIBLE );
removeChoicePointMarker();
mSearchBox.setTag( null );
if ( mSearchBox.getLayoutParams() instanceof RelativeLayout.LayoutParams ) {
final RelativeLayout.LayoutParams params = ( ( RelativeLayout.LayoutParams ) mSearchBox.getLayoutParams() );
params.removeRule( RelativeLayout.LEFT_OF );
mSearchBox.setPadding( 0, 0, WindowUtils.dip2px( mContext, 0 ), 0 );
mSearchBox.setLayoutParams( params );
}
mLastAMapLocation = null;
}
/**
* 显示我的位置,并且可设置为家
*/
private void multiSearchMyLocationUI() {
mUiMode = SearchConstants.UI_MODE_MULTI_MY_LOCATION;
mSearchBox.setEnabled( false );
mMyLocation.setVisibility( View.GONE );
mChoicePoint.setVisibility( View.GONE );
mCurrentLocation.setVisibility( View.GONE );
mSearchResult.setVisibility( View.GONE );
mActionButton.setVisibility( View.VISIBLE );
mActionButton.setText( SearchUtils.getSearchTypeActionName( mSearchType ) );
mSearchBox.setCompoundDrawables( null, null, null, null );
removeChoicePointMarker();
mSearchBox.setTag( null );
if ( mSearchBox.getLayoutParams() instanceof RelativeLayout.LayoutParams ) {
final RelativeLayout.LayoutParams params = ( ( RelativeLayout.LayoutParams ) mSearchBox.getLayoutParams() );
params.addRule( RelativeLayout.LEFT_OF, R.id.amap_search_action_setting );
mSearchBox.setPadding( 0, 0, WindowUtils.dip2px( mContext, 15 ), 0 );
mSearchBox.setLayoutParams( params );
}
}
/**
* 显示我的位置,并且可设置为家
*/
private void multiSearchChoicePointUI() {
mUiMode = SearchConstants.UI_MODE_MULTI_CHOICE_POINT;
mSearchBox.setEnabled( false );
mMyLocation.setVisibility( View.GONE );
mChoicePoint.setVisibility( View.GONE );
mCurrentLocation.setVisibility( View.GONE );
mSearchResult.setVisibility( View.GONE );
mActionButton.setVisibility( View.VISIBLE );
mActionButton.setText( SearchUtils.getSearchTypeActionName( mSearchType ) );
mSearchBox.setCompoundDrawables( null, null, null, null );
showChoicePointMarker();
mSearchBox.setTag( null );
if ( mSearchBox.getLayoutParams() instanceof RelativeLayout.LayoutParams ) {
final RelativeLayout.LayoutParams params = ( ( RelativeLayout.LayoutParams ) mSearchBox.getLayoutParams() );
params.addRule( RelativeLayout.LEFT_OF, R.id.amap_search_action_setting );
mSearchBox.setPadding( 0, 0, WindowUtils.dip2px( mContext, 15 ), 0 );
mSearchBox.setLayoutParams( params );
}
mLastAMapLocation = null;
}
private void saveCurrentLocationAsCommonAddress() {
if ( mLastAMapLocation == null ) {
shortToast( "定位失败,请重试" );
return;
}
final Disposable disposable = mSearchPresenter.cacheCommonAddressPoi( mLastAMapLocation ).subscribe( output -> {
Toast.makeText( mContext, "设置成功!", Toast.LENGTH_SHORT ).show();
mActionSuccess = true;
}, error -> {
if ( error instanceof Exception) {
Toast.makeText( mContext, ( (Exception) error ).getMessage(), Toast.LENGTH_SHORT ).show();
mActionSuccess = false;
}
} );
mSearchPresenter.addDisposable( disposable );
}
private void saveRegeoAddressAsCommonAddress() {
if ( mSearchBox.getTag() instanceof RegeocodeAddress ) {
final Disposable disposable = mSearchPresenter.cacheCommonAddressPoi( ( ( RegeocodeAddress ) mSearchBox.getTag() ) ).subscribe( output -> {
Toast.makeText( mContext, "设置成功!", Toast.LENGTH_SHORT ).show();
mActionSuccess = true;
}, error -> {
if ( error instanceof Exception) {
Toast.makeText( mContext, ( (Exception) error ).getMessage(), Toast.LENGTH_SHORT ).show();
mActionSuccess = false;
}
} );
mSearchPresenter.addDisposable( disposable );
} else {
Toast.makeText( mContext, "请选择位置", Toast.LENGTH_SHORT ).show();
}
}
@Override
public void onLocationChanged( AMapLocation aMapLocation ) {
//final String checkMsg = AMapUtils.getAMapLocationErrorMsg( aMapLocation );
//if ( AMapUtils.LOC_SUCCESS.equals( checkMsg ) ) {
// mLastAMapLocation = aMapLocation;
// MapUIController.getInstance().moveCurrentPositionToCenter( new LatLng( aMapLocation.getLatitude(), aMapLocation.getLongitude() ) );
// if ( mUiMode == SearchConstants.UI_MODE_MULTI_MY_LOCATION ) {
// showMyLocationAddress( aMapLocation );
// } else if ( mUiMode == SearchConstants.UI_MODE_MULTI_CHOICE_POINT ) {
// showChoicePointAddress( aMapLocation );// 显示当前中心点地址
// }
//} else {
// Toast.makeText( mContext, checkMsg, Toast.LENGTH_SHORT ).show();
//}
AMapLocationManager.getInstance( mContext ).removeLocationListener( this );
AMapLocationManager.getInstance( mContext ).stop();
}
private void showMyLocationAddress( AMapLocation location ) {
if ( location == null ) {
return;
}
mSearchBox.setEnabled( false );
mSearchBox.setText( location.getPoiName() );
}
/**
* 显示点选marker隐藏自车marker
*/
private void showChoicePointMarker() {
final AMap aMap = mUiController.getAMapServiceVisitor().getMap();
if ( aMap == null ) {
return;
}
// AMapService 里设置了监听,此处会覆盖
LatLng latLng = aMap.getCameraPosition().target;
Point screenPosition = aMap.getProjection().toScreenLocation( latLng );
mChoicePointMaker = aMap.addMarker( new MarkerOptions().zIndex( 1 ).anchor( 0.5f, 0.5f ).position( latLng ).icon( BitmapDescriptorFactory.fromResource( R.drawable.ic_search_choice_point ) ) );
mChoicePointMaker.setPositionByPixels( screenPosition.x, screenPosition.y );
MapUIController.getInstance().changeMyLocationVisibility( false );
}
/**
* 隐藏点选marker显示自车marker
*/
private void removeChoicePointMarker() {
if ( mChoicePointMaker != null ) {
mChoicePointMaker.remove();
}
mChoicePointMaker = null;
MapUIController.getInstance().changeMyLocationVisibility( true );
}
private void showChoicePointAddress( AMapLocation location ) {
if ( location == null ) {
return;
}
mSearchBox.setEnabled( false );
mSearchBox.setText( location.getPoiName() );
}
// view interface
@Override
public EditText getSearchBox() {
return mSearchBox;
}
@Override
public void renderSearchPoiResult( List< Tip > datums, boolean showDelete ) {
if ( datums == null || datums.isEmpty() ) {
mSearchResult.setVisibility( View.GONE );
} else {
mSearchResult.setVisibility( View.VISIBLE );
}
if ( mPoiAdapter == null ) {
mPoiAdapter = new SearchPoiAdapter(getContext(), datums );
mPoiAdapter.setOnItemClickedListener( item -> {
if ( mSearchType == SearchConstants.SEARCH_TYPE_COMMON ) {
final Disposable disposable = mSearchPresenter.cacheSelectPoiItem( item ).subscribe( output -> {
navi2Location( EntityConvertUtils.tipToPoi( item ) );
} );
mSearchPresenter.addDisposable( disposable );
} else {
// do nothing.
}
} );
mPoiAdapter.setOnDeleteAllClickedListener( NULL -> {
mSearchPresenter.deleteAllCachedPoi();
} );
mPoiAdapter.setOnActionButtonClickedListener( poi -> {
final Disposable disposable = mSearchPresenter.cacheCommonAddressPoi( poi ).subscribe( output -> {
Toast.makeText( mContext, "设置成功!", Toast.LENGTH_SHORT ).show();
mActionSuccess = true;
} );
mSearchPresenter.addDisposable( disposable );
} );
mPoiAdapter.setShowDelete( showDelete );
mSearchResult.setAdapter( mPoiAdapter );
} else {
if ( datums != null && !datums.isEmpty() ) {
mSearchResult.scrollToPosition( 0 );
}
mPoiAdapter.refresh( datums, showDelete );
}
}
@Override
public int getSearchType() {
return mSearchType;
}
@Override
public int getUiMode() {
return mUiMode;
}
@Override
public void renderChoicePointResult( RegeocodeAddress address ) {
if ( address == null ) {
mSearchBox.setTag( null );
mSearchBox.setText( "" );
return;
}
mSearchBox.setTag( address );
mSearchBox.setText( address.getFormatAddress() );
}
//@Override
//public void renderErrorView() {
//
//}
//
//@Override
//public void renderContentView() {
//
//}
// view interface end
/**
* 屏幕中心marker 跳动
*/
@Override
public void startJumpAnimation() {
final AMap aMap = mUiController.getAMapServiceVisitor().getMap();
if ( mChoicePointMaker != null ) {
//根据屏幕距离计算需要移动的目标点
final LatLng latLng = mChoicePointMaker.getPosition();
Point point = aMap.getProjection().toScreenLocation( latLng );
point.y -= WindowUtils.dip2px( mContext, 125 );
LatLng target = aMap.getProjection()
.fromScreenLocation( point );
//使用TranslateAnimation,填写一个需要移动的目标点
Animation animation = new TranslateAnimation( target );
animation.setInterpolator( new Interpolator() {
@Override
public float getInterpolation( float input ) {
// 模拟重加速度的interpolator
if ( input <= 0.5 ) {
return ( float ) ( 0.5f - 2 * ( 0.5 - input ) * ( 0.5 - input ) );
} else {
return ( float ) ( 0.5f - Math.sqrt( ( input - 0.5f ) * ( 1.5f - input ) ) );
}
}
} );
//整个移动所需要的时间
animation.setDuration( 600 );
//设置动画
mChoicePointMaker.setAnimation( animation );
//开始动画
mChoicePointMaker.startAnimation();
}
}
/**
* @param searchPoi 导航目的地
*/
private void navi2Location( SearchPoi searchPoi ) {
if ( searchPoi == null || searchPoi == SearchPoi.NULL ) {
Toast.makeText( mContext, "未设置", Toast.LENGTH_SHORT ).show();
return;
}
//SearchPoiLiveData.getInstance().postValue( searchPoi );
exitSearch();
}
/**
* 退出搜索,进行清理
*/
private void exitSearch() {
switch ( mSearchType ) {
case SearchConstants.SEARCH_TYPE_COMMON:
try {
mUiController.popBackStackImmediate();
} catch ( Exception e ) {
e.printStackTrace();
}
break;
case SearchConstants.SEARCH_TYPE_MULTI_HOME:
case SearchConstants.SEARCH_TYPE_MULTI_COMPANY:
if ( !mActionSuccess ) {
// 通过搜索框搜索,在设置成功之前点击返回按钮,返回到未搜索状态
if ( mUiMode != SearchConstants.UI_MODE_MULTI || mSearchResult.getVisibility() == View.VISIBLE ) {
multiSearchUI();
return;
}
}
try {
mUiController.popBackStackImmediate();
mUiController.onSettingsMode();
} catch ( Exception e ) {
e.printStackTrace();
}
break;
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
if ( mSearchPresenter != null ) {
mSearchPresenter.onDestroy( getViewLifecycleOwner() );
getLifecycle().removeObserver( mSearchPresenter );
mSearchPresenter = null;
}
mSearchBox.setTag( null );
mUiController = null;
if ( mSearchBoxRightDrawableBitmap != null ) {
try {
mSearchBoxRightDrawableBitmap.recycle();
} catch ( Exception e ) {
}
}
if ( mPoiAdapter != null ) {
mPoiAdapter.clear();
}
mPoiAdapter = null;
mSearchBoxRightDrawableBitmap = null;
removeChoicePointMarker();
AMapLocationManager.getInstance( mContext ).release();
}
}

View File

@@ -0,0 +1,294 @@
package com.mogo.module.navi.ui.search;
import android.app.AlertDialog;
import android.text.Editable;
import android.text.TextUtils;
import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import com.amap.api.location.AMapLocation;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeAddress;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.amap.api.services.help.Inputtips;
import com.amap.api.services.help.InputtipsQuery;
import com.amap.api.services.help.Tip;
import com.mogo.commons.mvp.Presenter;
import com.mogo.module.common.TextWatcherAdapter;
import com.mogo.module.navi.bean.EntityConvertUtils;
import com.mogo.module.navi.bean.SearchPoi;
import com.mogo.module.navi.constants.DataConstants;
import com.mogo.module.navi.database.AppDataBase;
import io.reactivex.Single;
import io.reactivex.SingleEmitter;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import java.util.List;
/**
* @author congtaowang
* @since 2019-10-02
* <p>
* 搜搜页逻辑处理
*/
public class SearchPresenter extends Presenter< SearchView >
implements Inputtips.InputtipsListener, GeocodeSearch.OnGeocodeSearchListener {
private Inputtips mSearchEngine;
private GeocodeSearch mGeocodeSearch;
private CompositeDisposable mCompositeDisposable;
private CameraPosition mLastCameraPosition;
public SearchPresenter( SearchView view ) {
super( view );
mCompositeDisposable = new CompositeDisposable();
}
@Override
public void onCreate( @NonNull LifecycleOwner owner ) {
super.onCreate( owner );
attachSearchBoxTextWatcher( mView.getSearchBox() );
switch ( mView.getSearchType() ) {
case SearchConstants.SEARCH_TYPE_COMMON:
loadHistories();
break;
}
}
private void loadHistories() {
}
private void attachSearchBoxTextWatcher( EditText editText ) {
if ( editText == null ) {
return;
}
editText.addTextChangedListener(watcherAdapter);
}
private final TextWatcherAdapter watcherAdapter = new TextWatcherAdapter() {
@Override
public void afterTextChanged( Editable s ) {
// 避免 disable 设置内容时触发
final String input = s.toString();
startSearchPoiByInput( input );
}
};
private void startSearchPoiByInput( String keyword ) {
switch ( mView.getUiMode() ) {
// 如果是普通搜索,清空搜索内容后需要加载缓存历史,否则不需要
case SearchConstants.UI_MODE_COMMON:
if ( TextUtils.isEmpty( keyword ) ) {
loadHistories();
return;
}
break;
case SearchConstants.UI_MODE_MULTI_CHOICE_POINT:
case SearchConstants.UI_MODE_MULTI_MY_LOCATION:
return;
case SearchConstants.UI_MODE_MULTI:
if ( TextUtils.isEmpty( keyword ) ) {
mView.renderSearchPoiResult( null, false );
return;
}
break;
}
final InputtipsQuery searchQuery = new InputtipsQuery( keyword, "" );
if ( mSearchEngine == null ) {
mSearchEngine = new Inputtips( getContext(), searchQuery );
mSearchEngine.setInputtipsListener( this );
} else {
mSearchEngine.setQuery( searchQuery );
}
mSearchEngine.requestInputtipsAsyn();
}
@Override
public void onGetInputtips( List<Tip> list, int i ) {
if ( mView != null ) {
mView.renderSearchPoiResult( list, false );
}
}
/**
* 缓存搜索到的导航地址
*
* @param tip
* @return
*/
public Single cacheSelectPoiItem( Tip tip ) {
return Single.create( emitter -> {
SearchPoi poi = EntityConvertUtils.tipToPoi( tip );
//ignore insert result
final List<Long> output = AppDataBase.getDatabase( getContext() ).poiDao().insert( poi );
emitter.onSuccess( output );
} ).subscribeOn( Schedulers.io() ).observeOn( AndroidSchedulers.mainThread() );
}
public void addDisposable( Disposable disposable ) {
mCompositeDisposable.add( disposable );
}
public void deleteAllCachedPoi() {
new AlertDialog.Builder( getContext() )
.setMessage( "清空历史记录?" )
.setPositiveButton( "立即清空", ( dlg, which ) -> {
dlg.dismiss();
deleteAllCachedPoiImpl();
} )
.setNegativeButton( "取消", ( dlg, which ) -> {
dlg.dismiss();
} )
.create()
.show();
}
private void deleteAllCachedPoiImpl() {
final Disposable disposable = AppDataBase.getDatabase( getContext() )
.poiDao()
.getAll()
.map( input -> {
return AppDataBase.getDatabase( getContext() ).poiDao().deleteAll( input );
} )
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() )
.subscribe( count -> {
mView.renderSearchPoiResult( null, false );
} );
mCompositeDisposable.add( disposable );
}
/**
* 缓存搜索位置为常用地址设置
*
* @param tip
* @return
*/
public Single cacheCommonAddressPoi( Tip tip ) {
return Single.<List<Long>>create( emitter -> {
SearchPoi poi = EntityConvertUtils.tipToPoi( tip );
emitterCommonAddress( emitter, poi );
} ).subscribeOn( Schedulers.io() ).observeOn( AndroidSchedulers.mainThread() );
}
/**
* 缓存地理位置常用地址设置
*
* @param location
* @return
*/
public Single cacheCommonAddressPoi( AMapLocation location ) {
return Single.
<List<Long>>create( emitter -> {
SearchPoi poi = EntityConvertUtils.aMapLocation2Poi( location );
emitterCommonAddress( emitter, poi );
} )
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() );
}
/**
* 缓存反地理位置编码常用地址设置
*
* @param address
* @return
*/
public Single cacheCommonAddressPoi( RegeocodeAddress address ) {
return Single.
<List<Long>>create( emitter -> {
SearchPoi poi = EntityConvertUtils.geocodeAddress2Poi( address, mLastCameraPosition );
emitterCommonAddress( emitter, poi );
} )
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() );
}
private void emitterCommonAddress( SingleEmitter<List<Long>> emitter, SearchPoi poi ) {
String poiId = null;
switch ( mView.getSearchType() ) {
case SearchConstants.SEARCH_TYPE_MULTI_HOME:
poiId = DataConstants.POI_ID_HOME;
break;
case SearchConstants.SEARCH_TYPE_MULTI_COMPANY:
poiId = DataConstants.POI_ID_COMPANY;
break;
}
if ( TextUtils.isEmpty( poiId ) ) {
emitter.onError( new IllegalArgumentException( "设置类型错误,请重试" ) );
return;
}
if ( poi == null ) {
emitter.onError( new IllegalArgumentException( "位置类型转换错误,请重试" ) );
return;
}
poi.setpId( poiId );
poi.setType( mView.getSearchType() );
//ignore insert result
final List<Long> output = AppDataBase.getDatabase( getContext() ).poiDao().insert( poi );
notifyAIAssistCommonAddressChanged();
emitter.onSuccess( output );
}
private void notifyAIAssistCommonAddressChanged() {
//if ( view.getSearchType() == SearchConstants.SEARCH_TYPE_MULTI_HOME ) {
// AddressHelper.notifyHomeAddressChanged( getContext() );
//} else if ( view.getSearchType() == SearchConstants.SEARCH_TYPE_MULTI_COMPANY ) {
// AddressHelper.notifyCompanyAddressChanged( getContext() );
//
//}
}
private void startSearchPoiByPoint( CameraPosition position ) {
if ( position == null ) {
return;
}
RegeocodeQuery
query = new RegeocodeQuery( new LatLonPoint( position.target.latitude, position.target.longitude ), 200, GeocodeSearch.AMAP );
if ( mGeocodeSearch == null ) {
mGeocodeSearch = new GeocodeSearch( getContext() );
mGeocodeSearch.setOnGeocodeSearchListener( this );
}
mGeocodeSearch.getFromLocationAsyn( query );
}
@Override
public void onRegeocodeSearched( RegeocodeResult regeocodeResult, int resultID ) {
if ( resultID == 1000 ) { // success
mView.renderChoicePointResult( regeocodeResult.getRegeocodeAddress() );
} else {
mView.renderChoicePointResult( null );
}
}
@Override
public void onGeocodeSearched( GeocodeResult geocodeResult, int resultID ) {
}
@Override
public void onDestroy( @NonNull LifecycleOwner owner ) {
super.onDestroy( owner );
if ( mView.getSearchBox() != null ) {
mView.getSearchBox().removeTextChangedListener( watcherAdapter );
}
if ( mCompositeDisposable != null && !mCompositeDisposable.isDisposed() ) {
mCompositeDisposable.dispose();
mCompositeDisposable = null;
}
//CameraChangedLiveData.getInstance().removeAllObserver();
mSearchEngine = null;
mGeocodeSearch = null;
mLastCameraPosition = null;
}
}

View File

@@ -0,0 +1,39 @@
package com.mogo.module.navi.ui.search;
/**
* @author congtaowang
* @since 2019-12-08
* <p>
* 搜索工具类
*/
public class SearchUtils {
/**
* @param searchType
* @return
*/
public static int checkAndResetSearchType( int searchType ) {
switch ( searchType ) {
case SearchConstants.SEARCH_TYPE_COMMON:
case SearchConstants.SEARCH_TYPE_MULTI_HOME:
case SearchConstants.SEARCH_TYPE_MULTI_COMPANY:
break;
default:
searchType = SearchConstants.SEARCH_TYPE_COMMON;
break;
}
return searchType;
}
public static String getSearchTypeActionName( int searchType ) {
switch ( searchType ) {
case SearchConstants.SEARCH_TYPE_COMMON:
return null;
case SearchConstants.SEARCH_TYPE_MULTI_HOME:
return "设为家";
case SearchConstants.SEARCH_TYPE_MULTI_COMPANY:
return "设为公司";
}
return null;
}
}

View File

@@ -0,0 +1,46 @@
package com.mogo.module.navi.ui.search;
import android.widget.EditText;
import com.amap.api.services.geocoder.RegeocodeAddress;
import com.amap.api.services.help.Tip;
import com.mogo.commons.mvp.IView;
import java.util.List;
/**
* @author congtaowang
* @since 2019-10-02
* <p>
* 描述
*/
public interface SearchView extends IView {
EditText getSearchBox();
/**
* @param datums
* @param showDelete 是否显示清空历史记录项
*/
void renderSearchPoiResult(List<Tip> datums, boolean showDelete);
int getSearchType();
/**
* 当前是哪一个操作
*
* @return
*/
int getUiMode();
/**
* 显示逆地理位置编码结果
*
* @param address
*/
void renderChoicePointResult(RegeocodeAddress address);
/**
* 选点完毕后marker动画
*/
void startJumpAnimation();
}

View File

@@ -0,0 +1,83 @@
package com.mogo.module.navi.wrapper;
import android.os.Parcel;
import android.os.Parcelable;
import com.amap.api.navi.model.AMapCalcRouteResult;
/**
* @author congtaowang
* @since 2019-09-27
* <p>
* 描述
*/
public class AMapCalcRouteResultWrapper implements Parcelable {
private final int errorCode;
private final int[] routeId;
private final int calcRouteType;
private final String errorDetail;
public AMapCalcRouteResultWrapper( AMapCalcRouteResult result ) {
errorCode = result.getErrorCode();
routeId = result.getRouteid();
calcRouteType = result.getCalcRouteType();
errorDetail = result.getErrorDetail();
}
public AMapCalcRouteResult parse() {
final AMapCalcRouteResult inst = new AMapCalcRouteResult();
inst.setErrorCode( getErrorCode() );
inst.setRouteid( getRouteId() );
inst.setCalcRouteType( getCalcRouteType() );
inst.setErrorDetail( getErrorDetail() );
return inst;
}
public int getErrorCode() {
return errorCode;
}
public int[] getRouteId() {
return routeId;
}
public int getCalcRouteType() {
return calcRouteType;
}
public String getErrorDetail() {
return errorDetail;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel( Parcel dest, int flags ) {
dest.writeInt( this.errorCode );
dest.writeIntArray( this.routeId );
dest.writeInt( this.calcRouteType );
dest.writeString( this.errorDetail );
}
protected AMapCalcRouteResultWrapper( Parcel in ) {
this.errorCode = in.readInt();
this.routeId = in.createIntArray();
this.calcRouteType = in.readInt();
this.errorDetail = in.readString();
}
public static final Creator< AMapCalcRouteResultWrapper > CREATOR = new Creator< AMapCalcRouteResultWrapper >() {
@Override
public AMapCalcRouteResultWrapper createFromParcel( Parcel source ) {
return new AMapCalcRouteResultWrapper( source );
}
@Override
public AMapCalcRouteResultWrapper[] newArray( int size ) {
return new AMapCalcRouteResultWrapper[size];
}
};
}

View File

@@ -0,0 +1,99 @@
package com.mogo.module.navi.wrapper;
import com.amap.api.navi.model.AMapNaviCameraInfo;
/**
* @author congtaowang
* @since 2019-10-10
* <p>
* 描述
*/
public class AMapNaviCameraInfoWrapper {
private int cameraDistance;
private double x;
private double y;
/**
* {@link AMapNaviCameraInfo#getCameraType()}
* {@link com.amap.api.navi.enums.CameraType#SPEED} 测速摄像
* {@link com.amap.api.navi.enums.CameraType#SURVEILLANCE}监控摄像
* {@link com.amap.api.navi.enums.CameraType#TRAFFICLIGHT} 闯红灯拍照
* {@link com.amap.api.navi.enums.CameraType#BREAKRULE} 违章拍照
* {@link com.amap.api.navi.enums.CameraType#BUSWAY} 公交专用道摄像头
* {@link com.amap.api.navi.enums.CameraType#EMERGENCY}应急车道拍照
* {@link com.amap.api.navi.enums.CameraType#BICYCLE}非机动车道(暂未使用)
* {@link com.amap.api.navi.enums.CameraType#INTERVALVELOCITYSTART}区间测速起始
* {@link com.amap.api.navi.enums.CameraType#INTERVALVELOCITYEND}区间测速解除
*/
private int cameraType;
private int cameraSpeed;
private int averageSpeed;
private int reasonableSpeedInRemainDist;
private int distance;
private int[] speed;
public AMapNaviCameraInfoWrapper( AMapNaviCameraInfo info ) {
if ( info != null ) {
cameraDistance = info.getCameraDistance();
x = info.getX();
y = info.getY();
cameraType = info.getCameraType();
cameraSpeed = info.getCameraSpeed();
averageSpeed = info.getAverageSpeed();
reasonableSpeedInRemainDist = info.getReasonableSpeedInRemainDist();
distance = info.getDistance();
speed = info.getSpeed();
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append( "cameraDistance" ).append( "=" ).append( cameraDistance ).append( "\n" );
builder.append( "cameraType" ).append( "=" ).append( cameraType ).append( "\n" );
builder.append( "cameraSpeed" ).append( "=" ).append( cameraSpeed ).append( "\n" );
builder.append( "averageSpeed" ).append( "=" ).append( averageSpeed ).append( "\n" );
builder.append( "reasonableSpeedInRemainDist" ).append( "=" ).append( reasonableSpeedInRemainDist ).append( "\n" );
builder.append( "distance" ).append( "=" ).append( distance ).append( "\n" );
if ( speed != null ) {
builder.append( "speed" ).append( "=" ).append( speed ).append( "\n" );
}
return builder.toString();
}
public int getCameraDistance() {
return cameraDistance;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public int getCameraType() {
return cameraType;
}
public int getCameraSpeed() {
return cameraSpeed;
}
public int getAverageSpeed() {
return averageSpeed;
}
public int getReasonableSpeedInRemainDist() {
return reasonableSpeedInRemainDist;
}
public int getDistance() {
return distance;
}
public int[] getSpeed() {
return speed;
}
}

View File

@@ -0,0 +1,148 @@
package com.mogo.module.navi.wrapper;
import android.os.Parcel;
import android.os.Parcelable;
import com.amap.api.navi.model.AMapNaviLocation;
import com.amap.api.navi.model.NaviLatLng;
/**
* @author congtaowang
* @since 2019-09-26
* <p>
* 描述
*/
public class AMapNaviLocationWrapper implements Parcelable {
private final float accuracy;
private final double altitude;
private final float bearing;
private final float speed;
private final long time;
private final int matchStatus;
private final NaviLatLng coord;
private final int curStepIndex;
private final int curLinkIndex;
private final int curPointIndex;
private final int type;
public AMapNaviLocationWrapper( AMapNaviLocation aMapNaviLocation ) {
this.accuracy = aMapNaviLocation.getAccuracy();
this.altitude = aMapNaviLocation.getAltitude();
this.bearing = aMapNaviLocation.getBearing();
this.speed = aMapNaviLocation.getSpeed();
this.time = aMapNaviLocation.getTime();
this.matchStatus = aMapNaviLocation.getMatchStatus();
this.coord = aMapNaviLocation.getCoord();
this.curStepIndex = aMapNaviLocation.getCurStepIndex();
this.curLinkIndex = aMapNaviLocation.getCurLinkIndex();
this.curPointIndex = aMapNaviLocation.getCurPointIndex();
this.type = aMapNaviLocation.getType();
}
public AMapNaviLocation parse() {
final AMapNaviLocation inst = new AMapNaviLocation();
inst.setAccuracy( getAccuracy() );
inst.setAltitude( getAltitude() );
inst.setBearing( getBearing() );
inst.setSpeed( getSpeed() );
inst.setTime( getTime() );
inst.setMatchStatus( getMatchStatus() );
inst.setCoord( getCoord() );
inst.setCurStepIndex( getCurStepIndex() );
inst.setCurLinkIndex( getCurLinkIndex() );
inst.setCurPointIndex( getCurPointIndex() );
inst.setType( getType() );
return inst;
}
public float getAccuracy() {
return accuracy;
}
public double getAltitude() {
return altitude;
}
public float getBearing() {
return bearing;
}
public float getSpeed() {
return speed;
}
public long getTime() {
return time;
}
public int getMatchStatus() {
return matchStatus;
}
public NaviLatLng getCoord() {
return coord;
}
public int getCurStepIndex() {
return curStepIndex;
}
public int getCurLinkIndex() {
return curLinkIndex;
}
public int getCurPointIndex() {
return curPointIndex;
}
public int getType() {
return type;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel( Parcel dest, int flags ) {
dest.writeFloat( this.accuracy );
dest.writeDouble( this.altitude );
dest.writeFloat( this.bearing );
dest.writeFloat( this.speed );
dest.writeLong( this.time );
dest.writeInt( this.matchStatus );
dest.writeParcelable( this.coord, flags );
dest.writeInt( this.curStepIndex );
dest.writeInt( this.curLinkIndex );
dest.writeInt( this.curPointIndex );
dest.writeInt( this.type );
}
protected AMapNaviLocationWrapper( Parcel in ) {
this.accuracy = in.readFloat();
this.altitude = in.readDouble();
this.bearing = in.readFloat();
this.speed = in.readFloat();
this.time = in.readLong();
this.matchStatus = in.readInt();
this.coord = in.readParcelable( NaviLatLng.class.getClassLoader() );
this.curStepIndex = in.readInt();
this.curLinkIndex = in.readInt();
this.curPointIndex = in.readInt();
this.type = in.readInt();
}
public static final Creator< AMapNaviLocationWrapper >
CREATOR = new Parcelable.Creator< AMapNaviLocationWrapper >() {
@Override
public AMapNaviLocationWrapper createFromParcel( Parcel source ) {
return new AMapNaviLocationWrapper( source );
}
@Override
public AMapNaviLocationWrapper[] newArray( int size ) {
return new AMapNaviLocationWrapper[size];
}
};
}

View File

@@ -0,0 +1,104 @@
package com.mogo.module.navi.wrapper;
import android.location.Location;
import android.os.Parcel;
import android.os.Parcelable;
import com.amap.api.maps.model.LatLng;
import com.amap.api.navi.model.AMapNaviLocation;
import com.amap.api.navi.model.NaviLatLng;
/**
* @author congtaowang
* @since 2019-09-26
* <p>
* 经纬度
*/
public class LatLngWrapper implements Parcelable {
private final double lat;
private final double lng;
public LatLngWrapper( double lat, double lng ) {
this.lat = lat;
this.lng = lng;
}
public double getLat() {
return lat;
}
public double getLng() {
return lng;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel( Parcel dest, int flags ) {
dest.writeDouble( this.lat );
dest.writeDouble( this.lng );
}
protected LatLngWrapper( Parcel in ) {
this.lat = in.readDouble();
this.lng = in.readDouble();
}
public static final Creator< LatLngWrapper > CREATOR = new Creator< LatLngWrapper >() {
@Override
public LatLngWrapper createFromParcel( Parcel source ) {
return new LatLngWrapper( source );
}
@Override
public LatLngWrapper[] newArray( int size ) {
return new LatLngWrapper[size];
}
};
public static LatLngWrapper from( LatLng latlng ) {
return new LatLngWrapper( latlng.latitude, latlng.longitude );
}
public static LatLngWrapper from( NaviLatLng latlng ) {
return new LatLngWrapper( latlng.getLatitude(), latlng.getLongitude() );
}
public static LatLngWrapper from( AMapNaviLocation latlng ) {
return from( latlng.getCoord() );
}
public LatLng parseLatLngInst() {
return new LatLng( getLat(), getLng() );
}
public static LatLng parse( NaviLatLng latLng ) {
if ( latLng == null ) {
return null;
}
return new LatLng( latLng.getLatitude(), latLng.getLongitude() );
}
public static LatLng parse( Location location ) {
if ( location == null ) {
return null;
}
return new LatLng( location.getLatitude(), location.getLongitude() );
}
public static LatLng parse( double lat, double lng ) {
if ( isRightLatLng( lat, lng ) ) {
return new LatLng( lat, lng );
}
return null;
}
public static boolean isRightLatLng( double lat, double lng ) {
return lat > 0 && lat < 90 && lng > 0 && lng < 180;
}
}

View File

@@ -0,0 +1,116 @@
package com.mogo.module.navi.wrapper;
import android.os.Parcel;
import android.os.Parcelable;
import com.amap.api.navi.model.NaviInfo;
/**
* @author congtaowang
* @since 2019-09-29
* <p>
* 导航信息对象
*/
public class NaviInfoWrapper implements Parcelable {
private static final NaviInfoWrapper INST = new NaviInfoWrapper();
private int nextIconType;
private int nextDistance;
private String nextRoad;
private int surplusDistance;
private int surplusTime;
private int currentSpeed;
private NaviInfoWrapper() {
}
public static NaviInfoWrapper getInst() {
return INST;
}
public synchronized NaviInfoWrapper fillWith( NaviInfo naviInfo ) {
INST.nextIconType = naviInfo.getIconType();
INST.nextDistance = naviInfo.getCurStepRetainDistance();
INST.nextRoad = naviInfo.getNextRoadName();
INST.surplusDistance = naviInfo.getPathRetainDistance();
INST.surplusTime = naviInfo.getPathRetainTime();
INST.currentSpeed = naviInfo.getCurrentSpeed();
return INST;
}
public NaviInfoWrapper( NaviInfo naviInfo ) {
this.nextIconType = naviInfo.getIconType();
this.nextDistance = naviInfo.getCurStepRetainDistance();
this.nextRoad = naviInfo.getNextRoadName();
this.surplusDistance = naviInfo.getPathRetainDistance();
this.surplusTime = naviInfo.getPathRetainTime();
this.currentSpeed = naviInfo.getCurrentSpeed();
}
public synchronized int getNextIconType() {
return nextIconType;
}
public synchronized int getNextDistance() {
return nextDistance;
}
public synchronized String getNextRoad() {
return nextRoad;
}
public synchronized int getSurplusDistance() {
return surplusDistance;
}
public synchronized int getSurplusTime() {
return surplusTime;
}
public synchronized int getCurrentSpeed() {
return currentSpeed;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel( Parcel dest, int flags ) {
dest.writeInt( getNextIconType() );
dest.writeInt( getNextDistance() );
dest.writeString( getNextRoad() );
dest.writeInt( getSurplusDistance() );
dest.writeInt( getSurplusTime() );
dest.writeInt( getCurrentSpeed() );
}
protected NaviInfoWrapper( Parcel in ) {
this.nextIconType = in.readInt();
this.nextDistance = in.readInt();
this.nextRoad = in.readString();
this.surplusDistance = in.readInt();
this.surplusTime = in.readInt();
this.currentSpeed = in.readInt();
}
public static final Creator< NaviInfoWrapper > CREATOR = new Parcelable.Creator< NaviInfoWrapper >() {
@Override
public NaviInfoWrapper createFromParcel( Parcel source ) {
return new NaviInfoWrapper( source );
}
@Override
public NaviInfoWrapper[] newArray( int size ) {
return new NaviInfoWrapper[size];
}
};
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
return builder.toString();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
style="@style/amap_fragment_container_padding_style"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.search.SearchFragment">
<RelativeLayout
android:id="@+id/amap_search_search_box_width_container"
android:layout_width="692dp"
android:layout_height="81dp"
android:background="@drawable/amap_white_shadow_bkg">
<ImageView
android:id="@+id/amap_search_close"
android:layout_width="@dimen/amap_search_back_size"
android:layout_height="@dimen/amap_search_back_size"
android:layout_alignTop="@+id/amap_search_search_box"
android:layout_alignBottom="@+id/amap_search_search_box"
android:layout_marginLeft="12dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_back_dark" />
<EditText
android:id="@+id/amap_search_search_box"
android:layout_width="match_parent"
android:layout_height="58dp"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@+id/amap_search_close"
android:background="@color/transparent"
android:drawableRight="@drawable/ic_search_unshadow"
android:drawablePadding="15dp"
android:ellipsize="end"
android:hint="@string/navi_search_hint"
android:maxLines="1"
android:paddingTop="@dimen/amap_search_search_box_paddingLTop"
android:paddingBottom="@dimen/amap_search_search_box_paddingBottom"
android:singleLine="true"
android:textColor="@color/black"
android:textColorHint="#848484"
android:textCursorDrawable="@drawable/amap_search_cursor_drawable"
android:textSize="@dimen/amap_search_search_box_textSize"
tools:text="@string/amap_long_text" />
<TextView
android:id="@+id/amap_search_action_setting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/amap_search_search_box"
android:layout_alignBottom="@+id/amap_search_search_box"
android:layout_alignParentRight="true"
android:layout_marginTop="8.5dp"
android:layout_marginRight="7.5dp"
android:layout_marginBottom="8.5dp"
android:background="@drawable/amap_search_action_button_bkg"
android:gravity="center"
android:paddingLeft="25dp"
android:paddingRight="25dp"
android:textColor="@color/white"
android:textSize="20dp"
android:visibility="gone"
tools:text="设为家"
tools:visibility="visible" />
</RelativeLayout>
<ImageView
android:id="@+id/amap_search_current_location_tag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/amap_search_search_box_width_container"
android:layout_alignLeft="@+id/amap_search_search_box_width_container"
android:layout_marginBottom="@dimen/amap_main_navi_current_location_marginBottom"
android:src="@drawable/ic_current_location"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_goneMarginBottom="@dimen/amap_main_navi_current_location_goneMarginBottom" />
<TextView
android:id="@+id/amap_search_poi_my_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/amap_search_current_location_tag"
android:layout_alignBottom="@+id/amap_search_current_location_tag"
android:background="@drawable/amap_white_shadow_bkg"
android:drawableLeft="@drawable/ic_search_poi_location"
android:drawablePadding="15.5dp"
android:gravity="center"
android:paddingLeft="23.5dp"
android:paddingRight="27.5dp"
android:text="我的位置"
android:textColor="#595959"
android:textSize="20dp" />
<TextView
android:id="@+id/amap_search_poi_choice_point"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/amap_search_current_location_tag"
android:layout_alignBottom="@+id/amap_search_current_location_tag"
android:layout_toRightOf="@+id/amap_search_poi_my_location"
android:background="@drawable/amap_white_shadow_bkg"
android:drawableLeft="@drawable/ic_search_poi_location"
android:drawablePadding="15.5dp"
android:gravity="center"
android:paddingLeft="23.5dp"
android:paddingRight="27.5dp"
android:text="地图选点"
android:textColor="#595959"
android:textSize="20dp" />
<ImageView
android:id="@+id/amap_search_current_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom"
android:layout_marginBottom="@dimen/amap_main_navi_current_location_marginBottom"
android:src="@drawable/ic_current_location" />
<android.support.v7.widget.RecyclerView
android:id="@+id/amap_search_poi_result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/amap_search_search_box_width_container"
android:layout_alignRight="@+id/amap_search_search_box_width_container"
android:layout_marginBottom="@dimen/amap_main_navi_current_location_marginBottom"
android:background="@drawable/amap_white_shadow_bkg"
android:overScrollMode="never"
android:visibility="invisible" />
</RelativeLayout>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="130dp">
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginLeft="130dp"
android:layout_marginRight="60dp"
android:background="#802D3256"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<ImageView
android:id="@+id/iv_position"
android:layout_width="30dp"
android:layout_height="42dp"
android:layout_marginLeft="130dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_position"
android:layout_width="0dp"
android:layout_height="42dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="28dp"
android:layout_marginRight="60dp"
android:textColor="@color/white"
android:textSize="30sp"
app:layout_constraintLeft_toRightOf="@id/iv_position"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_position_des"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="2dp"
android:layout_marginRight="60dp"
android:ellipsize="marquee"
android:singleLine="true"
android:textColor="@color/white_7f"
android:textSize="22sp"
app:layout_constraintLeft_toRightOf="@id/iv_position"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_position" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
<color name="bg_gray_common_page">#ff080625</color>
<color name="white">#FFFFFF</color>
<color name="white_7f">#7FFFFFFF</color>
<color name="arrow_color">#00BFFF</color>
<color name="white_30">#4DFFFFFF</color>
<color name="txt_gray_day">#4D080625</color>
<color name="bg_common">#080625</color>
</resources>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="tag_position" type="id"/>
</resources>

View File

@@ -0,0 +1,19 @@
<resources>
<style name="amap_fragment_container_padding_style">
<item name="android:paddingTop">25dp</item>
<item name="android:paddingLeft">48dp</item>
</style>
<style name="amap_fragment_container_margin_style">
<item name="android:layout_marginTop">25dp</item>
<item name="android:layout_marginLeft">48dp</item>
<item name="android:background">@drawable/amap_white_shadow_bkg</item>
</style>
<style name="amap_fragment_container_shadow_style">
<item name="android:paddingTop">25dp</item>
<item name="android:paddingLeft">48dp</item>
</style>
</resources>