Commit 6d4d2c2f by Luosp

增加聚合样式

parent 14af1553
......@@ -16,7 +16,9 @@
android:requestLegacyExternalStorage="true"
tools:ignore="GoogleAppIndexingWarning"
tools:targetApi="q">
<activity android:name=".MainActivity">
<activity android:name=".MainActivity"
android:windowSoftInputMode="stateAlwaysHidden|adjustPan"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
......
......@@ -3,6 +3,7 @@ package cn.com.founder.arcgisserver;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
......@@ -11,30 +12,44 @@ import java.util.ArrayList;
import java.util.List;
import cn.com.founder.arcgislib.ArcGisFounder;
import cn.com.founder.arcgislib.cluster.option.IArcGisClusterOption;
import cn.com.founder.arcgislib.compass.option.IArcGisCompassOption;
import cn.com.founder.arcgislib.location.option.IArcGisLocationOption;
import cn.com.founder.arcgislib.model.PointModel;
import cn.com.founder.arcgislib.model.SearchModel;
import cn.com.founder.arcgislib.search.listener.ISearchSelectedListener;
import cn.com.founder.arcgislib.search.option.IArcGisSearchOption;
import cn.com.founder.arcgislib.view.ArcGisBaseView;
import cn.com.founder.arcgislib.view.ArcGisClusterView;
import cn.com.founder.arcgislib.zoom.listener.IZoomClickListener;
import cn.com.founder.arcgislib.zoom.option.IArcGisZoomOption;
public class MainActivity extends AppCompatActivity {
// private LifecycleRegistry mLifecycleRegistry;
private ArcGisFounder arcGisFounder;
private Button naviBt;
/**
* @param savedInstanceState
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
naviBt = findViewById(R.id.bt_navi);
ArcGisBaseView arcGisBaseView = findViewById(R.id.main_arc_gis_base_view);
//集成Activity
// mLifecycleRegistry = new LifecycleRegistry(this);
// mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
ArcGisFounder arcGisFounder = ArcGisFounder.with(this)//context
initData(arcGisBaseView);
}
private void initData(ArcGisBaseView arcGisBaseView){
arcGisFounder = ArcGisFounder.with(this)//context
.setParentLayout(arcGisBaseView)//设置父布局
.setLifecycle(getLifecycle())//生命周期管理
.setBackgroundGridColor(Color.WHITE)//设置地图网格背景色
......@@ -44,9 +59,9 @@ public class MainActivity extends AppCompatActivity {
.setDefaultArcGisZoom()//设置默认缩放
.setDefaultArcGisCompass()//设置默认罗盘
.setOpenNavi()//开启导航
// .setOpenSearch()//开启搜索
.setOpenSearch()//开启搜索
// .setOpenHotPots()//开启热力图
// .setOpenCluster()//开启聚合
.setOpenCluster()//开启聚合
.createArcGisFounder();//创建ArcGisFounder地图实例
IArcGisZoomOption iArcGisZoomOption = arcGisFounder.arcGisZoomOption();
......@@ -65,19 +80,20 @@ public class MainActivity extends AppCompatActivity {
});
IArcGisLocationOption iArcGisLocationOption = arcGisFounder.arcGisLocationOption();
iArcGisLocationOption.setGeoDistance(0.5);
//自动定位;;;
// iArcGisLocationOption.startLocation(0);
//手动定位
iArcGisLocationOption.startLocation(113.75179,23.02067,0);
//开启TXT导入
iArcGisLocationOption.setShowTXTImportLayout(true);
List<PointModel> pointModels = new ArrayList<>();
pointModels.add(new PointModel(113.935576,22.995918));
pointModels.add(new PointModel(113.959722,23.000176));
pointModels.add(new PointModel(113.97582,22.949069));
pointModels.add(new PointModel(113.952823,22.916051));
pointModels.add(new PointModel(114.019513,22.951198));
iArcGisLocationOption.setImportPointData(pointModels);
// iArcGisLocationOption.setShowTXTImportLayout(true);
// List<PointModel> pointModels = new ArrayList<>();
// pointModels.add(new PointModel(113.935576,22.995918));
// pointModels.add(new PointModel(113.959722,23.000176));
// pointModels.add(new PointModel(113.97582,22.949069));
// pointModels.add(new PointModel(113.952823,22.916051));
// pointModels.add(new PointModel(114.019513,22.951198));
// iArcGisLocationOption.setImportPointData(pointModels);
//移动地图获取中心点
// iArcGisLocationOption.setFollowMapViewPoint(true);
//隐藏poi信息
......@@ -100,8 +116,43 @@ public class MainActivity extends AppCompatActivity {
IArcGisCompassOption iArcGisCompassOption = arcGisFounder.arcGisCompassOption();
iArcGisCompassOption.setIRotationAngleListener(() -> Toast.makeText(MainActivity.this, "转动结束。。。", Toast.LENGTH_LONG).show());
// IArcGisClusterOption iArcGisClusterOption = arcGisFounder.arcGisClusterOption();
// iArcGisClusterOption.setCluseterData(null);
}
//放在点击事件中调用或者当页面完全加载完成后调用
naviBt.setOnClickListener(view -> {
// IArcGisNaviOption iArcGisNaviOption = arcGisFounder.arcGisNaviOption();
// PointModel startPoint = new PointModel(113.6242709,22.8810121,"新丽佳百货");
// PointModel endPoint = new PointModel(113.6351135,22.8874085,"大自然花场");
//
// iArcGisNaviOption.setCustomPointNavi(startPoint,endPoint);
//必须开启搜索功能
IArcGisSearchOption iArcGisSearchOption = arcGisFounder.arcGisSearchOption();
iArcGisSearchOption.setSearchData(0, "公安局");
iArcGisSearchOption.setSearchSelectedListener(new ISearchSelectedListener() {
@Override
public void selectedResult(SearchModel searchModel) {
}
});
}
\ No newline at end of file
});
IArcGisClusterOption iArcGisClusterOption = arcGisFounder.arcGisClusterOption();
ArcGisClusterView.ClusterStyleBuilder clusterStyleBuilder = iArcGisClusterOption.getClusterStyleBuilder();
clusterStyleBuilder.setmClusterCircleBg(R.color.blue);
List<PointModel> pointList = new ArrayList<>();
pointList.add(new PointModel(113.935576,22.995918));
pointList.add(new PointModel(113.959722,23.000176));
pointList.add(new PointModel(113.97582,22.949069));
pointList.add(new PointModel(113.952823,22.916051));
pointList.add(new PointModel(114.019513,22.951198));
iArcGisClusterOption.setCluseterData(pointList);
iArcGisClusterOption.setIClusterPointInfoListener(locationModel -> Toast.makeText(MainActivity.this, "X:" + locationModel.getXPoint()
+ "\nY:" + locationModel.getYPoint()
+ "\n地址:" + locationModel.getAddress()
+ "\nPoi:" + locationModel.getPoi()
+ "\n补充信息:" + locationModel.getExtraInfo()
, Toast.LENGTH_LONG).show());
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
......@@ -9,5 +9,10 @@
android:id="@+id/main_arc_gis_base_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Button
android:id="@+id/bt_navi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="导航"/>
</LinearLayout>
\ No newline at end of file
</FrameLayout>
\ No newline at end of file
......@@ -59,10 +59,9 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
//arcgis地图
implementation 'com.esri.arcgisruntime:arcgis-android:100.6.0'
api 'com.esri.arcgisruntime:arcgis-android:100.6.0'
//权限
implementation 'com.yanzhenjie:permission:2.0.3'
//导航
implementation 'com.jakewharton.timber:timber:4.5.1'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.mapzen.android:lost:2.1.2'
......
......@@ -175,6 +175,10 @@
public *;
}
-keepclassmembers class cn.com.founder.arcgislib.view.ArcGisClusterView$ClusterStyleBuilder{
public *;
}
-keep class cn.com.founder.arcgislib.location.listener.**{ *; }
-keep class cn.com.founder.arcgislib.location.option.**{ *; }
-keep class cn.com.founder.arcgislib.compass.listener.**{ *; }
......@@ -184,20 +188,15 @@
-keep class cn.com.founder.arcgislib.search.listener.**{ *; }
-keep class cn.com.founder.arcgislib.search.option.**{ *; }
-keep class cn.com.founder.arcgislib.navi.option.**{ *; }
-keep class cn.com.founder.arcgislib.cluster.listener.**{ *; }
-keep class cn.com.founder.arcgislib.cluster.option.**{ *; }
-keep class cn.com.founder.arcgislib.hotpots.option.**{ *; }
-keep class cn.com.founder.arcgislib.model.**{ *; }
-keep class cn.com.founder.arcgislib.view.**{ *; }
-keep class cn.com.founder.arcgislib.widget.**{ *; }
-keep class cn.com.founder.arcgislib.widget.cluster.**{ *; }
-keep class cn.com.founder.arcgislib.widget.navi.**{ *; }
-keep class cn.com.founder.arcgislib.widget.popup.**{ *; }
-keep class cn.com.founder.arcgislib.widget.scrolllayout.**{ *; }
-keep class cn.com.founder.arcgislib.widget.scrolllayout.content.**{ *; }
-keep class cn.com.founder.arcgislib.widget.scrolllayout{ *; }
-keepclassmembers class cn.com.founder.arcgislib.widget.scrolllayout$Status{
public *;
}
-keep class com.minedata.minenavi.**{ *; }
-dontwarn com.minedata.minenavi.**
......
......@@ -454,7 +454,7 @@ public class ArcGisFounder implements IOption {
* @return {@link ArcGisClusterView}
*/
ArcGisClusterView getArcGisClusterView() {
return new ArcGisClusterView(mArcGisFounderBuilder.mSource.getContext(), mArcGisFounderBuilder.mArcGisMapView);
return new ArcGisClusterView(mArcGisFounderBuilder.mSource.getContext(), mArcGisFounderBuilder.mArcGisMapView, mArcGisFounderBuilder.mArcGisLocationView);
}
}
......
package cn.com.founder.arcgislib.cluster;
import com.esri.arcgisruntime.geometry.Point;
import java.util.List;
import cn.com.founder.arcgislib.cluster.listener.IClusterPointInfoListener;
import cn.com.founder.arcgislib.cluster.option.IArcGisClusterOption;
import cn.com.founder.arcgislib.common.Variable;
import cn.com.founder.arcgislib.model.PointModel;
import cn.com.founder.arcgislib.view.ArcGisClusterView;
/**
......@@ -24,28 +24,70 @@ public class ArcGisCluster implements IArcGisClusterOption {
public ArcGisCluster(ArcGisClusterView arcGisClusterView) {
this.mArcGisClusterView = arcGisClusterView;
}
/**
* @param isShow boolean-是否显示聚合布局
* 默认显示
*/
@Override
public IArcGisClusterOption setShowClusterLayout(boolean isShow) {
mArcGisClusterView.setShowClusterLayout(isShow);
return this;
}
/**
* @param location {@link Variable.ViewLocation } ClusterView显示位置
*/
@Override
public IArcGisClusterOption setClusterViewLocation(Variable.ViewLocation location) {
mArcGisClusterView.setClusterViewLocation(location);
return this;
}
/**
* @param clusterImage int(资源ID)-聚合图片
*/
@Override
public IArcGisClusterOption setClusterImage(int clusterImage) {
mArcGisClusterView.setClusterImage(clusterImage);
return this;
}
/**
* @param pointList 聚合点集合
*/
@Override
public IArcGisClusterOption setCluseterData(List<Point> pointList) {
public IArcGisClusterOption setCluseterData(List<PointModel> pointList) {
mArcGisClusterView.setClusterData(pointList);
return this;
}
@Override
public IArcGisClusterOption setGeoDistance(double distance) {
mArcGisClusterView.setGeoDistance(distance);
return this;
}
@Override
public IArcGisClusterOption setIClusterPointInfoListener(IClusterPointInfoListener clusterPointInfoListener) {
mArcGisClusterView.setIClusterPointInfoListener(clusterPointInfoListener);
return this;
}
/**
* @return 得到聚合样式
*/
@Override
public ArcGisClusterView.ClusterStyleBuilder getClusterStyleBuilder() {
return mArcGisClusterView.getClusterStyleBuilder();
}
@Override
public ArcGisClusterView.CalloutStyleBuilder getCalloutStyleBuilder() {
return mArcGisClusterView.getCalloutStyleBuilder();
}
@Override
public ArcGisClusterView.CalloutContentBuilder getCalloutContentBuilder() {
return mArcGisClusterView.getCalloutContentBuilder();
}
}
package cn.com.founder.arcgislib.cluster.option;
import com.esri.arcgisruntime.geometry.Point;
import java.util.List;
import cn.com.founder.arcgislib.cluster.listener.IClusterPointInfoListener;
import cn.com.founder.arcgislib.common.Variable;
import cn.com.founder.arcgislib.model.PointModel;
import cn.com.founder.arcgislib.view.ArcGisClusterView;
/**
* Copyright: 方正国际软件有限公司
......@@ -33,5 +34,32 @@ public interface IArcGisClusterOption {
/**
* @param pointList 聚合点集合
*/
IArcGisClusterOption setCluseterData(List<Point> pointList);
IArcGisClusterOption setCluseterData(List<PointModel> pointList);
/**
* @param distance 默认逆地理编码距离是0.1,单位是km;
* 需要在最上层调用
*
*/
IArcGisClusterOption setGeoDistance(double distance);
/**
* @param clusterPointInfoListener 设置聚合点信息回调
*/
IArcGisClusterOption setIClusterPointInfoListener(IClusterPointInfoListener clusterPointInfoListener);
/**
* @return 得到聚合样式
*/
ArcGisClusterView.ClusterStyleBuilder getClusterStyleBuilder();
/**
* callout样式
*/
ArcGisClusterView.CalloutStyleBuilder getCalloutStyleBuilder();
/**
* callout内容样式
*/
ArcGisClusterView.CalloutContentBuilder getCalloutContentBuilder();
}
......@@ -63,6 +63,7 @@ public class Variable {
public static enum SearchType{
NONE,
SEARCH,
SEARCH_TYPE_RESULT,
START_ADDRESS_SEARCH,
END_ADDRESS_SEARCH,
}
......
......@@ -9,37 +9,62 @@ package cn.com.founder.arcgislib.constants;
*/
public class Constants {
/*****************************************互联网***********************************************/
//互联网-地图
private static String baseUrl = "http://47.92.225.109:6080/arcgis/rest/services/founder/dg20191120/MapServer";
//互联网-Geo
private static String baseGeoUrl = "http://47.92.226.24:8051/selectVdzjx";
//互联网-搜索
private static String searchUrl = "http://47.92.226.24:8051/selectPoiDataList";
//互联网-导航
private static String naviUrl = "minedata.cn/lbsservice/navi/";
/**********************************************************************************************/
/*****************************************互联网*********************************************
//互联网-地图
private static String baseUrl = "http://47.92.225.109:6080/arcgis/rest/services/founder/dg20191120/MapServer";
//互联网-Geo
private static String baseGeoUrl = "http://68.174.25.107:8090/esBzdzTestQuery";
//互联网-搜索
private static String searchUrl = "http://47.92.226.24:8051/selectPoiDataList";
//互联网-导航
private static String naviUrl = "minedata.cn/lbsservice/navi/";
//二标四实-单位
private static String dwUrl = "http://68.174.69.46:8051/selectVdwjx";
//二标四实-房屋
private static String fwUrl = "http://68.174.69.46:8051/selectVfwjx";
//二标四实-地址
private static String dzUrl = "http://68.174.69.46:8051/selectVdzjx";
/**********************************************************************************************
/*****************************************用户网***********************************************
//用户网-地图
private static String baseUrl = "http://20.97.50.41:6080/arcgis/rest/services/founder/dg20191120/MapServer";
//互联网-Geo
private static String baseGeoUrl = "http://20.97.50.41:8050/selectVdzjx";
//用户网-搜索
private static String searchUrl = "http://20.97.50.41:8051/selectPoiDataList";
/**********************************************************************************************/
//如果使用公安局的映射,导航907和958行代码需要修改坐标系
//用户网-地图
private static String baseUrl = "http://192.168.2.56:19076/arcgis/rest/services/founder/dg20191120/MapServer";
//用户网-导航
private static String naviUrl = "http://192.168.2.56:19085/PPmap/LBSservice";
//公安网-Geo
private static String baseGeoUrl = "http://192.168.2.56:19087/esBzdzTestQuery";
//用户网-搜索
private static String searchUrl = "http://192.168.2.56:19084/selectPoiDataList";
//二标四实-单位
private static String dwUrl = "http://192.168.2.56:19084/selectVdwjx";
//二标四实-房屋
private static String fwUrl = "http://192.168.2.56:19084/selectVfwjx";
//二标四实-地址
private static String dzUrl = "http://192.168.2.56:19084/selectVdzjx";
/**********************************************************************************************/
/*****************************************公安网***********************************************
// /*****************************************公安网***********************************************
//公安网-地图
private static String baseUrl = "http://68.174.69.45:6080/arcgis/rest/services/founder/dg20191120/MapServer";
//公安网-Geo
private static String baseGeoUrl = "http://68.174.69.46:8051/selectVdzjx";
private static String baseGeoUrl = "http://68.174.25.107:8090/esBzdzTestQuery";
//公安网-搜索
private static String searchUrl = "http://68.174.69.46:8051/selectPoiDataList";
//公安网-导航
private static String naviUrl = "http://68.26.19.5/";
private static String naviUrl = "http://68.26.19.197:8380/PPmap/LBSservice";
//二标四实-单位
private static String dwUrl = "http://68.174.69.46:8051/selectVdwjx";
//二标四实-房屋
private static String fwUrl = "http://68.174.69.46:8051/selectVfwjx";
//二标四实-地址
private static String dzUrl = "http://68.174.69.46:8051/selectVdzjx";
/**********************************************************************************************/
// argis证书
......@@ -51,7 +76,6 @@ public class Constants {
//测试热力图
private static String hotPotsUrl = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/911CallsHotspot/GPServer/911%20Calls%20Hotspot";
//arcGis证书
public static final String BASE_MAP_RUNTIME = baseRunTime;
//服务器Url
......@@ -69,4 +93,11 @@ public class Constants {
//热力图
public static final String BASE_HOT_POTS_URL = hotPotsUrl;
//二标四实-房屋
public static final String BASE_FW_URL = fwUrl;
//二标四实-地址
public static final String BASE_DZ_URL = dzUrl;
//二标四实-单位
public static final String BASE_DW_URL = dwUrl;
}
......@@ -152,6 +152,16 @@ public class ArcGisLocation implements IArcGisLocationOption {
return this;
}
/**
* @param distance 默认逆地理编码距离是0.1,单位是km;
* 需要在最上层调用
*/
@Override
public IArcGisLocationOption setGeoDistance(double distance) {
mArcGisLocationView.setGeoDistance(distance);
return this;
}
@Override
public ArcGisLocationView.CalloutStyleBuilder getCalloutStyleBuilder() {
return mArcGisLocationView.getCalloutStyleBuilder();
......
......@@ -89,6 +89,13 @@ public interface IArcGisLocationOption {
* 默认不跟随
*/
IArcGisLocationOption setFollowMapViewPoint(boolean isFollow);
/**
* @param distance 默认逆地理编码距离是0.1,单位是km;
* 需要在最上层调用
*
*/
IArcGisLocationOption setGeoDistance(double distance);
/**
* callout样式
*/
......
......@@ -47,6 +47,13 @@ public class LocationModel implements Parcelable {
this.locationChangeType = locationChangeType;
}
public LocationModel(double xPoint, double yPoint, String address, String poi, String extraInfo) {
this.xPoint = xPoint;
this.yPoint = yPoint;
this.address = address;
this.poi = poi;
this.extraInfo = extraInfo;
}
private LocationModel(Parcel in){
xPoint = in.readDouble();
......
package cn.com.founder.arcgislib.navi;
import cn.com.founder.arcgislib.common.Variable;
import cn.com.founder.arcgislib.model.PointModel;
import cn.com.founder.arcgislib.navi.option.IArcGisNaviOption;
import cn.com.founder.arcgislib.view.ArcGisNaviView;
......@@ -38,4 +39,10 @@ public class ArcGisNavi implements IArcGisNaviOption {
mArcGisNaviView.setNaviImage(naviImage);
return this;
}
@Override
public IArcGisNaviOption setCustomPointNavi(PointModel startPoint, PointModel endPoint) {
mArcGisNaviView.setCustomPointNavi(startPoint,endPoint);
return this;
}
}
package cn.com.founder.arcgislib.navi.option;
import cn.com.founder.arcgislib.common.Variable;
import cn.com.founder.arcgislib.model.PointModel;
/**
* Copyright: 方正国际软件有限公司
......@@ -25,4 +26,11 @@ public interface IArcGisNaviOption {
* @param naviImage int(资源ID)-导航图片
*/
IArcGisNaviOption setNaviImage(int naviImage);
/**
* 自定义点导航
* @param startPoint 起点
* @param endPoint 终点
*/
IArcGisNaviOption setCustomPointNavi(PointModel startPoint, PointModel endPoint);
}
package cn.com.founder.arcgislib.search;
import cn.com.founder.arcgislib.search.listener.ISearchSelectedListener;
import cn.com.founder.arcgislib.search.option.IArcGisSearchOption;
import cn.com.founder.arcgislib.view.ArcGisSearchView;
......@@ -19,4 +20,20 @@ public class ArcGisSearch implements IArcGisSearchOption {
public ArcGisSearch(ArcGisSearchView arcGisSearchView) {
this.mArcGisSearchView = arcGisSearchView;
}
/**
* @param type 搜索类型:0:poi,1:实有单位,2:实有房屋,3:标准地址
* @param keyWord 关键字
*/
@Override
public IArcGisSearchOption setSearchData(int type, String keyWord) {
mArcGisSearchView.setSearchData(type,keyWord);
return this;
}
@Override
public IArcGisSearchOption setSearchSelectedListener(ISearchSelectedListener listener) {
mArcGisSearchView.setSearchSelectedListener(listener);
return this;
}
}
package cn.com.founder.arcgislib.search.option;
import cn.com.founder.arcgislib.search.listener.ISearchSelectedListener;
/**
* Copyright: 方正国际软件有限公司
* Author:luo_shaopeng
......@@ -8,4 +10,16 @@ package cn.com.founder.arcgislib.search.option;
* Description:搜索
*/
public interface IArcGisSearchOption {
/**
* @param type 搜索类型:0:poi,1:实有单位,2:实有房屋,3:标准地址
* @param keyWord 关键字
*/
IArcGisSearchOption setSearchData(int type , String keyWord);
/**
* @param listener 设置列表点击事件监听
*/
IArcGisSearchOption setSearchSelectedListener(ISearchSelectedListener listener);
}
package cn.com.founder.arcgislib.utils;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
......@@ -10,40 +16,152 @@ import android.widget.EditText;
* Author:luo_shaopeng
* Date:2020/2/11 20:27
* EMail:luo_shaopeng@founder.com.cn
* Description:toDo
* Description:键盘
*/
public class KeyboardUtil {
/**
* 显示软键盘的延迟时间
*/
public static final int SHOW_KEYBOARD_DELAY_TIME = 200;
public final static int KEYBOARD_VISIBLE_THRESHOLD_DP = 100;
public static void showKeyboard(final EditText editText, boolean delay) {
showKeyboard(editText, delay ? SHOW_KEYBOARD_DELAY_TIME : 0);
}
/**
* 针对给定的editText显示软键盘(editText会先获得焦点). 可以和{@link #hideKeyboard(View)}
* 搭配使用,进行键盘的显示隐藏控制。
*/
public static void showKeyboard(final EditText editText, int delay) {
if (null == editText)
return;
if (!editText.requestFocus()) {
return;
}
if (delay > 0) {
editText.postDelayed(new Runnable() {
@Override
public void run() {
InputMethodManager imm = (InputMethodManager) editText.getContext().getApplicationContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
}
}, delay);
} else {
InputMethodManager imm = (InputMethodManager) editText.getContext().getApplicationContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
}
}
/**
* 显示键盘
* 隐藏软键盘 可以和{@link #showKeyboard(EditText, boolean)}搭配使用,进行键盘的显示隐藏控制。
*
* @param view 当前页面上任意一个可用的view
*/
public static void showKeyboard(final View view) {
view.requestFocus();
InputMethodManager inputManager =
(InputMethodManager) view.getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
inputManager.showSoftInput(view, 0);
public static boolean hideKeyboard(final View view) {
if (null == view)
return false;
InputMethodManager inputManager = (InputMethodManager) view.getContext().getApplicationContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
// 即使当前焦点不在editText,也是可以隐藏的。
return inputManager.hideSoftInputFromWindow(view.getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
}
/**
* 打开软键盘
* Set keyboard visibility change event listener.
*
* @param mEditText 输入框
* @param mContext 上下文
* @param activity Activity
* @param listener KeyboardVisibilityEventListener
*/
public static void openKeybord(EditText mEditText, Context mContext) {
InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(mEditText, InputMethodManager.RESULT_SHOWN);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
@SuppressWarnings("deprecation")
public static void setVisibilityEventListener(final Activity activity,
final KeyboardVisibilityEventListener listener) {
if (activity == null) {
throw new NullPointerException("Parameter:activity must not be null");
}
if (listener == null) {
throw new NullPointerException("Parameter:listener must not be null");
}
final View activityRoot = ((ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT)).getChildAt(0);
final ViewTreeObserver.OnGlobalLayoutListener layoutListener =
new ViewTreeObserver.OnGlobalLayoutListener() {
private final Rect r = new Rect();
private final int visibleThreshold = Math.round(
DensityUtil.dip2px(activity, KEYBOARD_VISIBLE_THRESHOLD_DP));
private boolean wasOpened = false;
@Override
public void onGlobalLayout() {
activityRoot.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRoot.getRootView().getHeight() - r.height();
boolean isOpen = heightDiff > visibleThreshold;
if (isOpen == wasOpened) {
// keyboard state has not changed
return;
}
wasOpened = isOpen;
boolean removeListener = listener.onVisibilityChanged(isOpen, heightDiff);
if (removeListener) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
activityRoot.getViewTreeObserver()
.removeOnGlobalLayoutListener(this);
} else {
activityRoot.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
}
}
}
};
activityRoot.getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
}
/**
* 关闭隐藏键盘
* Determine if keyboard is visible
*
* @param activity Activity
* @return Whether keyboard is visible or not
*/
public static void hideKeyboard(final View view) {
InputMethodManager imm =
(InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
public static boolean isKeyboardVisible(Activity activity) {
Rect r = new Rect();
View activityRoot = ((ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT)).getChildAt(0);
int visibleThreshold =
Math.round(DensityUtil.dip2px(activity, KEYBOARD_VISIBLE_THRESHOLD_DP));
activityRoot.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRoot.getRootView().getHeight() - r.height();
return heightDiff > visibleThreshold;
}
public interface KeyboardVisibilityEventListener {
/**
* @return to remove global listener or not
*/
boolean onVisibilityChanged(boolean isOpen, int heightDiff);
}
}
......@@ -11,6 +11,9 @@ import android.widget.Toast;
import com.esri.arcgisruntime.geometry.Point;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
......@@ -255,4 +258,23 @@ public class ToolUtil {
return resultPoint;
}
/**
* @return 东莞最大最小经纬度
*/
public static String dongGuanSearchParams(String value){
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("jsjd", "114.26742553710938");
jsonObject.put("qsjd", "113.50799560546875");
jsonObject.put("jswd","23.152313232421875");
jsonObject.put("qswd", "22.646942138671875");
jsonObject.put("value", value);
jsonObject.put("isAll", "0");
return jsonObject.toString();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
package cn.com.founder.arcgislib.view;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.esri.arcgisruntime.concurrent.ListenableFuture;
import com.esri.arcgisruntime.data.ServiceFeatureTable;
import com.esri.arcgisruntime.geometry.GeometryEngine;
import com.esri.arcgisruntime.geometry.Point;
import com.esri.arcgisruntime.geometry.PointCollection;
import com.esri.arcgisruntime.geometry.SpatialReference;
import com.esri.arcgisruntime.layers.FeatureLayer;
import com.esri.arcgisruntime.mapping.view.Callout;
import com.esri.arcgisruntime.mapping.view.DrawStatus;
import com.esri.arcgisruntime.mapping.view.Graphic;
import com.esri.arcgisruntime.mapping.view.GraphicsOverlay;
import com.esri.arcgisruntime.mapping.view.IdentifyGraphicsOverlayResult;
import com.esri.arcgisruntime.mapping.view.MapView;
import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.minedata.minenavi.common.OkHttp3Utils;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import cn.com.founder.arcgislib.R;
import cn.com.founder.arcgislib.cluster.listener.IClusterPointInfoListener;
import cn.com.founder.arcgislib.common.Variable;
import cn.com.founder.arcgislib.constants.Constants;
import cn.com.founder.arcgislib.model.LocationModel;
import cn.com.founder.arcgislib.model.PointModel;
import cn.com.founder.arcgislib.utils.GsonUtil;
import cn.com.founder.arcgislib.utils.ToolUtil;
import cn.com.founder.arcgislib.widget.cluster.ClusterLayer;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
/**
* Copyright: 方正国际软件有限公司
......@@ -36,7 +71,7 @@ import cn.com.founder.arcgislib.widget.cluster.ClusterLayer;
* EMail:luo_shaopeng@founder.com.cn
* Description:点聚合
*/
public class ArcGisClusterView extends LinearLayout implements View.OnClickListener {
public class ArcGisClusterView extends LinearLayout implements View.OnClickListener, ArcGisMapView.MyTouchClusterListener {
protected static ArcGisClusterView instance;
/**
* {@link Context}
......@@ -55,6 +90,8 @@ public class ArcGisClusterView extends LinearLayout implements View.OnClickListe
* {@link ArcGisMapView}
*/
private ArcGisMapView mArcGisMapView;
private ArcGisLocationView mArcGisLocationView;
/**
* {@link MapView}
*/
......@@ -83,16 +120,59 @@ public class ArcGisClusterView extends LinearLayout implements View.OnClickListe
/**
* 实际数据源
*/
private List<Point> pointList = new ArrayList<>();
private List<PointModel> pointList = new ArrayList<>();
private boolean isFirstCreate = true;
/**
* {@link ClusterStyleBuilder}
*/
private ClusterStyleBuilder mClusterStyleBuilder;
/**
* 当前中心点图标,数据的综合体
*/
private Graphic mCenteredGraphic = null;
/**
* 加载框
*/
protected ProgressDialog myDialog;
/**
* 默认逆地理编码距离是0.1,单位是km;
*/
private double distance = 0.1;
private IClusterPointInfoListener mIClusterPointInfoListener;
/**
* {@link CalloutStyleBuilder}
*/
private CalloutStyleBuilder mCalloutStyleBuilder;
/**
* {@link CalloutContentBuilder}
*/
private CalloutContentBuilder mCalloutContentBuilder;
public ArcGisClusterView(Context context, ArcGisMapView arcGisMapView) {
public ArcGisClusterView(Context context, ArcGisMapView arcGisMapView, ArcGisLocationView arcGisLocationView) {
this(context);
this.mContext = context;
this.mArcGisMapView = arcGisMapView;
this.mMapView = mArcGisMapView.getMapView();
this.mArcGisLocationView = arcGisLocationView;
this.graphicsOverlay = arcGisMapView.getClusterGraphicsOverlay();
if(mArcGisLocationView != null){
mArcGisLocationView.isUseCluster = true;
}
arcGisMapView.setMyTouchClusterListener(this);
mCalloutStyleBuilder = new CalloutStyleBuilder(context);
mCalloutContentBuilder = new CalloutContentBuilder();
mPointCollection = new PointCollection(SpatialReference.create(4326));
graphicsOverlay = new GraphicsOverlay();
mMapView.getGraphicsOverlays().add(graphicsOverlay);
mClusterStyleBuilder = new ClusterStyleBuilder(mContext);
// addFeatureLayer();
}
......@@ -117,20 +197,11 @@ public class ArcGisClusterView extends LinearLayout implements View.OnClickListe
@Override
public void onClick(View view) {
if(isClean){
if (isClean) {
graphicsOverlay.setVisible(false);
clusterLayer.setGraphicVisible(false);
}else{
// initRamdData();
boolean isEmpty = pointList.size() == 0;
if(isEmpty){
Toast.makeText(mContext,"暂无数据源",Toast.LENGTH_LONG).show();
return;
}
} else {
graphicsOverlay.setVisible(true);
if(clusterLayer == null){
clusterLayer = new ClusterLayer(mMapView, graphicsOverlay, mContext);
}
clusterLayer.setGraphicVisible(true);
}
......@@ -151,21 +222,42 @@ public class ArcGisClusterView extends LinearLayout implements View.OnClickListe
}
/**
*设置数据源
* 设置数据源
*/
public void setClusterData(List<Point> points){
boolean isEmpty = points == null || points.isEmpty();
if(isEmpty){
Toast.makeText(mContext,"暂无数据源",Toast.LENGTH_LONG).show();
public void setClusterData(List<PointModel> pointModelList) {
boolean isEmpty = pointModelList == null || pointModelList.isEmpty();
if (isEmpty) {
Toast.makeText(mContext, "暂无数据源", Toast.LENGTH_LONG).show();
return;
}
pointList.clear();
pointList.addAll(points);
for (Point point: pointList) {
Point graPoint= (Point) GeometryEngine.project(point,mMapView.getSpatialReference());
Graphic gra1 = new Graphic(graPoint, simpleMarkerSymbol);
graphicsOverlay.getGraphics().add(gra1);
pointList = pointModelList;
for (PointModel pointModel : pointModelList) {
double x = pointModel.getxPoint();
double y = pointModel.getyPoint();
if(x < 0 || y < 0){
break;
}
Point point = new Point(x, y, SpatialReference.create(4326));
graphicsOverlay.getGraphics().add(new Graphic(point, simpleMarkerSymbol));
}
mMapView.addDrawStatusChangedListener(drawStatusChangedEvent -> {
if (drawStatusChangedEvent.getDrawStatus() == DrawStatus.COMPLETED && isFirstCreate) {
graphicsOverlay.setVisible(true);
if (clusterLayer == null) {
clusterLayer = new ClusterLayer(mMapView, graphicsOverlay, mContext,mClusterStyleBuilder);
}
clusterLayer.setGraphicVisible(true);
isClean = true;
isFirstCreate = false;
}
});
}
/**
......@@ -174,26 +266,25 @@ public class ArcGisClusterView extends LinearLayout implements View.OnClickListe
private void initRamdData() {
graphicsOverlay.getGraphics().clear();
mPointCollection.clear();
mPointCollection.add(new Point(113.935576,22.995918));
mPointCollection.add(new Point(113.959722,23.000176));
mPointCollection.add(new Point(113.97582,22.949069));
mPointCollection.add(new Point(113.952823,22.916051));
mPointCollection.add(new Point(114.019513,22.951198));
mPointCollection.add(new Point(113.876934,22.998047));
mPointCollection.add(new Point(113.909129,22.936289));
mPointCollection.add(new Point(113.847039,22.998047));
mPointCollection.add(new Point(114.114949,22.995918));
mPointCollection.add(new Point(114.047109,22.97356));
mPointCollection.add(new Point(114.066656,22.935224));
for (Point point: mPointCollection) {
Point graPoint= (Point) GeometryEngine.project(point,mMapView.getSpatialReference());
mPointCollection.add(new Point(113.935576, 22.995918));
mPointCollection.add(new Point(113.959722, 23.000176));
mPointCollection.add(new Point(113.97582, 22.949069));
mPointCollection.add(new Point(113.952823, 22.916051));
mPointCollection.add(new Point(114.019513, 22.951198));
mPointCollection.add(new Point(113.876934, 22.998047));
mPointCollection.add(new Point(113.909129, 22.936289));
mPointCollection.add(new Point(113.847039, 22.998047));
mPointCollection.add(new Point(114.114949, 22.995918));
mPointCollection.add(new Point(114.047109, 22.97356));
mPointCollection.add(new Point(114.066656, 22.935224));
for (Point point : mPointCollection) {
Point graPoint = (Point) GeometryEngine.project(point, mMapView.getSpatialReference());
Graphic gra1 = new Graphic(graPoint, simpleMarkerSymbol);
graphicsOverlay.getGraphics().add(gra1);
}
//随机点
// for (int i = 0; i < 1000; i++) {
// double lat = Math.random() + 23.02067;
......@@ -242,10 +333,1080 @@ public class ArcGisClusterView extends LinearLayout implements View.OnClickListe
}
}
@Override
public void onUp(Variable.TouchUp touchUp, MotionEvent motionEvent) {
}
@Override
public void onSingleTap(MotionEvent motionEvent) {
final android.graphics.Point screenPoint = new android.graphics.Point(
(int) motionEvent.getX(),
(int) motionEvent.getY());
//获取屏幕上的点,误差在10米以内
final ListenableFuture<IdentifyGraphicsOverlayResult> identifyGraphic = mMapView
.identifyGraphicsOverlayAsync(clusterLayer.getGraphicLayer(), screenPoint, 10, false);
identifyGraphic.addDoneListener(() -> {
try {
if (mCenteredGraphic != null) {
mCenteredGraphic.setZIndex(0);
mCenteredGraphic.setSelected(false);
}
// get the list of graphics returned by identify
final IdentifyGraphicsOverlayResult graphic = identifyGraphic.get();
// get size of list in results
final int identifyResultSize = graphic.getGraphics().size();
boolean isExist = false;
if (identifyResultSize > 0) {
final Graphic foundGraphic = graphic.getGraphics().get(0);
final List<Graphic> graphics = clusterLayer.getGraphicLayer().getGraphics();
for (final Graphic g : graphics) {
if (g.getGeometry().equals(foundGraphic.getGeometry())) {
mCenteredGraphic = g;
isExist = true;
break;
}
}
}
if (isExist) {
Point centerPoint = (Point) mCenteredGraphic.getGeometry();
mMapView.setViewpointCenterAsync(centerPoint);
Map<String, Object> attrResultMap = mCenteredGraphic.getAttributes();
int count = (Integer) attrResultMap.get("count");
if(count == 1){
mCenteredGraphic.setZIndex(3);
mCenteredGraphic.setSelected(true);
requestGeoCeoder(centerPoint,true,true);
}else{
double scale = mMapView.getMapScale();
double currScale = scale * (1.0 / 4);
mMapView.setViewpointScaleAsync(currScale);
}
}
} catch (InterruptedException | ExecutionException ie) {
ie.printStackTrace();
}
});
}
public static class ClusterStyleBuilder {
private Context mContext;
/**
* 默认展开得图标 单个点
*/
private int mDefaultExpandImage;
/**
* 聚合时圆的大小
*/
private int mClusterCircleSize;
/**
* 聚合时圆的背景
*/
private int mClusterCircleBg;
/**
* 圆中文字的大小
*/
private int mClusterTextSize;
/**
* 聚合时圆中文字得颜色
*/
private int mClusterTextColor;
public ClusterStyleBuilder(Context context){
this.mContext = context;
this.mDefaultExpandImage = R.drawable.icon_label_location_normal;
this.mClusterCircleSize = 28;
this.mClusterCircleBg = Color.BLACK;
this.mClusterTextColor = Color.WHITE;
this.mClusterTextSize = 18;
}
public int getmDefaultExpandImage() {
return mDefaultExpandImage;
}
/**
* @param expandImage int(资源ID)-最终展开后单点图片,R.drawable.xxx
*/
public void setmDefaultExpandImage(int expandImage) {
if(expandImage > 0){
return;
}
this.mDefaultExpandImage = expandImage;
}
public int getmClusterCircleSize() {
return mClusterCircleSize;
}
/**
* @param mClusterCircleSize 设置聚合时圆的大小
* 默认28
*/
public void setmClusterCircleSize(int mClusterCircleSize) {
if(mClusterCircleSize < 10){
return;
}
this.mClusterCircleSize = mClusterCircleSize;
}
public int getmClusterCircleBg() {
return mClusterCircleBg;
}
/**
* @param mClusterCircleBg 设置聚合时圆的背景色,R.color.xxxx
* 默认黑色
*/
public void setmClusterCircleBg(int mClusterCircleBg) {
if(mClusterCircleBg == -1){
return;
}
this.mClusterCircleBg = ContextCompat.getColor(mContext, mClusterCircleBg);
}
public int getmClusterTextSize() {
return mClusterTextSize;
}
/**
* @param mClusterTextSize 设置聚合时圆中文字的大小
* 默认18
*/
public void setmClusterTextSize(int mClusterTextSize) {
if(mClusterTextSize < 10){
return;
}
this.mClusterTextSize = mClusterTextSize;
}
public int getmClusterTextColor() {
return mClusterTextColor;
}
/**
* @param mClusterTextColor 设置聚合时圆中文字得颜色
* 默认白色
*/
public void setmClusterTextColor(int mClusterTextColor) {
if(mClusterTextColor < -1){
return;
}
this.mClusterTextColor = ContextCompat.getColor(mContext, mClusterTextColor);
}
}
/**
* @param clusterImage int(资源ID)-聚合图片
*/
public void setClusterImage(int clusterImage) {
mClusterIv.setImageDrawable(getResources().getDrawable(clusterImage));
}
/**
* @return 聚合样式
*/
public ClusterStyleBuilder getClusterStyleBuilder() {
return mClusterStyleBuilder;
}
/**
* @param distance 默认逆地理编码距离是0.1,单位是km;
* 需要在最上层调用
*/
public void setGeoDistance(double distance){
this.distance = distance;
}
protected void showDialog() {
try {
if (myDialog != null && myDialog.isShowing()) {
myDialog.dismiss();
}
myDialog = new ProgressDialog(mContext);
myDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
myDialog.setMessage("正在加载...");
myDialog.setIndeterminate(false);
myDialog.setCancelable(false);
myDialog.show();
} catch (Exception e) {
}
}
/**
* 关闭
*/
protected void disDialog() {
try {
if (myDialog != null && myDialog.isShowing()) {
myDialog.dismiss();
}
myDialog = null;
} catch (Exception e) {
}
}
/**
* 天地图逆地址编码
* 当导入数据得时候,不显示加载框,不显示气泡组件
*
* @param point 当前点位
* @param isLoading 加载框
* @param showCallout 气泡
*/
private void requestGeoCeoder(Point point, boolean isLoading, boolean showCallout) {
if (isLoading) {
showDialog();
}
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("index", "bzdz");
JSONObject infoObject = new JSONObject();
infoObject.put("field", "xy");
infoObject.put("distance", String.valueOf(distance));
JSONObject xyObject = new JSONObject();
xyObject.put("lat", String.valueOf(point.getY()));
xyObject.put("lon", String.valueOf(point.getX()));
infoObject.put("point", xyObject);
jsonObject.put("geographicInfo", infoObject);
} catch (JSONException e) {
e.printStackTrace();
}
// Log.e("GEOCeoder========",jsonObject.toString());
OkHttp3Utils.doPost(Constants.BASE_GEO_URL, jsonObject.toString(), new Callback() {
@Override
public void onFailure(Call call, IOException e) {
disDialog();
// Toast.makeText(mContext, "请求失败,请重试", Toast.LENGTH_LONG).show();
Log.e("Fail", "e=" + e.toString());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
disDialog();
String address = null;
String poi = null;
if (response.isSuccessful()) {
if (response.body() != null) {
String responseStr = response.body().string();
// Log.e("responseStr", responseStr);
JsonObject jsonObject = GsonUtil.gsonToBean(responseStr, JsonObject.class);
int status = jsonObject.get("status").getAsInt();
if (status == 200) {
JsonArray dataArray = jsonObject.get("data").getAsJsonArray();
if (dataArray != null && dataArray.size() > 0) {
JsonObject jsonObject1 = (JsonObject) dataArray.get(0);
//地址全称
address = jsonObject1.get("dzqc").getAsString();
///地址详址
poi = jsonObject1.get("dzxz").getAsString();
}
}
}
}
Message message = Message.obtain();
message.obj = new LocationModel(point.getX(), point.getY(), address, poi, null);
message.what = 0;
message.arg1 = showCallout ? 0 : 1;
mHandler.sendMessage(message);
}
});
}
@SuppressLint("HandlerLeak")
Handler mHandler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
LocationModel locationModel = (LocationModel) msg.obj;
if(msg.what == 0){
setCallout(mCenteredGraphic, locationModel.getAddress(), locationModel.getPoi(), msg.arg1 == 0);
if (mIClusterPointInfoListener != null) {
mIClusterPointInfoListener.pointInfoCallBack(locationModel);
}
}
}
};
/**
* @param listener 点信息监听
*/
public void setIClusterPointInfoListener(IClusterPointInfoListener listener) {
this.mIClusterPointInfoListener = listener;
}
/**
* 设置气泡组件
*/
protected void setCallout(Graphic graphic, String address, String poi, boolean isShowCallout) {
Point point = (Point) graphic.getGeometry();
Callout mCallout = mMapView.getCallout();
if (mCallout.isShowing()) {
mCallout.dismiss();
}
View view = LayoutInflater.from(mContext).inflate(R.layout.layout_callout, null, false);
TextView mXPointTv = view.findViewById(R.id.callout_x_tv);
TextView mYPointTv = view.findViewById(R.id.callout_y_tv);
TextView mAddressTv = view.findViewById(R.id.callout_address_tv);
TextView mPoiTv = view.findViewById(R.id.callout_poi_tv);
ImageView mInfoIv = view.findViewById(R.id.callout_info_iv);
LinearLayout mDelLayout = view.findViewById(R.id.callout_del_ll);
TextView mDelTv = view.findViewById(R.id.callout_del_tv);
TextView mDescLabelTv = view.findViewById(R.id.callout_label_tv);
EditText mDescEt = view.findViewById(R.id.callout_desc_et);
TextView mCancelTv = view.findViewById(R.id.callout_cancel_tv);
TextView mOkTv = view.findViewById(R.id.callout_ok_tv);
if (mCalloutContentBuilder.mXPointFontColor != -1) {
mXPointTv.setTextColor(ContextCompat.getColor(mContext, mCalloutContentBuilder.mXPointFontColor));
}
if (mCalloutContentBuilder.mXPointFontSize != -1) {
mXPointTv.setTextSize(mCalloutContentBuilder.mXPointFontSize);
}
if (mCalloutContentBuilder.mXPointHide) {
mXPointTv.setVisibility(View.GONE);
} else {
mXPointTv.setVisibility(View.VISIBLE);
}
if (mCalloutContentBuilder.mYPointFontColor != -1) {
mYPointTv.setTextColor(ContextCompat.getColor(mContext, mCalloutContentBuilder.mYPointFontColor));
}
if (mCalloutContentBuilder.mYPointFontSize != -1) {
mYPointTv.setTextSize(mCalloutContentBuilder.mYPointFontSize);
}
if (mCalloutContentBuilder.mYPointHide) {
mYPointTv.setVisibility(View.GONE);
} else {
mYPointTv.setVisibility(View.VISIBLE);
}
if (mCalloutContentBuilder.mAddressFontColor != -1) {
mAddressTv.setTextColor(ContextCompat.getColor(mContext, mCalloutContentBuilder.mAddressFontColor));
}
if (mCalloutContentBuilder.mAddressFontSize != -1) {
mAddressTv.setTextSize(mCalloutContentBuilder.mAddressFontSize);
}
if (mCalloutContentBuilder.mAddressHide) {
mAddressTv.setVisibility(View.GONE);
} else {
mAddressTv.setVisibility(View.VISIBLE);
}
if (mCalloutContentBuilder.mPoiFontColor != -1) {
mPoiTv.setTextColor(ContextCompat.getColor(mContext, mCalloutContentBuilder.mPoiFontColor));
}
if (mCalloutContentBuilder.mPoiFontSize != -1) {
mPoiTv.setTextSize(mCalloutContentBuilder.mPoiFontSize);
}
if (mCalloutContentBuilder.mPoiHide) {
mPoiTv.setVisibility(View.GONE);
} else {
mPoiTv.setVisibility(View.VISIBLE);
}
if (mCalloutContentBuilder.mInfoImage != -1) {
mInfoIv.setImageDrawable(getResources().getDrawable(mCalloutContentBuilder.mInfoImage));
}
if (mCalloutContentBuilder.mInfoImageHide) {
mInfoIv.setVisibility(View.GONE);
} else {
mInfoIv.setVisibility(View.VISIBLE);
}
if (mCalloutContentBuilder.mDelBackground != -1) {
mDelLayout.setBackground(getResources().getDrawable(mCalloutContentBuilder.mDelBackground));
}
if (mCalloutContentBuilder.mDelFontColor != -1) {
mDelTv.setTextColor(ContextCompat.getColor(mContext, mCalloutContentBuilder.mDelFontColor));
}
if (mCalloutContentBuilder.mDelFontSize != -1) {
mDelTv.setTextSize(mCalloutContentBuilder.mDelFontSize);
}
if (mCalloutContentBuilder.mDelHide) {
mDelLayout.setVisibility(View.GONE);
} else {
mDelLayout.setVisibility(View.VISIBLE);
}
if (mCalloutContentBuilder.mDescLabelFontColor != -1) {
mDescLabelTv.setTextColor(ContextCompat.getColor(mContext, mCalloutContentBuilder.mDescLabelFontColor));
}
if (mCalloutContentBuilder.mDescLabelFontSize != -1) {
mDescLabelTv.setTextSize(mCalloutContentBuilder.mDescLabelFontSize);
}
if (mCalloutContentBuilder.mDescBackground != -1) {
mDescEt.setBackground(getResources().getDrawable(mCalloutContentBuilder.mDescBackground));
}
if (mCalloutContentBuilder.mDescFontColor != -1) {
mDescEt.setTextColor(ContextCompat.getColor(mContext, mCalloutContentBuilder.mDescFontColor));
}
if (mCalloutContentBuilder.mDescFontSize != -1) {
mDescEt.setTextSize(mCalloutContentBuilder.mDescFontSize);
}
if (mCalloutContentBuilder.mDescHide) {
mDescLabelTv.setVisibility(View.GONE);
mDescEt.setVisibility(View.GONE);
} else {
mDescLabelTv.setVisibility(View.VISIBLE);
mDescEt.setVisibility(View.VISIBLE);
}
if (mCalloutContentBuilder.mCancelBackground != -1) {
mCancelTv.setBackground(getResources().getDrawable(mCalloutContentBuilder.mCancelBackground));
}
if (mCalloutContentBuilder.mCancelFontColor != -1) {
mCancelTv.setTextColor(ContextCompat.getColor(mContext, mCalloutContentBuilder.mCancelFontColor));
}
if (mCalloutContentBuilder.mCancelFontSize != -1) {
mCancelTv.setTextSize(mCalloutContentBuilder.mCancelFontSize);
}
if (mCalloutContentBuilder.mCancelHide) {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(0, 0, 0, 0);
mOkTv.setLayoutParams(layoutParams);//因为在xml布局中有40dip的Margin
mCancelTv.setVisibility(View.GONE);
} else {
mCancelTv.setVisibility(View.VISIBLE);
}
if (mCalloutContentBuilder.mOkBackground != -1) {
mOkTv.setBackground(getResources().getDrawable(mCalloutContentBuilder.mOkBackground));
}
if (mCalloutContentBuilder.mOkFontColor != -1) {
mOkTv.setTextColor(ContextCompat.getColor(mContext, mCalloutContentBuilder.mOkFontColor));
}
if (mCalloutContentBuilder.mOkFontSize != -1) {
mOkTv.setTextSize(mCalloutContentBuilder.mOkFontSize);
}
if (mCalloutContentBuilder.mOkHide) {
mOkTv.setVisibility(View.GONE);
} else {
mOkTv.setVisibility(View.VISIBLE);
}
mDescEt.setOnFocusChangeListener((view15, b) -> {
if (b) {
ToolUtil.showSoftInput(mContext, mDescEt);
} else {
ToolUtil.hideSoftInput(mContext, mDescEt);
}
});
mXPointTv.setText(mContext.getString(R.string.string_callout_point_x, String.valueOf(point.getX())));
mYPointTv.setText(mContext.getString(R.string.string_callout_point_y, String.valueOf(point.getY())));
mAddressTv.setText(mContext.getString(R.string.string_callout_point_address, TextUtils.isEmpty(address) ? "暂无" : address));
mPoiTv.setText(mContext.getString(R.string.string_callout_point_POI, TextUtils.isEmpty(poi) ? "暂无" : poi));
Map<String, Object> attrResultMap = graphic.getAttributes();
if (attrResultMap != null && attrResultMap.size() > 0 && attrResultMap.containsKey("DESCRIPTION")) {
mDescEt.setText(attrResultMap.get("DESCRIPTION").toString());
}
mInfoIv.setOnClickListener(view1 -> {
if (mDelLayout.getVisibility() == View.GONE) {
mDelLayout.setVisibility(View.VISIBLE);
} else {
mDelLayout.setVisibility(View.GONE);
}
});
mCancelTv.setOnClickListener(view13 -> mCallout.dismiss());
mOkTv.setOnClickListener(view12 -> {
Map<String, Object> attrMap = graphic.getAttributes();
attrMap.put("DESCRIPTION", mDescEt.getText().toString());
if (mIClusterPointInfoListener != null) {
mIClusterPointInfoListener.pointInfoCallBack(new LocationModel(point.getX(), point.getY(), address, poi, mDescEt.getText().toString()));
}
mCallout.dismiss();
});
Callout.Style mCalloutStyle = new Callout.Style(mContext);
mCalloutStyle.setMaxWidth(mCalloutStyleBuilder.mCalloutMaxWidth); //设置最大宽度
if (mCalloutStyleBuilder.mCalloutMaxHeight != -1) {
mCalloutStyle.setMaxHeight(mCalloutStyleBuilder.mCalloutMaxHeight); //设置最大高度
}
mCalloutStyle.setMinWidth(mCalloutStyleBuilder.mCalloutMinWidth); //设置最小宽度
if (mCalloutStyleBuilder.mCalloutMinHeight != -1) {
mCalloutStyle.setMinHeight(mCalloutStyleBuilder.mCalloutMinHeight); //设置最小高度
}
mCalloutStyle.setBackgroundColor(ContextCompat.getColor(mContext, mCalloutStyleBuilder.mCalloutBackgroundColor)); //设置背景颜色
mCalloutStyle.setBorderWidth(mCalloutStyleBuilder.mCalloutBorderWidth); //设置边框宽度
mCalloutStyle.setBorderColor(ContextCompat.getColor(mContext, mCalloutStyleBuilder.mCalloutBorderColor)); //设置边框颜色
mCalloutStyle.setCornerRadius(mCalloutStyleBuilder.mCalloutCornerRadius); //设置圆角半径
if (mCalloutStyleBuilder.mCalloutLeaderLength != -1) {
mCalloutStyle.setLeaderLength(mCalloutStyleBuilder.mCalloutLeaderLength); //设置指示性长度
}
if (mCalloutStyleBuilder.mCalloutLeaderWidth != -1) {
mCalloutStyle.setLeaderWidth(mCalloutStyleBuilder.mCalloutLeaderWidth); //设置指示性宽度
}
mCalloutStyle.setLeaderPosition(mCalloutStyleBuilder.mLeaderPosition); //设置指示性位置
mCallout.setStyle(mCalloutStyle);
mCallout.setLocation(point);
mCallout.setContent(view);
if (isShowCallout) {
mCallout.show();
}
mMapView.setViewpointCenterAsync(point);
mInfoIv.setVisibility(View.GONE);
}
public CalloutStyleBuilder getCalloutStyleBuilder() {
return mCalloutStyleBuilder;
}
public static class CalloutStyleBuilder {
/**
* {@link Context}
*/
private Context mContext;
/**
* callout最大宽度
*/
private int mCalloutMaxWidth;
/**
* callout最大高度
*/
private int mCalloutMaxHeight = -1;
/**
* callout最小宽度
*/
private int mCalloutMinWidth;
/**
* callout最小高度
*/
private int mCalloutMinHeight = -1;
/**
* callout背景色
*/
private int mCalloutBackgroundColor;
/**
* callout圆角半径
*/
private int mCalloutCornerRadius;
/**
* callout边框宽度
*/
private int mCalloutBorderWidth;
/**
* callout边框颜色
*/
private int mCalloutBorderColor;
/**
* callout指示器长度
*/
private int mCalloutLeaderLength = -1;
/**
* callout指示器宽度
*/
private int mCalloutLeaderWidth = -1;
/**
* callout指示器位置
*/
private Callout.Style.LeaderPosition mLeaderPosition;
CalloutStyleBuilder(Context context) {
this.mContext = context;
this.mCalloutMaxWidth = (int) (ToolUtil.getScreenWidth(mContext) * 0.9);
this.mCalloutMinWidth = (int) (ToolUtil.getScreenWidth(mContext) * 0.9);
this.mCalloutBackgroundColor = R.color.colorWhiteTras;
this.mCalloutCornerRadius = 5;
this.mCalloutBorderWidth = 1;
this.mCalloutBorderColor = R.color.color_13227A;
this.mLeaderPosition = Callout.Style.LeaderPosition.LOWER_MIDDLE;
}
/**
* @param width callout最大宽度
*/
public void setCalloutMaxWidth(int width) {
this.mCalloutMaxWidth = width;
}
/**
* @param height callout最大高度
*/
public void setCalloutMaxHeight(int height) {
this.mCalloutMaxHeight = height;
}
/**
* @param width callout最小宽度
*/
public void setCalloutMinWidth(int width) {
this.mCalloutMinWidth = width;
}
/**
* @param height callout最小高度
*/
public void setCalloutMinHeight(int height) {
this.mCalloutMinHeight = height;
}
/**
* @param colorResId callout背景色,资源ID
*/
public void setCalloutBackgroundColor(int colorResId) {
this.mCalloutBackgroundColor = colorResId;
}
/**
* @param cornerRadius callout圆角半径
*/
public void setCalloutCornerRadius(int cornerRadius) {
this.mCalloutCornerRadius = cornerRadius;
}
/**
* @param borderWidth callout边框宽度
*/
public void setCalloutBorderWidth(int borderWidth) {
this.mCalloutBorderWidth = borderWidth;
}
/**
* @param colorResId callout边框颜色,资源ID
*/
public void setCalloutBorderColor(int colorResId) {
this.mCalloutBorderColor = colorResId;
}
/**
* @param leaderLength callout指示器长度
*/
public void setCalloutLeaderLength(int leaderLength) {
this.mCalloutLeaderLength = leaderLength;
}
/**
* @param leaderWidth callout指示器宽度
*/
public void setCalloutLeaderWidth(int leaderWidth) {
this.mCalloutLeaderWidth = leaderWidth;
}
/**
* @param position callout指示器位置
*/
public void setCalloutLeaderPosition(Variable.CalloutLeaderPosition position) {
if (position == Variable.CalloutLeaderPosition.DEFAULT) {
this.mLeaderPosition = Callout.Style.LeaderPosition.LOWER_MIDDLE;
} else if (position == Variable.CalloutLeaderPosition.AUTO) {
this.mLeaderPosition = Callout.Style.LeaderPosition.AUTOMATIC;
}
}
}
public CalloutContentBuilder getCalloutContentBuilder() {
return mCalloutContentBuilder;
}
public static class CalloutContentBuilder {
/**
* x点字体颜色
*/
private int mXPointFontColor = -1;
/**
* x点字体大小
*/
private int mXPointFontSize = -1;
/**
* x点隐藏
*/
private boolean mXPointHide = false;
/**
* y点字体颜色
*/
private int mYPointFontColor = -1;
/**
* y点字体大小
*/
private int mYPointFontSize = -1;
/**
* y点隐藏
*/
private boolean mYPointHide = false;
/**
* 地址字体颜色
*/
private int mAddressFontColor = -1;
/**
* 地址字体大小
*/
private int mAddressFontSize = -1;
/**
* 地址隐藏
*/
private boolean mAddressHide = false;
/**
* poi字体颜色
*/
private int mPoiFontColor = -1;
/**
* poi字体大小
*/
private int mPoiFontSize = -1;
/**
* poi隐藏
*/
private boolean mPoiHide = false;
/**
* 右边信息图标
*/
private int mInfoImage = -1;
/**
* 右边信息图标隐藏
*/
private boolean mInfoImageHide = false;
/**
* 右边删除背景
*/
private int mDelBackground = -1;
/**
* 右边删除字体颜色
*/
private int mDelFontColor = -1;
/**
* 右边删除字体大小
*/
private int mDelFontSize = -1;
/**
* 右边删除隐藏
*/
private boolean mDelHide = true;
/**
* 补充信息label字体颜色
*/
private int mDescLabelFontColor = -1;
/**
* 补充信息label字体大小
*/
private int mDescLabelFontSize = -1;
/**
* 补充信息字体颜色
*/
private int mDescFontColor = -1;
/**
* 补充信息字体大小
*/
private int mDescFontSize = -1;
/**
* 补充信息背景
*/
private int mDescBackground = -1;
/**
* 补充信息隐藏
*/
private boolean mDescHide = false;
/**
* 取消字体颜色
*/
private int mCancelFontColor = -1;
/**
* 取消字体大小
*/
private int mCancelFontSize = -1;
/**
* 取消背景
*/
private int mCancelBackground = -1;
/**
* 取消隐藏
*/
private boolean mCancelHide = false;
/**
* 确定字体颜色
*/
private int mOkFontColor = -1;
/**
* 确定字体大小
*/
private int mOkFontSize = -1;
/**
* 确定背景
*/
private int mOkBackground = -1;
/**
* 确定隐藏
*/
private boolean mOkHide = false;
/**
* @param mXPointFontColor x点字体颜色
*/
public void setmXPointFontColor(int mXPointFontColor) {
this.mXPointFontColor = mXPointFontColor;
}
/**
* @param mXPointFontSize x点字体大小
*/
public void setmXPointFontSize(int mXPointFontSize) {
this.mXPointFontSize = mXPointFontSize;
}
/**
* @param mXPointHide x点隐藏
*/
public void setmXPointHide(boolean mXPointHide) {
this.mXPointHide = mXPointHide;
}
/**
* @param mYPointFontColor y点字体颜色
*/
public void setmYPointFontColor(int mYPointFontColor) {
this.mYPointFontColor = mYPointFontColor;
}
/**
* @param mYPointFontSize y点字体大小
*/
public void setmYPointFontSize(int mYPointFontSize) {
this.mYPointFontSize = mYPointFontSize;
}
/**
* @param mYPointHide y点隐藏
*/
public void setmYPointHide(boolean mYPointHide) {
this.mYPointHide = mYPointHide;
}
/**
* @param mAddressFontColor 地址字体颜色
*/
public void setmAddressFontColor(int mAddressFontColor) {
this.mAddressFontColor = mAddressFontColor;
}
/**
* @param mAddressFontSize 地址字体大小
*/
public void setmAddressFontSize(int mAddressFontSize) {
this.mAddressFontSize = mAddressFontSize;
}
/**
* @param mAddressHide 地址隐藏
*/
public void setmAddresstHide(boolean mAddressHide) {
this.mAddressHide = mAddressHide;
}
/**
* @param mPoiFontColor Poi字体颜色
*/
public void setmPoiFontColor(int mPoiFontColor) {
this.mPoiFontColor = mPoiFontColor;
}
/**
* @param mPoiFontSize Poi字体大小
*/
public void setmPoiFontSize(int mPoiFontSize) {
this.mPoiFontSize = mPoiFontSize;
}
/**
* @param mPoiHide Poi隐藏
*/
public void setmPoiHide(boolean mPoiHide) {
this.mPoiHide = mPoiHide;
}
/**
* @param mInfoImage 右边信息图标
*/
public void setmInfoImage(int mInfoImage) {
this.mInfoImage = mInfoImage;
}
/**
* @param mInfoImageHide 右边信息图标隐藏
*/
public void setmInfoImageHide(boolean mInfoImageHide) {
this.mInfoImageHide = mInfoImageHide;
}
/**
* @param mDelBackground 右边删除背景
*/
public void setmDelBackground(int mDelBackground) {
this.mDelBackground = mDelBackground;
}
/**
* @param mDelFontColor 右边删除字体颜色
*/
public void setmDelFontColor(int mDelFontColor) {
this.mDelFontColor = mDelFontColor;
}
/**
* @param mDelFontSize 右边删除字体大小
*/
public void setmDelFontSize(int mDelFontSize) {
this.mDelFontSize = mDelFontSize;
}
/**
* @param mDelHide 右边删除隐藏
*/
public void setmDelHide(boolean mDelHide) {
this.mDelHide = mDelHide;
}
/**
* @param mDescLabelFontColor 补充信息label字体颜色
*/
public void setmDescLabelFontColor(int mDescLabelFontColor) {
this.mDescLabelFontColor = mDescLabelFontColor;
}
/**
* @param mDescLabelFontSize 补充信息label字体大小
*/
public void setmDescLabelFontSize(int mDescLabelFontSize) {
this.mDescLabelFontSize = mDescLabelFontSize;
}
/**
* @param mDescFontColor 补充信息字体颜色
*/
public void setmDescFontColor(int mDescFontColor) {
this.mDescFontColor = mDescFontColor;
}
/**
* @param mDescFontSize 补充信息字体大小
*/
public void setmDescFontSize(int mDescFontSize) {
this.mDescFontSize = mDescFontSize;
}
/**
* @param mDescBackground 补充信息背景
*/
public void setmDescBackground(int mDescBackground) {
this.mDescBackground = mDescBackground;
}
/**
* @param mDescHide 补充信息隐藏
*/
public void setmDescHide(boolean mDescHide) {
this.mDescHide = mDescHide;
}
/**
* @param mCancelFontColor 取消按钮字体颜色
*/
public void setmCancelFontColor(int mCancelFontColor) {
this.mCancelFontColor = mCancelFontColor;
}
/**
* @param mCancelFontSize 取消按钮字体大小
*/
public void setmCancelFontSize(int mCancelFontSize) {
this.mCancelFontSize = mCancelFontSize;
}
/**
* @param mCancelBackground 取消按钮背景
*/
public void setmCancelBackground(int mCancelBackground) {
this.mCancelBackground = mCancelBackground;
}
/**
* @param mCancelHide 取消按钮隐藏
*/
public void setmCancelHide(boolean mCancelHide) {
this.mCancelHide = mCancelHide;
}
/**
* @param mOkFontColor 确定按钮字体颜色
*/
public void setmOkFontColor(int mOkFontColor) {
this.mOkFontColor = mOkFontColor;
}
/**
* @param mOkFontSize 确定按钮字体大小
*/
public void setmOkFontSize(int mOkFontSize) {
this.mOkFontSize = mOkFontSize;
}
/**
* @param mOkBackground 确定按钮背景
*/
public void setmOkBackground(int mOkBackground) {
this.mOkBackground = mOkBackground;
}
/**
* @param mOkHide 确定按钮隐藏
*/
public void setmOkHide(boolean mOkHide) {
this.mOkHide = mOkHide;
}
}
}
......@@ -173,7 +173,7 @@ public class ArcGisHotPotsView extends LinearLayout implements View.OnClickListe
if (bottomParentView == null) {
bottomParentView = View.inflate(mContext, R.layout.layout_hot_pots_input, null);
initBottomView();
popupLayout = PopupLayout.init(mContext, bottomParentView);
popupLayout = new PopupLayout(mContext, bottomParentView);
popupLayout.setUseRadius(true);
popupLayout.setHeight((int) (ToolUtil.getScreenHeight(mContext) * 0.35), false);
}
......
......@@ -25,7 +25,6 @@ import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
......@@ -218,6 +217,16 @@ public class ArcGisLocationView extends LinearLayout implements View.OnClickList
*/
private List<LocationModel> locationModelList = new LinkedList<>();
/**
* 默认逆地理编码距离是0.1,单位是km;
*/
private double distance = 0.1;
/**
* 使用聚合时使用此字段
*/
protected boolean isUseCluster = false;
public ArcGisLocationView(Context context, ArcGisMapView arcGisMapView) {
this(context);
this.mContext = context;
......@@ -1052,6 +1061,8 @@ public class ArcGisLocationView extends LinearLayout implements View.OnClickList
@Override
public void onUp(Variable.TouchUp touchUp, MotionEvent motionEvent) {
if(isUseCluster)
return;
if (touchUp == Variable.TouchUp.UP && mFollowMapGetCenterPoint) {
final android.graphics.Point screenPoint = new android.graphics.Point(
mScreenCenterXPoint,
......@@ -1109,6 +1120,8 @@ public class ArcGisLocationView extends LinearLayout implements View.OnClickList
@Override
public void onSingleTap(MotionEvent motionEvent) {
if(isUseCluster)
return;
switch (currSearchType) {
case SEARCH:
case NONE:
......@@ -1121,6 +1134,8 @@ public class ArcGisLocationView extends LinearLayout implements View.OnClickList
@Override
public void onLongPress(MotionEvent motionEvent) {
if(isUseCluster)
return;
switch (currSearchType) {
case SEARCH:
case NONE:
......@@ -1204,6 +1219,14 @@ public class ArcGisLocationView extends LinearLayout implements View.OnClickList
}
/**
* @param distance 默认逆地理编码距离是0.1,单位是km;
* 需要在最上层调用
*/
public void setGeoDistance(double distance){
this.distance = distance;
}
/**
* 正常点击显示加载狂,显示气泡组件
*
* @param point 坐标点
......@@ -1227,21 +1250,31 @@ public class ArcGisLocationView extends LinearLayout implements View.OnClickList
showDialog();
}
double[] lngArray = ToolUtil.calcMaxMinLng(point, 0.5);
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("jsjd", String.valueOf(lngArray[0]));
jsonObject.put("qsjd", String.valueOf(lngArray[1]));
jsonObject.put("jswd", String.valueOf(lngArray[2]));
jsonObject.put("qswd", String.valueOf(lngArray[3]));
jsonObject.put("index","bzdz");
JSONObject infoObject = new JSONObject();
infoObject.put("field","xy");
infoObject.put("distance",String.valueOf(distance));
JSONObject xyObject = new JSONObject();
xyObject.put("lat",String.valueOf(point.getY()));
xyObject.put("lon",String.valueOf(point.getX()));
infoObject.put("point",xyObject);
jsonObject.put("geographicInfo",infoObject);
} catch (JSONException e) {
e.printStackTrace();
}
// Log.e("GEOCeoder========",jsonObject.toString());
OkHttp3Utils.doPost(Constants.BASE_GEO_URL, jsonObject.toString(), new Callback() {
@Override
public void onFailure(Call call, IOException e) {
disDialog();
Toast.makeText(mContext, "请求失败,请重试", Toast.LENGTH_LONG).show();
// Toast.makeText(mContext, "请求失败,请重试", Toast.LENGTH_LONG).show();
Log.e("Fail", "e=" + e.toString());
}
......@@ -1253,7 +1286,7 @@ public class ArcGisLocationView extends LinearLayout implements View.OnClickList
if (response.isSuccessful()) {
if (response.body() != null) {
String responseStr = response.body().string();
Log.e("responseStr", responseStr);
// Log.e("responseStr", responseStr);
JsonObject jsonObject = GsonUtil.gsonToBean(responseStr, JsonObject.class);
int status = jsonObject.get("status").getAsInt();
if (status == 200) {
......@@ -1262,18 +1295,8 @@ public class ArcGisLocationView extends LinearLayout implements View.OnClickList
JsonObject jsonObject1 = (JsonObject) dataArray.get(0);
//地址全称
address = jsonObject1.get("dzqc").getAsString();
///所属派出所代码_名称
poi = jsonObject1.get("sspcsdm_mc").getAsString();
// if (dataArray.size() == 1) {
// JsonObject jsonObject1 = (JsonObject) dataArray.get(0);
// //地址全称
// address = jsonObject1.get("dzqc").getAsString();
// ///所属派出所代码_名称
// poi = jsonObject1.get("sspcsdm_mc").getAsString();
// } else {
//
// }
///地址详址
poi = jsonObject1.get("dzxz").getAsString();
}
}
......@@ -1289,6 +1312,12 @@ public class ArcGisLocationView extends LinearLayout implements View.OnClickList
}
});
/**************天地图的逆地址编码**************************/
// String urlParams = Constants.BASE_TIANDITU_GEO_URL + "?postStr={'lon':" + point.getX() + ",'lat':" + point.getY() + ",'ver':1}&type=geocode&tk=" + Constants.BASE_TIANDITU_KEY;
// OkHttp3Utils.doGet(urlParams, new Callback() {
......
......@@ -54,6 +54,11 @@ public class ArcGisMapView extends LinearLayout {
* 导航地图操作图层(点)
*/
private GraphicsOverlay mRouteMarkerGraphicsOverlay;
/**
* 聚合地图操作图层(点)
*/
private GraphicsOverlay mClusterGraphicsOverlay;
/**
* 长按事件拦截
*/
......@@ -107,6 +112,7 @@ public class ArcGisMapView extends LinearLayout {
addLocationGraphicLayers();
addSearchGraphicLayers();
addRouteMarkerGraphicLayers();
addClusterGraphicLayers();
mLongPressEvent = null;
mMapView.setOnTouchListener(new ArcGisMapView.MapTouchListener(getContext().getApplicationContext(), mMapView));
......@@ -125,6 +131,7 @@ public class ArcGisMapView extends LinearLayout {
mLocationGraphicsOverlay.setOpacity(0.8f);
mMapView.getGraphicsOverlays().add(mLocationGraphicsOverlay);
}
private void addSearchGraphicLayers() {
// Add location layer
if (mSearchGraphicsOverlay == null) {
......@@ -133,6 +140,7 @@ public class ArcGisMapView extends LinearLayout {
mSearchGraphicsOverlay.setOpacity(0.8f);
mMapView.getGraphicsOverlays().add(mSearchGraphicsOverlay);
}
private void addNaviGraphicLayers() {
// Add location layer
if (mNaviGraphicsOverlay == null) {
......@@ -141,6 +149,7 @@ public class ArcGisMapView extends LinearLayout {
mNaviGraphicsOverlay.setOpacity(0.8f);
mMapView.getGraphicsOverlays().add(mNaviGraphicsOverlay);
}
private void addRouteMarkerGraphicLayers() {
// Add location layer
if (mRouteMarkerGraphicsOverlay == null) {
......@@ -150,6 +159,15 @@ public class ArcGisMapView extends LinearLayout {
mMapView.getGraphicsOverlays().add(mRouteMarkerGraphicsOverlay);
}
private void addClusterGraphicLayers() {
// Add location layer
if (mClusterGraphicsOverlay == null) {
mClusterGraphicsOverlay = new GraphicsOverlay();
}
mClusterGraphicsOverlay.setOpacity(0.8f);
mMapView.getGraphicsOverlays().add(mClusterGraphicsOverlay);
}
protected MapView getMapView() {
return mMapView;
}
......@@ -157,16 +175,23 @@ public class ArcGisMapView extends LinearLayout {
protected GraphicsOverlay getLocationGraphicsOverlay() {
return mLocationGraphicsOverlay;
}
protected GraphicsOverlay getSearchGraphicsOverlay() {
return mSearchGraphicsOverlay;
}
protected GraphicsOverlay getNaviGraphicsOverlay() {
return mSearchGraphicsOverlay;
}
protected GraphicsOverlay getRouteMarkerGraphicsOverlay() {
return mRouteMarkerGraphicsOverlay;
}
protected GraphicsOverlay getClusterGraphicsOverlay(){
return mClusterGraphicsOverlay;
}
private class MapTouchListener extends DefaultMapViewOnTouchListener {
/**
* Instantiates a new DrawingMapViewOnTouchListener with the specified
......@@ -192,6 +217,10 @@ public class ArcGisMapView extends LinearLayout {
}
if (myTouchClusterListener != null) {
myTouchLocationListener.onUp(Variable.TouchUp.UP, motionEvent);
}
if (mRotateEvent != null && myTouchCompassListener != null) {
mRotateEvent = null;
myTouchCompassListener.onUp(Variable.TouchUp.RORATE, motionEvent);
......@@ -204,6 +233,9 @@ public class ArcGisMapView extends LinearLayout {
if (myTouchLocationListener != null) {
myTouchLocationListener.onSingleTap(motionEvent);
}
if (myTouchClusterListener != null) {
myTouchClusterListener.onSingleTap(motionEvent);
}
return super.onSingleTapConfirmed(motionEvent);
}
......@@ -232,6 +264,7 @@ public class ArcGisMapView extends LinearLayout {
private MyTouchLocationListener myTouchLocationListener;
private MyTouchCompassListener myTouchCompassListener;
private MyTouchClusterListener myTouchClusterListener;
protected void setMyTouchLocationListener(MyTouchLocationListener touchListener) {
this.myTouchLocationListener = touchListener;
......@@ -241,6 +274,10 @@ public class ArcGisMapView extends LinearLayout {
this.myTouchCompassListener = touchListener;
}
protected void setMyTouchClusterListener(MyTouchClusterListener touchListener) {
this.myTouchClusterListener = touchListener;
}
/**
* 位置触摸监听类
*/
......@@ -288,4 +325,25 @@ public class ArcGisMapView extends LinearLayout {
void onRotate(double rotationAngle);
}
/**
* 聚合触摸监听类
*/
interface MyTouchClusterListener {
/**
* 手指抬起时
*
* @param touchUp {@link Variable.TouchUp}
* @param motionEvent 移动事件
*/
void onUp(Variable.TouchUp touchUp, MotionEvent motionEvent);
/**
* 单击
*
* @param motionEvent 移动事件
*/
void onSingleTap(MotionEvent motionEvent);
}
}
......@@ -61,6 +61,7 @@ import java.util.List;
import cn.com.founder.arcgislib.R;
import cn.com.founder.arcgislib.common.Variable;
import cn.com.founder.arcgislib.constants.Constants;
import cn.com.founder.arcgislib.model.PointModel;
import cn.com.founder.arcgislib.model.SearchModel;
import cn.com.founder.arcgislib.search.listener.ISearchSelectedListener;
import cn.com.founder.arcgislib.utils.DensityUtil;
......@@ -198,6 +199,8 @@ public class ArcGisNaviView extends FrameLayout implements View.OnClickListener,
initRoute();
}
private ArcGisNaviView(Context context) {
......@@ -223,6 +226,10 @@ public class ArcGisNaviView extends FrameLayout implements View.OnClickListener,
if (mineNaviRoute == null) {
MineNaviMain.getInstance().setNaviURL(Constants.BASE_NAVI_URL);
/**
* 设置华为token
*/
// MineNaviMain.getInstance().setHuaweicloudToken();
/**
* 获取路径
*/
MineNaviMain.getInstance().init(FileSource.getCachePath(mContext) + "/", mContext, (i, s) -> Log.e("onSdkAuthComplete", i + "#认证"));
......@@ -253,11 +260,14 @@ public class ArcGisNaviView extends FrameLayout implements View.OnClickListener,
* 设置算路成功失败回调
*/
mineNaviRoute.setRoutePlanListener(i -> {
Toast.makeText(mContext, "i="+i, Toast.LENGTH_LONG).show();
if (i == MineNaviRoute.ErrorCode.success || i == MineNaviRoute.ErrorCode.successAndLimit) {
routeInfoList.clear();
Toast.makeText(mContext, "路线规划完毕", Toast.LENGTH_LONG).show();
arcGisSearchView.disDialog();
popupLayout.dismiss();
if(popupLayout != null){
popupLayout.dismiss();
}
createNaviBt();
// 语音播报
List<Integer> mergeRouteCalcCond = mineNaviRoute.getMergeRouteCalcCond();
......@@ -680,8 +690,6 @@ public class ArcGisNaviView extends FrameLayout implements View.OnClickListener,
@SuppressLint("SimpleDateFormat") SimpleDateFormat format = new SimpleDateFormat("HH:mm");
ll_navi_bottom_info_text.setNaviContent("$disStr $timeStr", format.format(date) + "到达");
//TODO 更新蚯蚓图
}
private void showServiceArea() {
......@@ -760,6 +768,26 @@ public class ArcGisNaviView extends FrameLayout implements View.OnClickListener,
mNaviIv.setImageDrawable(getResources().getDrawable(naviImage));
}
/**
* 自定义点开始导航
* @param startPoint 起点
* @param endPoint 终点
* new PointModel(113.6242709,22.8810121,"新丽佳百货"),new PointModel(113.6351135,22.8874085,"大自然花场")
*/
public void setCustomPointNavi(PointModel startPoint, PointModel endPoint) {
if (startPoint == null) {
Toast.makeText(mContext, "请设置起点", Toast.LENGTH_LONG).show();
return;
}
if (endPoint == null) {
Toast.makeText(mContext, "请设置终点", Toast.LENGTH_LONG).show();
return;
}
setCustomPointNaviRoute(startPoint, endPoint);
}
@Override
public void onClick(View view) {
......@@ -768,14 +796,16 @@ public class ArcGisNaviView extends FrameLayout implements View.OnClickListener,
arcGisLocationView.mNaviGraphicsOverlay.getGraphics().clear();
arcGisLocationView.mMapView.getCallout().dismiss();
}
setPopupLayout();
}
private void setPopupLayout() {
if (bottomNaviParentView == null) {
bottomNaviParentView = View.inflate(mContext, R.layout.layout_navi_input, null);
initBottomView();
popupLayout = PopupLayout.init(mContext, bottomNaviParentView);
popupLayout = new PopupLayout(mContext, bottomNaviParentView);
popupLayout.setUseRadius(true);
popupLayout.setHeight((int) (ToolUtil.getScreenHeight(mContext) * 0.35), false);
}
......@@ -807,7 +837,7 @@ public class ArcGisNaviView extends FrameLayout implements View.OnClickListener,
isSelectStartAddress = true;
arcGisSearchView.currSearchType = Variable.SearchType.START_ADDRESS_SEARCH;
arcGisSearchView.setVisibility(View.VISIBLE);
arcGisSearchView.mScrollLayout.scrollToClose();
arcGisSearchView.mBottomLayout.performClick();
});
endAddressTv.setOnClickListener(view -> {
......@@ -822,7 +852,8 @@ public class ArcGisNaviView extends FrameLayout implements View.OnClickListener,
isSelectStartAddress = false;
arcGisSearchView.currSearchType = Variable.SearchType.END_ADDRESS_SEARCH;
arcGisSearchView.setVisibility(View.VISIBLE);
arcGisSearchView.mScrollLayout.scrollToClose();
arcGisSearchView.mBottomLayout.performClick();
});
......@@ -852,17 +883,18 @@ public class ArcGisNaviView extends FrameLayout implements View.OnClickListener,
Toast.makeText(mContext, "出发地和目的地不能是同一地址", Toast.LENGTH_LONG).show();
return;
}
setRoute();
setDefaultSearchNaviRoute();
});
}
private void setRoute() {
// mContext.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//屏幕常亮
private void setDefaultSearchNaviRoute() {
arcGisLocationView.mNaviGraphicsOverlay.getGraphics().clear();
arcGisLocationView.setSearchLocation(startSearchModel.getX(), startSearchModel.getY(), Variable.SearchType.START_ADDRESS_SEARCH);
arcGisLocationView.setSearchLocation(endSearchModel.getX(), endSearchModel.getY(), Variable.SearchType.END_ADDRESS_SEARCH);
Log.e("startPoint",startSearchModel.getX()+","+ startSearchModel.getY() + "," + startSearchModel.getPoiname());
Log.e("endPoint",endSearchModel.getX()+","+ endSearchModel.getY() + "," + endSearchModel.getPoiname());
PlanPoint startPoint = new PlanPoint();
startPoint.name = startSearchModel.getPoiname();
double[] startPointArr = GpsUtil.toGCJ02Point(startSearchModel.getY(), startSearchModel.getX());
......@@ -877,7 +909,6 @@ public class ArcGisNaviView extends FrameLayout implements View.OnClickListener,
// endPoint.pos = new GeoPoint(22.970898,114.047684);
endPoint.idx = PlanPoint.VIA1_IDX;
/**
* 设置开始点
*
......@@ -898,6 +929,59 @@ public class ArcGisNaviView extends FrameLayout implements View.OnClickListener,
arcGisSearchView.showDialog();
}
/**
* 自定义点开启导航
*
* @param startPoint 起点
* @param endPoint 终点
*/
private void setCustomPointNaviRoute(PointModel startPoint, PointModel endPoint) {
arcGisLocationView.mLocationGraphicsOverlay.getGraphics().clear();
arcGisLocationView.mNaviGraphicsOverlay.getGraphics().clear();
arcGisLocationView.mMapView.getCallout().dismiss();
if (mapScanleValue != arcGisLocationView.mMapView.getMapScale()) {
arcGisLocationView.mMapView.setViewpointScaleAsync(mapScanleValue);
}
arcGisLocationView.setSearchLocation(startPoint.getxPoint(), startPoint.getyPoint(), Variable.SearchType.START_ADDRESS_SEARCH);
arcGisLocationView.setSearchLocation(endPoint.getxPoint(), endPoint.getyPoint(), Variable.SearchType.END_ADDRESS_SEARCH);
PlanPoint startPlantPoint = new PlanPoint();
startPlantPoint.name = startPoint.getPointName();
//互联网
// double[] startPointArr = GpsUtil.toGCJ02Point(startPoint.getyPoint(), startPoint.getxPoint());
// startPlantPoint.pos = new GeoPoint(startPointArr[0], startPointArr[1]);
//公安网
startPlantPoint.pos = new GeoPoint(startPoint.getyPoint(), startPoint.getxPoint());
startPlantPoint.idx = 0;
PlanPoint endPlantPoint = new PlanPoint();
endPlantPoint.name = endPoint.getPointName();
// double[] endPointArr = GpsUtil.toGCJ02Point(endPoint.getyPoint(), endPoint.getxPoint());
// endPlantPoint.pos = new GeoPoint(endPointArr[0], endPointArr[1]);
endPlantPoint.pos = new GeoPoint(endPoint.getyPoint(), endPoint.getxPoint());
endPlantPoint.idx = PlanPoint.VIA1_IDX;
/**
* 设置开始点
*
* @param originPoint 开始点
* @return 设置成功还是失败
*/
mineNaviRoute.setOrigin(startPlantPoint);
/**
* 设置目的地
*
* @param destPoint 目的地
* @return 设置成功还是失败
*/
mineNaviRoute.setDestination(endPlantPoint);
mineNaviRoute.calcDriveRoute();
}
@Override
public void selectedResult(SearchModel searchModel) {
arcGisSearchView.mSearchEt.setText("");
......
......@@ -10,13 +10,16 @@ import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ActionMode;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
......@@ -26,7 +29,6 @@ import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.minedata.minenavi.common.OkHttp3Utils;
......@@ -35,8 +37,11 @@ import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import cn.com.founder.arcgislib.R;
import cn.com.founder.arcgislib.common.Variable;
......@@ -46,7 +51,8 @@ import cn.com.founder.arcgislib.model.SearchModel;
import cn.com.founder.arcgislib.search.listener.ISearchSelectedListener;
import cn.com.founder.arcgislib.utils.GsonUtil;
import cn.com.founder.arcgislib.utils.KeyboardUtil;
import cn.com.founder.arcgislib.widget.scrolllayout.ScrollLayout;
import cn.com.founder.arcgislib.utils.ToolUtil;
import cn.com.founder.arcgislib.widget.popup.PopupLayout;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
......@@ -73,13 +79,20 @@ public class ArcGisSearchView extends LinearLayout {
*/
private ArcGisLocationView arcGisLocationView;
/**
* 滚动布局
* 底部布局
*/
protected ScrollLayout mScrollLayout;
protected LinearLayout mBottomLayout;
private TextView mSearchResultTv;
/**
* 指示器
* popup
*/
protected ImageView mIndicatorIv;
protected PopupLayout searchPopupLayout;
/**
* 下拉框
*/
private LinearLayout mTypeLayout;
private TextView mTypeResultTv;
/**
* 搜索框
*/
......@@ -97,17 +110,13 @@ public class ArcGisSearchView extends LinearLayout {
*/
protected LinearLayout mEmptyLayout;
/**
* 滚动布局当前状态
*/
private ScrollLayout.Status currentState = ScrollLayout.Status.OPENED;
/**
* 适配器
*/
private SearchAdapter mAdapter;
/**
* 适配器数据
*/
private List<SearchModel> resultList = new ArrayList<>();
private List<SearchModel> resultList = new LinkedList<>();
/**
* 加载框
*/
......@@ -119,10 +128,21 @@ public class ArcGisSearchView extends LinearLayout {
protected Variable.SearchType currSearchType = Variable.SearchType.SEARCH;
/**
* 搜索类型,默认poi
*/
private int currentSpinnerType = 0;
private LinearLayout mSearchTypeLayout;
private TextView mPoiTv;
private TextView mDwTv;
private TextView mFwTv;
private TextView mDzTv;
public ArcGisSearchView(Context context, ArcGisLocationView locationView) {
this(context);
this.mContext = context;
this.arcGisLocationView = locationView;
setSearchPopupLayout();
}
private ArcGisSearchView(Context context) {
......@@ -135,49 +155,102 @@ public class ArcGisSearchView extends LinearLayout {
private ArcGisSearchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
inflate(context, R.layout.layout_search, this);
inflate(context, R.layout.layout_search_new, this);
instance = this;
mScrollLayout = findViewById(R.id.search_scroll_layout);
mIndicatorIv = findViewById(R.id.search_scroll_arrow_iv);
mSearchEt = findViewById(R.id.search_scroll_content_search_et);
mCancelTv = findViewById(R.id.search_scroll_content_search_cancel_tv);
mRecyclerView = findViewById(R.id.search_swipeRecyclerView);
mEmptyLayout = findViewById(R.id.search_empty);
mBottomLayout = findViewById(R.id.search_total_ll);
mSearchResultTv = findViewById(R.id.search_result_tv);
initView();
initScrollLayout();
}
private void initView() {
mBottomLayout.setOnClickListener(view -> {
searchPopupLayout.show(PopupLayout.POSITION_BOTTOM);
mSearchEt.requestFocus();
mSearchEt.setFocusableInTouchMode(true);
mSearchEt.setFocusable(true);
KeyboardUtil.showKeyboard(mSearchEt, true);
});
}
private void setSearchPopupLayout() {
View searchParentView = View.inflate(mContext, R.layout.layout_item_search, null);
initSearchView(searchParentView);
searchPopupLayout = new PopupLayout(mContext, searchParentView);
searchPopupLayout.setUseRadius(true);
searchPopupLayout.setHeight((int) (ToolUtil.getScreenHeight(mContext) * 0.7), false);
searchPopupLayout.setDismissListener(() -> {
mSearchEt.setFocusable(false);
mSearchEt.setFocusableInTouchMode(false);
KeyboardUtil.hideKeyboard(mSearchEt);
});
}
private void initSearchView(View searchParentView) {
mTypeLayout = searchParentView.findViewById(R.id.search_scroll_content_type_ll);
mTypeResultTv = searchParentView.findViewById(R.id.search_scroll_content_type_tv);
mSearchEt = searchParentView.findViewById(R.id.search_scroll_content_search_et);
mCancelTv = searchParentView.findViewById(R.id.search_scroll_content_search_cancel_search_tv);
mRecyclerView = searchParentView.findViewById(R.id.search_swipeRecyclerView);
mEmptyLayout = searchParentView.findViewById(R.id.search_empty);
mSearchTypeLayout = searchParentView.findViewById(R.id.search_type_ll);
mPoiTv = searchParentView.findViewById(R.id.search_type_poi_tv);
mDwTv = searchParentView.findViewById(R.id.search_type_dw_tv);
mFwTv = searchParentView.findViewById(R.id.search_type_fw_tv);
mDzTv = searchParentView.findViewById(R.id.search_type_dz_tv);
mCancelTv.setOnClickListener(view -> {
if (mCancelTv.getText().toString().equals("取消")) {
KeyboardUtil.hideKeyboard(mSearchEt);
searchPopupLayout.dismiss();
} else {
doSearchByKeyWord(mSearchEt.getText().toString().trim());
}
});
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
mAdapter = new SearchAdapter(resultList);
mRecyclerView.setAdapter(mAdapter);
mIndicatorIv.setOnClickListener(view -> {
if (currentState.equals(ScrollLayout.Status.OPENED)) {
mScrollLayout.scrollToClose();
mTypeLayout.setOnClickListener(view ->{
if(mSearchTypeLayout.getVisibility() == View.VISIBLE){
mSearchTypeLayout.setVisibility(View.GONE);
}else{
mSearchTypeLayout.setVisibility(View.VISIBLE);
}
} );
} else if (currentState.equals(ScrollLayout.Status.CLOSED)) {
mScrollLayout.scrollToOpen();
disableCopyAndPaste(mSearchEt);
mSearchEt.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
return false;
}
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
} else if (currentState.equals(ScrollLayout.Status.EXIT)) {
mScrollLayout.scrollToOpen();
@Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
return false;
}
});
mSearchEt.setOnFocusChangeListener((view, b) -> {
if (b) {
mScrollLayout.scrollToClose();
KeyboardUtil.openKeybord(mSearchEt, mContext);
} else {
mScrollLayout.scrollToOpen();
KeyboardUtil.hideKeyboard(mSearchEt);
@Override
public void onDestroyActionMode(ActionMode actionMode) {
}
});
mSearchEt.setOnClickListener(view -> {
mScrollLayout.scrollToClose();
KeyboardUtil.openKeybord(mSearchEt, mContext);
mSearchEt.requestFocus();
mSearchEt.setFocusableInTouchMode(true);
mSearchEt.setFocusable(true);
KeyboardUtil.showKeyboard(mSearchEt, true);
if (!searchPopupLayout.isShowing()) {
searchPopupLayout.show(PopupLayout.POSITION_BOTTOM);
}
});
mSearchEt.setOnEditorActionListener((v, actionId, event) -> {
......@@ -202,76 +275,46 @@ public class ArcGisSearchView extends LinearLayout {
@Override
public void afterTextChanged(Editable editable) {
doSearchByKeyWord(editable.toString());
mSearchResultTv.setText(editable.toString().trim());
if (TextUtils.isEmpty(editable.toString().trim())) {
mCancelTv.setText("取消");
} else {
mCancelTv.setText("搜索");
}
}
});
mCancelTv.setOnClickListener(view -> mScrollLayout.scrollToOpen());
iniTypeView();
}
@SuppressLint("ClickableViewAccessibility")
private void initScrollLayout() {
mScrollLayout.setOnScrollChangedListener(new ScrollLayout.OnScrollChangedListener() {
@Override
public void onScrollProgressChanged(float currentProgress) {
if (currentProgress >= 0) {
float precent = 255 * currentProgress;
if (precent > 255) {
precent = 255;
} else if (precent < 0) {
precent = 0;
}
mScrollLayout.getBackground().setAlpha(255 - (int) precent);
}
}
@Override
public void onScrollFinished(ScrollLayout.Status currentStatus) {
currentState = currentStatus;
if (currentStatus.equals(ScrollLayout.Status.OPENED)) {
//暂时先拦截触摸事件防止事件穿透
showAllView();
mScrollLayout.setOnTouchListener((v, event) -> false);
mIndicatorIv.setImageResource(R.drawable.icon_search_line);
mCancelTv.setVisibility(View.GONE);
mEmptyLayout.setVisibility(GONE);
KeyboardUtil.hideKeyboard(mSearchEt);
} else if (currentStatus.equals(ScrollLayout.Status.CLOSED)) {
//暂时先拦截触摸事件防止事件穿透
hideAllView();
mScrollLayout.setOnTouchListener((v, event) -> true);
mIndicatorIv.setImageResource(R.drawable.icon_search_down);
mCancelTv.setVisibility(View.VISIBLE);
mEmptyLayout.setVisibility(View.VISIBLE);
KeyboardUtil.openKeybord(mSearchEt, mContext);
mSearchEt.requestFocus();
mSearchEt.setFocusableInTouchMode(true);
mSearchEt.setFocusable(true);
} else if (currentStatus.equals(ScrollLayout.Status.EXIT)) {
//暂时先拦截触摸事件防止事件穿透
mScrollLayout.setOnTouchListener((v, event) -> false);
mIndicatorIv.setImageResource(R.drawable.icon_search_up);
mCancelTv.setVisibility(View.GONE);
mEmptyLayout.setVisibility(GONE);
KeyboardUtil.hideKeyboard(mSearchEt);
}
}
@Override
public void onChildScroll(int top) {
private void iniTypeView() {
}
mPoiTv.setOnClickListener(view -> {
currentSpinnerType = 0;
mTypeResultTv.setText("POI");
mSearchTypeLayout.setVisibility(View.GONE);
});
mDwTv.setOnClickListener(view -> {
currentSpinnerType = 1;
mTypeResultTv.setText("实有单位");
mSearchTypeLayout.setVisibility(View.GONE);
});
mFwTv.setOnClickListener(view -> {
currentSpinnerType = 2;
mTypeResultTv.setText("实有房屋");
mSearchTypeLayout.setVisibility(View.GONE);
});
mDzTv.setOnClickListener(view -> {
currentSpinnerType = 3;
mTypeResultTv.setText("标准地址");
mSearchTypeLayout.setVisibility(View.GONE);
});
mScrollLayout.getBackground().setAlpha(0);
}
protected void setSearchSelectedListener(ISearchSelectedListener listener){
public void setSearchSelectedListener(ISearchSelectedListener listener) {
this.searchSelectedListener = listener;
}
......@@ -305,6 +348,30 @@ public class ArcGisSearchView extends LinearLayout {
}
}
/**
* @param type 搜索类型:0:poi,1:实有单位,2:实有房屋,3:标准地址
* @param keyWord 关键字
*/
public void setSearchData(int type, String keyWord) {
if (type > 3 || type < 0) {
Toast.makeText(mContext, "搜索类型错误,请检查类型设置", Toast.LENGTH_LONG).show();
return;
}
if (TextUtils.isEmpty(keyWord)) {
Toast.makeText(mContext, "请设置搜索关键字", Toast.LENGTH_LONG).show();
return;
}
currentSpinnerType = type;
mCancelTv.setVisibility(VISIBLE);
mCancelTv.setText("搜索");
mSearchEt.setText(keyWord);
mSearchEt.setSelection(keyWord.length());
searchPopupLayout.show(PopupLayout.POSITION_BOTTOM);
doSearchByKeyWord(keyWord);
}
@SuppressLint("HandlerLeak")
Handler mHandler = new Handler() {
@Override
......@@ -312,12 +379,13 @@ public class ArcGisSearchView extends LinearLayout {
super.handleMessage(msg);
switch (msg.what) {
case HANDLE_MSG_NO_DATA:
resultList.clear();
mEmptyLayout.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.GONE);
resultList.clear();
mAdapter.notifyDataSetChanged();
break;
case HANDLE_MSG_HAS_DATA:
resultList.clear();
mEmptyLayout.setVisibility(View.GONE);
mRecyclerView.setVisibility(View.VISIBLE);
resultList.addAll((List<SearchModel>) msg.obj);
......@@ -330,24 +398,55 @@ public class ArcGisSearchView extends LinearLayout {
};
private void doSearchByKeyWord(String keyWord) {
if (!ToolUtil.isNetWorkAvailable(mContext)) {
Toast.makeText(mContext, mContext.getString(R.string.string_net), Toast.LENGTH_LONG).show();
return;
}
if (TextUtils.isEmpty(keyWord)) {
mHandler.sendEmptyMessage(HANDLE_MSG_NO_DATA);
return;
}
KeyboardUtil.hideKeyboard(mSearchEt);
showDialog();
switch (currentSpinnerType) {
case 0://poi
requestPOIData(keyWord);
break;
case 1://实有单位
requestDwData(keyWord);
break;
case 2://实有房屋
requestFwData(keyWord);
break;
case 3://标准地址
requestDzData(keyWord);
break;
}
}
/**
* @param keyWord poi
*/
private void requestPOIData(String keyWord) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("poiname", keyWord);
} catch (JSONException e) {
e.printStackTrace();
}
String jsonParams = new Gson().toJson(jsonObject);
String jsonParams = jsonObject.toString();
OkHttp3Utils.doPost(Constants.BASE_SEARCH_URL, jsonParams, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
disDialog();
Toast.makeText(mContext, "请求失败,请重试", Toast.LENGTH_LONG).show();
// Toast.makeText(mContext, "请求失败,请重试", Toast.LENGTH_LONG).show();
Log.e(TAG, "e=" + e.toString());
}
......@@ -361,8 +460,8 @@ public class ArcGisSearchView extends LinearLayout {
int status = jsonObject.get("status").getAsInt();
if (status == 200) {
JsonArray dataArray = jsonObject.get("data").getAsJsonArray();
if(dataArray !=null && dataArray.size() > 0){
List<SearchModel> searchModelList = new ArrayList<>();
if (dataArray != null && dataArray.size() > 0) {
List<SearchModel> searchModelList = new LinkedList<>();
for (int i = 0; i < dataArray.size(); i++) {
JsonObject jsonObject1 = (JsonObject) dataArray.get(i);
SearchModel searchModel = new SearchModel();
......@@ -382,11 +481,11 @@ public class ArcGisSearchView extends LinearLayout {
mHandler.sendEmptyMessage(HANDLE_MSG_NO_DATA);
}
}else{
} else {
mHandler.sendEmptyMessage(HANDLE_MSG_NO_DATA);
}
}else{
} else {
mHandler.sendEmptyMessage(HANDLE_MSG_NO_DATA);
}
......@@ -400,6 +499,173 @@ public class ArcGisSearchView extends LinearLayout {
});
}
/**
* @param keyWord 单位
*/
private void requestDwData(String keyWord) {
OkHttp3Utils.doPost(Constants.BASE_DW_URL, Objects.requireNonNull(ToolUtil.dongGuanSearchParams(keyWord)), new Callback() {
@Override
public void onFailure(Call call, IOException e) {
disDialog();
// Toast.makeText(mContext, "请求失败,请重试", Toast.LENGTH_LONG).show();
Log.e("Fail", "e=" + e.toString());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
disDialog();
if (response.isSuccessful()) {
if (response.body() != null) {
String responseStr = response.body().string();
Log.e("responseStr", responseStr);
JsonObject jsonObject = GsonUtil.gsonToBean(responseStr, JsonObject.class);
int status = jsonObject.get("status").getAsInt();
if (status == 200) {
JsonArray dataArray = jsonObject.get("data").getAsJsonArray();
if (dataArray != null && dataArray.size() > 0) {
List<SearchModel> searchModelList = new ArrayList<>();
for (int i = 0; i < dataArray.size(); i++) {
JsonObject jsonObject1 = (JsonObject) dataArray.get(i);
SearchModel searchModel = new SearchModel();
searchModel.setX(jsonObject1.get("x").getAsDouble());
searchModel.setY(jsonObject1.get("y").getAsDouble());
searchModel.setPoiaddress(jsonObject1.get("dzqc").getAsString());
searchModel.setPoiname(jsonObject1.get("dwcszpmc").getAsString());
searchModelList.add(searchModel);
}
if (searchModelList.size() > 0) {
Message message = new Message();
message.what = HANDLE_MSG_HAS_DATA;
message.obj = searchModelList;
mHandler.sendMessage(message);
} else {
mHandler.sendEmptyMessage(HANDLE_MSG_NO_DATA);
}
} else {
mHandler.sendEmptyMessage(HANDLE_MSG_NO_DATA);
}
}
}
}
}
});
}
/**
* @param keyWord 房屋
*/
private void requestFwData(String keyWord) {
OkHttp3Utils.doPost(Constants.BASE_FW_URL, Objects.requireNonNull(ToolUtil.dongGuanSearchParams(keyWord)), new Callback() {
@Override
public void onFailure(Call call, IOException e) {
disDialog();
// Toast.makeText(mContext, "请求失败,请重试", Toast.LENGTH_LONG).show();
Log.e("Fail", "e=" + e.toString());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
disDialog();
if (response.isSuccessful()) {
if (response.body() != null) {
String responseStr = response.body().string();
Log.e("responseStr", responseStr);
JsonObject jsonObject = GsonUtil.gsonToBean(responseStr, JsonObject.class);
int status = jsonObject.get("status").getAsInt();
if (status == 200) {
JsonArray dataArray = jsonObject.get("data").getAsJsonArray();
if (dataArray != null && dataArray.size() > 0) {
List<SearchModel> searchModelList = new ArrayList<>();
for (int i = 0; i < dataArray.size(); i++) {
JsonObject jsonObject1 = (JsonObject) dataArray.get(i);
SearchModel searchModel = new SearchModel();
searchModel.setX(jsonObject1.get("x").getAsDouble());
searchModel.setY(jsonObject1.get("y").getAsDouble());
searchModel.setPoiaddress(jsonObject1.get("dzqc").getAsString());
searchModel.setPoiname(jsonObject1.get("fwmc").getAsString());
searchModelList.add(searchModel);
}
if (searchModelList.size() > 0) {
Message message = new Message();
message.what = HANDLE_MSG_HAS_DATA;
message.obj = searchModelList;
mHandler.sendMessage(message);
} else {
mHandler.sendEmptyMessage(HANDLE_MSG_NO_DATA);
}
} else {
mHandler.sendEmptyMessage(HANDLE_MSG_NO_DATA);
}
}
}
}
}
});
}
/**
* @param keyWord 地址
*/
private void requestDzData(String keyWord) {
OkHttp3Utils.doPost(Constants.BASE_DZ_URL, Objects.requireNonNull(ToolUtil.dongGuanSearchParams(keyWord)), new Callback() {
@Override
public void onFailure(Call call, IOException e) {
disDialog();
// Toast.makeText(mContext, "请求失败,请重试", Toast.LENGTH_LONG).show();
Log.e("Fail", "e=" + e.toString());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
disDialog();
if (response.isSuccessful()) {
if (response.body() != null) {
String responseStr = response.body().string();
Log.e("responseStr", responseStr);
JsonObject jsonObject = GsonUtil.gsonToBean(responseStr, JsonObject.class);
int status = jsonObject.get("status").getAsInt();
if (status == 200) {
JsonArray dataArray = jsonObject.get("data").getAsJsonArray();
if (dataArray != null && dataArray.size() > 0) {
List<SearchModel> searchModelList = new ArrayList<>();
for (int i = 0; i < dataArray.size(); i++) {
JsonObject jsonObject1 = (JsonObject) dataArray.get(i);
SearchModel searchModel = new SearchModel();
searchModel.setX(jsonObject1.get("x").getAsDouble());
searchModel.setY(jsonObject1.get("y").getAsDouble());
searchModel.setPoiaddress(jsonObject1.get("dzqc").getAsString());
searchModel.setPoiname(jsonObject1.get("dzxz").getAsString());
searchModelList.add(searchModel);
}
if (searchModelList.size() > 0) {
Message message = new Message();
message.what = HANDLE_MSG_HAS_DATA;
message.obj = searchModelList;
mHandler.sendMessage(message);
} else {
mHandler.sendEmptyMessage(HANDLE_MSG_NO_DATA);
}
} else {
mHandler.sendEmptyMessage(HANDLE_MSG_NO_DATA);
}
}
}
}
}
});
}
private void showAllView() {
if (ArcGisNaviView.instance != null) {
ArcGisNaviView.instance.mNaviIv.setVisibility(View.VISIBLE);
......@@ -428,6 +694,81 @@ public class ArcGisSearchView extends LinearLayout {
}
}
/**
* 禁止输入框复制粘贴菜单
*/
@SuppressLint("ClickableViewAccessibility")
private void disableCopyAndPaste(final EditText editText) {
try {
if (editText == null) {
return;
}
editText.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return true;
}
});
editText.setLongClickable(false);
editText.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// setInsertionDisabled when user touches the view
setInsertionDisabled(editText);
editText.requestFocus();
editText.setFocusableInTouchMode(true);
editText.setFocusable(true);
}
return false;
});
editText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
private void setInsertionDisabled(EditText editText) {
try {
Field editorField = TextView.class.getDeclaredField("mEditor");
editorField.setAccessible(true);
Object editorObject = editorField.get(editText);
// if this view supports insertion handles
Class editorClass = Class.forName("android.widget.Editor");
Field mInsertionControllerEnabledField = editorClass.getDeclaredField("mInsertionControllerEnabled");
mInsertionControllerEnabledField.setAccessible(true);
mInsertionControllerEnabledField.set(editorObject, false);
// if this view supports selection handles
Field mSelectionControllerEnabledField = editorClass.getDeclaredField("mSelectionControllerEnabled");
mSelectionControllerEnabledField.setAccessible(true);
mSelectionControllerEnabledField.set(editorObject, false);
} catch (Exception e) {
e.printStackTrace();
}
}
class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.VH> {
......@@ -444,15 +785,22 @@ public class ArcGisSearchView extends LinearLayout {
holder.desc.setText(mDatas.get(position).getPoiaddress());
holder.itemView.setOnClickListener(v -> {
//item 点击事件
mScrollLayout.scrollToOpen();
KeyboardUtil.hideKeyboard(mSearchEt);
switch (currSearchType){
searchPopupLayout.dismiss();
if(TextUtils.isEmpty(mSearchEt.getText().toString())){
mSearchResultTv.setText("");
}else{
mSearchResultTv.setText(mDatas.get(position).getPoiname());
}
switch (currSearchType) {
case SEARCH:
arcGisLocationView.setSearchLocation(mDatas.get(position).getX(), mDatas.get(position).getY(), currSearchType);
if (searchSelectedListener != null) {
searchSelectedListener.selectedResult(mDatas.get(position));
}
break;
case START_ADDRESS_SEARCH:
case END_ADDRESS_SEARCH:
if(searchSelectedListener != null){
if (searchSelectedListener != null) {
searchSelectedListener.selectedResult(mDatas.get(position));
}
break;
......
......@@ -2,6 +2,9 @@ package cn.com.founder.arcgislib.widget.cluster;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import androidx.core.content.ContextCompat;
import com.esri.arcgisruntime.geometry.Envelope;
import com.esri.arcgisruntime.geometry.Geometry;
......@@ -9,10 +12,9 @@ import com.esri.arcgisruntime.geometry.Point;
import com.esri.arcgisruntime.geometry.Polygon;
import com.esri.arcgisruntime.mapping.view.Graphic;
import com.esri.arcgisruntime.mapping.view.GraphicsOverlay;
import com.esri.arcgisruntime.mapping.view.MapScaleChangedEvent;
import com.esri.arcgisruntime.mapping.view.MapScaleChangedListener;
import com.esri.arcgisruntime.mapping.view.MapView;
import com.esri.arcgisruntime.symbology.CompositeSymbol;
import com.esri.arcgisruntime.symbology.PictureMarkerSymbol;
import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol;
import com.esri.arcgisruntime.symbology.Symbol;
import com.esri.arcgisruntime.symbology.TextSymbol;
......@@ -22,6 +24,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cn.com.founder.arcgislib.view.ArcGisClusterView;
/**
* 模拟聚合
*/
......@@ -45,8 +49,12 @@ public class ClusterLayer {
ArrayList<Graphic> _clusterGraphics = new ArrayList<Graphic>();
private PictureMarkerSymbol defaultPointImageSymbol;
private SimpleMarkerSymbol defaultClusterCircleSymbol;
private ArcGisClusterView.ClusterStyleBuilder clusterStyleBuilder;
public ClusterLayer(final MapView mapView, GraphicsOverlay GraphicsOverlay,
Context context) {
Context context, ArcGisClusterView.ClusterStyleBuilder clusterStyleBuilder) {
if (mapView == null || GraphicsOverlay == null) {
return;
}
......@@ -58,20 +66,31 @@ public class ClusterLayer {
this._clusterGraphicsOverlay = new GraphicsOverlay();
this._mapView.getGraphicsOverlays().add(this._clusterGraphicsOverlay);
this._context = context;
this.clusterStyleBuilder = clusterStyleBuilder;
defaultClusterCircleSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.Style.CIRCLE,
clusterStyleBuilder.getmClusterCircleBg(), clusterStyleBuilder.getmClusterCircleSize());
BitmapDrawable bitmapDrawableNormal = (BitmapDrawable) ContextCompat
.getDrawable(_context, clusterStyleBuilder.getmDefaultExpandImage());
try {
defaultPointImageSymbol = PictureMarkerSymbol.createAsync(bitmapDrawableNormal).get();
} catch (Exception e) {
e.printStackTrace();
}
this._clusterGraphics();
mapView.addMapScaleChangedListener(new MapScaleChangedListener() {
@Override
public void mapScaleChanged(MapScaleChangedEvent mapScaleChangedEvent) {
if (!mapView.isNavigating()) {
_clusterResolution = _getExtent(_mapView.getVisibleArea())
.getWidth() / _mapView.getWidth();
_clusterData.clear();
_clusterGraphics.clear();
_clusterGraphicsOverlay.getGraphics().clear();
_clusterGraphics();
}
mapView.addMapScaleChangedListener(mapScaleChangedEvent -> {
if (!mapView.isNavigating()) {
_clusterResolution = _getExtent(_mapView.getVisibleArea())
.getWidth() / _mapView.getWidth();
_clusterData.clear();
_clusterGraphics.clear();
_clusterGraphicsOverlay.getGraphics().clear();
_clusterGraphics();
}
});
}
......@@ -104,8 +123,7 @@ public class ClusterLayer {
public ArrayList<Graphic> getGraphicsByClusterID(int id) {
ArrayList<Graphic> graphics = new ArrayList<>();
for (Graphic gra : this._clusterGraphics
) {
for (Graphic gra : this._clusterGraphics) {
if (Integer.valueOf(gra.getAttributes().get("clusterID").toString()) == id) {
graphics.add(gra);
}
......@@ -231,17 +249,21 @@ public class ClusterLayer {
private Symbol createClusterSymbol(Map<String, Object> cluster) {
int count = (Integer) cluster.get("count");
if (count == 1) {
return markerSymbol;
return defaultPointImageSymbol != null ? defaultPointImageSymbol : markerSymbol;
} else if (count > 1) {
List<Symbol> symbols = new ArrayList<>();
if (count <= 10) {
symbols.add(markerSymbolS);
} else if (count > 10 && count <= 20) {
symbols.add(markerSymbolM);
} else if (count > 20) {
symbols.add(markerSymbolL);
}
TextSymbol textSymbol = new TextSymbol(18, count + "", Color.WHITE,
symbols.add(defaultClusterCircleSymbol);
// if (count <= 10) {
// symbols.add(markerSymbolS);
// } else if (count > 10 && count <= 20) {
// symbols.add(markerSymbolM);
// } else if (count > 20) {
// symbols.add(markerSymbolL);
// }
TextSymbol textSymbol = new TextSymbol(clusterStyleBuilder.getmClusterTextSize(), count + "", clusterStyleBuilder.getmClusterTextColor(),
TextSymbol.HorizontalAlignment.CENTER,
TextSymbol.VerticalAlignment.MIDDLE);
symbols.add(textSymbol);
......@@ -252,6 +274,7 @@ public class ClusterLayer {
return null;
}
SimpleMarkerSymbol markerSymbolL = new SimpleMarkerSymbol(SimpleMarkerSymbol.Style.CIRCLE,
Color.RED, 36);
SimpleMarkerSymbol markerSymbolM = new SimpleMarkerSymbol(SimpleMarkerSymbol.Style.CIRCLE,
......@@ -264,4 +287,6 @@ public class ClusterLayer {
private Envelope _getExtent(Polygon polygon) {
return polygon.getExtent();
}
}
......@@ -5,8 +5,6 @@ import android.content.DialogInterface;
import android.view.Gravity;
import android.view.View;
import androidx.annotation.LayoutRes;
/**
* Copyright: 方正国际软件有限公司
* Author:luo_shaopeng
......@@ -15,7 +13,7 @@ import androidx.annotation.LayoutRes;
* Description:类似popup的dialog--辅助类
*/
public class PopupLayout {
private static PopupDialog mPopupDialog;//内部使用的Dialog
private PopupDialog mPopupDialog;//内部使用的Dialog
private static DismissListener mDismissListener;//监听弹出窗口的消失事件
public static int POSITION_LEFT= Gravity.LEFT;//从最左侧弹出
......@@ -24,33 +22,37 @@ public class PopupLayout {
public static int POSITION_TOP= Gravity.TOP;//从顶部弹出
public static int POSITION_BOTTOM= Gravity.BOTTOM;//从底部弹出
private PopupLayout(){}
/**
* 初始化PopLayout
* @param context
* @param contentLayoutId 内容布局Id
*/
public static PopupLayout init(Context context, @LayoutRes int contentLayoutId){
PopupLayout popupLayout=new PopupLayout();
mPopupDialog=new PopupDialog(context);
mPopupDialog.setContentLayout(contentLayoutId);
popupLayout.initListener();
return popupLayout;
}
/**
* 初始化PopLayout
* @param context
* @param contentView 内容布局
*/
public static PopupLayout init(Context context, View contentView){
PopupLayout popupLayout=new PopupLayout();
public PopupLayout(Context context, View contentView){
mPopupDialog=new PopupDialog(context);
mPopupDialog.setContentLayout(contentView);
popupLayout.initListener();
return popupLayout;
}
initListener();
}
// /**
// * 初始化PopLayout
// * @param context
// * @param contentLayoutId 内容布局Id
// */
// public PopupLayout init(Context context, @LayoutRes int contentLayoutId){
// PopupLayout popupLayout=new PopupLayout();
// mPopupDialog=new PopupDialog(context);
// mPopupDialog.setContentLayout(contentLayoutId);
// popupLayout.initListener();
// return popupLayout;
// }
//
// /**
// * 初始化PopLayout
// * @param context
// * @param contentView 内容布局
// */
// public PopupLayout init(Context context, View contentView){
// PopupLayout popupLayout=new PopupLayout();
// mPopupDialog=new PopupDialog(context);
// mPopupDialog.setContentLayout(contentView);
// initListener();
// return popupLayout;
// }
//初始化Dialog监听器
private void initListener(){
......
/*
*
* * sufly0001@gmail.com Modify the code to enhance the ease of use.
* *
* * Copyright (C) 2015 Ted xiong-wei@hotmail.com
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*
*/
package cn.com.founder.arcgislib.widget.scrolllayout;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.FrameLayout;
import android.widget.Scroller;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import cn.com.founder.arcgislib.R;
import cn.com.founder.arcgislib.widget.scrolllayout.content.ContentScrollView;
/**
* Layout that can scroll down to a max offset and can tell the scroll progress by
* OnScrollProgressListener.
*/
public class ScrollLayout extends FrameLayout {
private static final int MAX_SCROLL_DURATION = 400;
private static final int MIN_SCROLL_DURATION = 100;
private static final int FLING_VELOCITY_SLOP = 80;
private static final float DRAG_SPEED_MULTIPLIER = 1.2f;
private static final int DRAG_SPEED_SLOP = 30;
private static final int MOTION_DISTANCE_SLOP = 10;
private static final float SCROLL_TO_CLOSE_OFFSET_FACTOR = 0.5f;
private static final float SCROLL_TO_EXIT_OFFSET_FACTOR = 0.8f;
private final GestureDetector.OnGestureListener gestureListener =
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (velocityY > FLING_VELOCITY_SLOP) {
if (lastFlingStatus.equals(Status.OPENED) && -getScrollY() > maxOffset) {
lastFlingStatus = Status.EXIT;
scrollToExit();
} else {
scrollToOpen();
lastFlingStatus = Status.OPENED;
}
return true;
} else if (velocityY < FLING_VELOCITY_SLOP && getScrollY() <= -maxOffset) {
scrollToOpen();
lastFlingStatus = Status.OPENED;
return true;
} else if (velocityY < FLING_VELOCITY_SLOP && getScrollY() > -maxOffset) {
scrollToClose();
lastFlingStatus = Status.CLOSED;
return true;
}
return false;
}
};
private final AbsListView.OnScrollListener associatedListViewListener =
new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
updateListViewScrollState(view);
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
updateListViewScrollState(view);
}
};
private final RecyclerView.OnScrollListener associatedRecyclerViewListener =
new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
updateRecyclerViewScrollState(recyclerView);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
updateRecyclerViewScrollState(recyclerView);
}
};
private float lastX;
private float lastY;
private float lastDownX;
private float lastDownY;
private Status lastFlingStatus = Status.CLOSED;
private Scroller scroller;
private GestureDetector gestureDetector;
private boolean isEnable = true;
private boolean isSupportExit = false;
private boolean isAllowHorizontalScroll = true;
private boolean isDraggable = true;
private boolean isAllowPointerIntercepted = true;
private boolean isCurrentPointerIntercepted = false;
private InnerStatus currentInnerStatus = InnerStatus.OPENED;
private int maxOffset = 0;
public int minOffset = 0;
private int exitOffset = 0;
private OnScrollChangedListener onScrollChangedListener;
private ContentScrollView mScrollView;
public ScrollLayout(Context context) {
super(context);
}
public ScrollLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initFromAttributes(context, attrs);
}
public ScrollLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initFromAttributes(context, attrs);
}
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
scroller = new Scroller(getContext(), null, true);
} else {
scroller = new Scroller(getContext());
}
gestureDetector = new GestureDetector(getContext(), gestureListener);
}
private void initFromAttributes(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.ScrollLayout);
if (a.hasValue(R.styleable.ScrollLayout_maxOffset)) {
int maxset = a.getDimensionPixelOffset(R.styleable.ScrollLayout_maxOffset, maxOffset);
if (maxset != getScreenHeight()) {
maxOffset = getScreenHeight() - maxset;
}
}
if (a.hasValue(R.styleable.ScrollLayout_minOffset))
minOffset = a.getDimensionPixelOffset(R.styleable.ScrollLayout_minOffset, minOffset);
if (a.hasValue(R.styleable.ScrollLayout_exitOffset)) {
int exitset = a.getDimensionPixelOffset(R.styleable.ScrollLayout_exitOffset, getScreenHeight());
if (exitset != getScreenHeight()) {
exitOffset = getScreenHeight() - exitset;
}
}
if (a.hasValue(R.styleable.ScrollLayout_allowHorizontalScroll))
isAllowHorizontalScroll = a.getBoolean(R.styleable.ScrollLayout_allowHorizontalScroll, true);
if (a.hasValue(R.styleable.ScrollLayout_isSupportExit))
isSupportExit = a.getBoolean(R.styleable.ScrollLayout_isSupportExit, true);
if (a.hasValue(R.styleable.ScrollLayout_mode)) {
int mode = a.getInteger(R.styleable.ScrollLayout_mode, 0);
switch (mode) {
case 0x0:
setToOpen();
break;
case 0x1:
setToClosed();
break;
case 0x2:
setToExit();
break;
default:
setToClosed();
break;
}
}
a.recycle();
}
private ContentScrollView.OnScrollChangedListener mOnScrollChangedListener = new ContentScrollView.OnScrollChangedListener() {
@Override
public void onScrollChanged(int l, int t, int oldL, int oldT) {
if (null == mScrollView) return;
if (null != onScrollChangedListener)
onScrollChangedListener.onChildScroll(oldT);
if (mScrollView.getScrollY() == 0) {
setDraggable(true);
} else {
setDraggable(false);
}
}
};
/**
* Set the scrolled position of your view. This will cause a call to
* {@link #onScrollChanged(int, int, int, int)} and the view will be
* invalidated.
*
* @param x the x position to scroll to
* @param y the y position to scroll to
*/
@Override
public void scrollTo(int x, int y) {
super.scrollTo(x, y);
if (maxOffset == minOffset) {
return;
}
//only from min to max or from max to min,send progress out. not exit
if (-y <= maxOffset) {
float progress = (float) (-y - minOffset) / (maxOffset - minOffset);
onScrollProgressChanged(progress);
} else {
float progress = (float) (-y - maxOffset) / (maxOffset - exitOffset);
onScrollProgressChanged(progress);
}
if (y == -minOffset) {
// closed
if (currentInnerStatus != InnerStatus.CLOSED) {
currentInnerStatus = InnerStatus.CLOSED;
onScrollFinished(Status.CLOSED);
}
} else if (y == -maxOffset) {
// opened
if (currentInnerStatus != InnerStatus.OPENED) {
currentInnerStatus = InnerStatus.OPENED;
onScrollFinished(Status.OPENED);
}
} else if (isSupportExit && y == -exitOffset) {
// exited
if (currentInnerStatus != InnerStatus.EXIT) {
currentInnerStatus = InnerStatus.EXIT;
onScrollFinished(Status.EXIT);
}
}
}
private void onScrollFinished(Status status) {
if (onScrollChangedListener != null) {
onScrollChangedListener.onScrollFinished(status);
}
}
private void onScrollProgressChanged(float progress) {
if (onScrollChangedListener != null) {
onScrollChangedListener.onScrollProgressChanged(progress);
}
}
@Override
public void computeScroll() {
if (!scroller.isFinished() && scroller.computeScrollOffset()) {
int currY = scroller.getCurrY();
scrollTo(0, currY);
if (currY == -minOffset || currY == -maxOffset || (isSupportExit && currY == -exitOffset)) {
scroller.abortAnimation();
} else {
invalidate();
}
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!isEnable) {
return false;
}
if (!isDraggable && currentInnerStatus == InnerStatus.CLOSED) {
return false;
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = ev.getX();
lastY = ev.getY();
lastDownX = lastX;
lastDownY = lastY;
isAllowPointerIntercepted = true;
isCurrentPointerIntercepted = false;
if (!scroller.isFinished()) {
scroller.forceFinished(true);
currentInnerStatus = InnerStatus.MOVING;
isCurrentPointerIntercepted = true;
return true;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
isAllowPointerIntercepted = true;
isCurrentPointerIntercepted = false;
if (currentInnerStatus == InnerStatus.MOVING) {
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (!isAllowPointerIntercepted) {
return false;
}
if (isCurrentPointerIntercepted) {
return true;
}
int deltaY = (int) (ev.getY() - lastDownY);
int deltaX = (int) (ev.getX() - lastDownX);
if (Math.abs(deltaY) < MOTION_DISTANCE_SLOP) {
return false;
}
if (Math.abs(deltaY) < Math.abs(deltaX)) {
// horizontal event
if (isAllowHorizontalScroll) {
isAllowPointerIntercepted = false;
isCurrentPointerIntercepted = false;
return false;
}
}
if (currentInnerStatus == InnerStatus.CLOSED) {
// when closed, only handle downwards motion event
if (deltaY < 0) {
// upwards
return false;
}
} else if (currentInnerStatus == InnerStatus.OPENED && !isSupportExit) {
// when opened, only handle upwards motion event
if (deltaY > 0) {
// downwards
return false;
}
}
isCurrentPointerIntercepted = true;
return true;
default:
return false;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isCurrentPointerIntercepted) {
return false;
}
gestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = event.getY();
return true;
case MotionEvent.ACTION_MOVE:
int deltaY = (int) ((event.getY() - lastY) * DRAG_SPEED_MULTIPLIER);
deltaY = (int) (Math.signum(deltaY)) * Math.min(Math.abs(deltaY), DRAG_SPEED_SLOP);
if (disposeEdgeValue(deltaY)) {
return true;
}
currentInnerStatus = InnerStatus.MOVING;
int toScrollY = getScrollY() - deltaY;
if (toScrollY >= -minOffset) {
scrollTo(0, -minOffset);
} else if (toScrollY <= -maxOffset && !isSupportExit) {
scrollTo(0, -maxOffset);
} else {
scrollTo(0, toScrollY);
}
lastY = event.getY();
return true;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (currentInnerStatus == InnerStatus.MOVING) {
completeMove();
return true;
}
break;
default:
return false;
}
return false;
}
private boolean disposeEdgeValue(int deltaY) {
if (isSupportExit) {
if (deltaY <= 0 && getScrollY() >= -minOffset) {
return true;
} else if (deltaY >= 0 && getScrollY() <= -exitOffset) {
return true;
}
} else {
if (deltaY <= 0 && getScrollY() >= -minOffset) {
return true;
} else if (deltaY >= 0 && getScrollY() <= -maxOffset) {
return true;
}
}
return false;
}
private void completeMove() {
float closeValue = -((maxOffset - minOffset) * SCROLL_TO_CLOSE_OFFSET_FACTOR);
if (getScrollY() > closeValue) {
scrollToClose();
} else {
if (isSupportExit) {
float exitValue = -((exitOffset - maxOffset) * SCROLL_TO_EXIT_OFFSET_FACTOR + maxOffset);
if (getScrollY() <= closeValue && getScrollY() > exitValue) {
scrollToOpen();
} else {
scrollToExit();
}
} else {
scrollToOpen();
}
}
}
/**
* 滚动布局打开关闭,关闭否则滚动.
*/
public void showOrHide() {
if (currentInnerStatus == InnerStatus.OPENED) {
scrollToClose();
} else if (currentInnerStatus == InnerStatus.CLOSED) {
scrollToOpen();
}
}
/**
* 滚动布局开放,maxOffset之后向下滚动.
*/
public void scrollToOpen() {
if (currentInnerStatus == InnerStatus.OPENED) {
return;
}
if (maxOffset == minOffset) {
return;
}
int dy = -getScrollY() - maxOffset;
if (dy == 0) {
return;
}
currentInnerStatus = InnerStatus.SCROLLING;
int duration = MIN_SCROLL_DURATION
+ Math.abs((MAX_SCROLL_DURATION - MIN_SCROLL_DURATION) * dy / (maxOffset - minOffset));
scroller.startScroll(0, getScrollY(), 0, dy, duration);
invalidate();
}
/**
* 滚动的布局来关闭,滚动到minOffset.
*/
public void scrollToClose() {
if (currentInnerStatus == InnerStatus.CLOSED) {
return;
}
if (maxOffset == minOffset) {
return;
}
int dy = -getScrollY() - minOffset;
if (dy == 0) {
return;
}
currentInnerStatus = InnerStatus.SCROLLING;
int duration = MIN_SCROLL_DURATION
+ Math.abs((MAX_SCROLL_DURATION - MIN_SCROLL_DURATION) * dy / (maxOffset - minOffset));
scroller.startScroll(0, getScrollY(), 0, dy, duration);
invalidate();
}
/**
* 滚动布局退出
*/
public void scrollToExit() {
if (!isSupportExit) return;
if (currentInnerStatus == InnerStatus.EXIT) {
return;
}
if (exitOffset == maxOffset) {
return;
}
int dy = -getScrollY() - exitOffset;
if (dy == 0) {
return;
}
currentInnerStatus = InnerStatus.SCROLLING;
int duration = MIN_SCROLL_DURATION
+ Math.abs((MAX_SCROLL_DURATION - MIN_SCROLL_DURATION) * dy / (exitOffset - maxOffset));
scroller.startScroll(0, getScrollY(), 0, dy, duration);
invalidate();
}
/**
* 初始化布局开放,没有动画。
*/
public void setToOpen() {
scrollTo(0, -maxOffset);
currentInnerStatus = InnerStatus.OPENED;
lastFlingStatus = Status.OPENED;
}
/**
* 初始化布局关闭,没有动画。
*/
public void setToClosed() {
scrollTo(0, -minOffset);
currentInnerStatus = InnerStatus.CLOSED;
lastFlingStatus = Status.CLOSED;
}
/**
* 初始化布局,退出,没有动画。
*/
public void setToExit() {
if (!isSupportExit) return;
scrollTo(0, -exitOffset);
currentInnerStatus = InnerStatus.EXIT;
}
public void setMinOffset(int minOffset) {
this.minOffset = minOffset;
}
public void setMaxOffset(int maxOffset) {
this.maxOffset = getScreenHeight() - maxOffset;
}
public void setExitOffset(int exitOffset) {
this.exitOffset = getScreenHeight() - exitOffset;
}
public void setEnable(boolean enable) {
this.isEnable = enable;
}
public void setIsSupportExit(boolean isSupportExit) {
this.isSupportExit = isSupportExit;
}
public boolean isSupportExit() {
return isSupportExit;
}
public boolean isAllowHorizontalScroll() {
return isAllowHorizontalScroll;
}
public void setAllowHorizontalScroll(boolean isAllowed) {
isAllowHorizontalScroll = isAllowed;
}
public boolean isDraggable() {
return isDraggable;
}
public void setDraggable(boolean draggable) {
this.isDraggable = draggable;
}
public void setOnScrollChangedListener(OnScrollChangedListener listener) {
this.onScrollChangedListener = listener;
}
public Status getCurrentStatus() {
switch (currentInnerStatus) {
case CLOSED:
return Status.CLOSED;
case OPENED:
return Status.OPENED;
case EXIT:
return Status.EXIT;
default:
return Status.OPENED;
}
}
/**
* Set associated list view, then this layout will only be able to drag down when the list
* view is scrolled to top.
*
* @param listView
*/
public void setAssociatedListView(AbsListView listView) {
listView.setOnScrollListener(associatedListViewListener);
updateListViewScrollState(listView);
}
/**
* Set associated list view, then this layout will only be able to drag down when the list
* view is scrolled to top.
*
* @param recyclerView
*/
public void setAssociatedRecyclerView(RecyclerView recyclerView) {
recyclerView.addOnScrollListener(associatedRecyclerViewListener);
updateRecyclerViewScrollState(recyclerView);
}
private void updateListViewScrollState(AbsListView listView) {
if (listView.getChildCount() == 0) {
setDraggable(true);
} else {
if (listView.getFirstVisiblePosition() == 0) {
View firstChild = listView.getChildAt(0);
if (firstChild.getTop() == listView.getPaddingTop()) {
setDraggable(true);
return;
}
}
setDraggable(false);
}
}
private void updateRecyclerViewScrollState(RecyclerView recyclerView) {
if (recyclerView.getChildCount() == 0) {
setDraggable(true);
} else {
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
int[] i = new int[1];
if (layoutManager instanceof LinearLayoutManager || layoutManager instanceof GridLayoutManager) {
i[0] = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
i = null;
i = ((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(i);
}
if (i[0] == 0) {
View firstChild = recyclerView.getChildAt(0);
if (firstChild.getTop() == recyclerView.getPaddingTop()) {
setDraggable(true);
return;
}
}
setDraggable(false);
}
}
public void setAssociatedScrollView(ContentScrollView scrollView) {
this.mScrollView = scrollView;
this.mScrollView.setScrollbarFadingEnabled(false);
this.mScrollView.setOnScrollChangeListener(mOnScrollChangedListener);
}
private enum InnerStatus {
EXIT, OPENED, CLOSED, MOVING, SCROLLING
}
/**
* 获取屏幕内容高度
*
* @return
*/
public int getScreenHeight() {
DisplayMetrics dm = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(dm);
int result = 0;
int resourceId = getContext().getResources()
.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getContext().getResources().getDimensionPixelSize(resourceId);
}
int screenHeight = dm.heightPixels - result;
return screenHeight;
}
/**
* 表明Scrolllayout的状态,只可以打开或关闭。
*/
public static enum Status {
EXIT, OPENED, CLOSED
}
/**
* 注册这个Scrolllayout可以监控其滚动
*/
public interface OnScrollChangedListener {
/**
* 每次滚动改变值
*
* @param currentProgress 0 to 1, 1 to -1, 0 means close, 1 means open, -1 means exit.
*/
void onScrollProgressChanged(float currentProgress);
/**
* 滚动状态改变时调用的方法
*
* @param currentStatus the current status after change
*/
void onScrollFinished(Status currentStatus);
/***
* 滚动子视图
*
* @param top the child view scroll data
*/
void onChildScroll(int top);
}
}
/*
*
* * sufly0001@gmail.com Modify the code to enhance the ease of use.
* *
* * Copyright (C) 2015 Ted xiong-wei@hotmail.com
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*
*/
package cn.com.founder.arcgislib.widget.scrolllayout.content;
import android.content.Context;
import android.os.Looper;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.widget.AbsListView;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import cn.com.founder.arcgislib.widget.scrolllayout.ScrollLayout;
public class ContentListView extends ListView {
private final CompositeScrollListener compositeScrollListener =
new CompositeScrollListener();
private boolean showShadow = false;
private View shadowView;
public ContentListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ContentListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ContentListView(Context context) {
super(context);
}
{
super.setOnScrollListener(compositeScrollListener);
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
ViewGroup.LayoutParams layoutParams = getLayoutParams();
ViewParent parent = getParent();
while (parent != null) {
if (parent instanceof ScrollLayout) {
int height = ((ScrollLayout) parent).getMeasuredHeight() - ((ScrollLayout) parent).minOffset;
if (layoutParams.height == height) {
return;
} else {
layoutParams.height = height;
break;
}
}
parent = parent.getParent();
}
setLayoutParams(layoutParams);
}
});
}
/**
* 添加一个OnScrollListener,不会取代已添加OnScrollListener
* <p>
* <b>Make sure call this on UI thread</b>
* </p>
*
* @param listener the listener to add
*/
@Override
public void setOnScrollListener(final OnScrollListener listener) {
addOnScrollListener(listener);
}
/**
* 添加一个OnScrollListener,不会取代已添加OnScrollListener
* <p>
* <b>Make sure call this on UI thread</b>
* </p>
*
* @param listener the listener to add
*/
public void addOnScrollListener(final OnScrollListener listener) {
throwIfNotOnMainThread();
compositeScrollListener.addOnScrollListener(listener);
}
/**
* 删除前一个添加scrollListener,只会删除完全相同的对象
* <p>
* <b>Make sure call this on UI thread.</b>
* </p>
*
* @param listener the listener to remove
*/
public void removeOnScrollListener(final OnScrollListener listener) {
throwIfNotOnMainThread();
compositeScrollListener.removeOnScrollListener(listener);
}
/**
* 需要调用之前setOnScrollListener
*
* @param shadowView the shadow view
*/
public void setTopShadowView(View shadowView) {
if (shadowView == null) {
return;
}
this.shadowView = shadowView;
addOnScrollListener(new OnScrollListener() {
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
View firstChild = view.getChildAt(0);
if (firstChild != null) {
if (firstVisibleItem == 0 && firstChild.getTop() == 0) {
showShadow = false;
showTopShadow();
} else if (!showShadow) {
showShadow = true;
showTopShadow();
}
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
});
}
private void showTopShadow() {
if (shadowView == null || shadowView.getVisibility() == View.VISIBLE) {
return;
}
shadowView.setVisibility(View.VISIBLE);
}
private void hideTopShadow() {
if (shadowView == null || shadowView.getVisibility() == View.GONE) {
return;
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
ViewParent parent = getParent();
while (parent != null) {
if (parent instanceof ScrollLayout) {
((ScrollLayout) parent).setAssociatedListView(this);
break;
}
parent = parent.getParent();
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
private void throwIfNotOnMainThread() {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("Must be invoked from the main thread.");
}
}
private class CompositeScrollListener implements OnScrollListener {
private final List<OnScrollListener> scrollListenerList = new
ArrayList<OnScrollListener>();
public void addOnScrollListener(OnScrollListener listener) {
if (listener == null) {
return;
}
for (OnScrollListener scrollListener : scrollListenerList) {
if (listener == scrollListener) {
return;
}
}
scrollListenerList.add(listener);
}
public void removeOnScrollListener(OnScrollListener listener) {
if (listener == null) {
return;
}
Iterator<OnScrollListener> iterator = scrollListenerList.iterator();
while (iterator.hasNext()) {
OnScrollListener scrollListener = iterator.next();
if (listener == scrollListener) {
iterator.remove();
return;
}
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
List<OnScrollListener> listeners = new ArrayList<OnScrollListener>(scrollListenerList);
for (OnScrollListener listener : listeners) {
listener.onScrollStateChanged(view, scrollState);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
List<OnScrollListener> listeners = new ArrayList<OnScrollListener>(scrollListenerList);
for (OnScrollListener listener : listeners) {
listener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
}
}
}
package cn.com.founder.arcgislib.widget.scrolllayout.content;
import android.content.Context;
import android.os.Looper;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.widget.AbsListView;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import cn.com.founder.arcgislib.widget.scrolllayout.ScrollLayout;
public class ContentRecyclerView extends RecyclerView {
private final ContentRecyclerView.CompositeScrollListener compositeScrollListener =
new ContentRecyclerView.CompositeScrollListener();
public ContentRecyclerView(Context context) {
super(context);
}
public ContentRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public ContentRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
{
super.addOnScrollListener(compositeScrollListener);
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
ViewGroup.LayoutParams layoutParams = getLayoutParams();
ViewParent parent = getParent();
while (parent != null) {
if (parent instanceof ScrollLayout) {
int height = ((ScrollLayout) parent).getMeasuredHeight() - ((ScrollLayout) parent).minOffset;
if (layoutParams.height == height) {
return;
} else {
layoutParams.height = height;
break;
}
}
parent = parent.getParent();
}
setLayoutParams(layoutParams);
}
});
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
ViewParent parent = getParent();
while (parent != null) {
if (parent instanceof ScrollLayout) {
((ScrollLayout) parent).setAssociatedRecyclerView(this);
break;
}
parent = parent.getParent();
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
private void throwIfNotOnMainThread() {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("Must be invoked from the main thread.");
}
}
private class CompositeScrollListener extends OnScrollListener {
private final List<OnScrollListener> scrollListenerList = new
ArrayList<OnScrollListener>();
public void addOnScrollListener(RecyclerView.OnScrollListener listener) {
if (listener == null) {
return;
}
for (RecyclerView.OnScrollListener scrollListener : scrollListenerList) {
if (listener == scrollListener) {
return;
}
}
scrollListenerList.add(listener);
}
public void removeOnScrollListener(AbsListView.OnScrollListener listener) {
if (listener == null) {
return;
}
Iterator<OnScrollListener> iterator = scrollListenerList.iterator();
while (iterator.hasNext()) {
RecyclerView.OnScrollListener scrollListener = iterator.next();
if (listener == scrollListener) {
iterator.remove();
return;
}
}
}
@Override
public void onScrollStateChanged(RecyclerView view, int scrollState) {
List<OnScrollListener> listeners = new ArrayList<OnScrollListener>(scrollListenerList);
for (RecyclerView.OnScrollListener listener : listeners) {
listener.onScrollStateChanged(view, scrollState);
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
List<OnScrollListener> listeners = new ArrayList<OnScrollListener>(scrollListenerList);
for (RecyclerView.OnScrollListener listener : listeners) {
listener.onScrolled(recyclerView, dx, dy);
}
}
}
}
/*
*
* * sufly0001@gmail.com Modify the code to enhance the ease of use.
* *
* * Copyright (C) 2015 Ted xiong-wei@hotmail.com
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*
*/
package cn.com.founder.arcgislib.widget.scrolllayout.content;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewParent;
import android.widget.ScrollView;
import cn.com.founder.arcgislib.widget.scrolllayout.ScrollLayout;
public class ContentScrollView extends ScrollView {
public interface OnScrollChangedListener {
void onScrollChanged(int l, int t, int oldl, int oldt);
}
private OnScrollChangedListener listener;
public ContentScrollView(Context context) {
super(context);
}
public ContentScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ContentScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setOnScrollChangeListener(OnScrollChangedListener listener) {
this.listener = listener;
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
listener.onScrollChanged(l, t, oldl, oldt);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
ViewParent parent = this.getParent();
while (parent != null) {
if (parent instanceof ScrollLayout) {
((ScrollLayout) parent).setAssociatedScrollView(this);
break;
}
parent = parent.getParent();
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
ViewParent parent = this.getParent();
if (parent instanceof ScrollLayout) {
if (((ScrollLayout) parent).getCurrentStatus() == ScrollLayout.Status.OPENED)
return false;
}
return super.onTouchEvent(ev);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
style="@style/WrapContent.WidthMatchParent">
<cn.com.founder.arcgislib.widget.scrolllayout.ScrollLayout
android:id="@+id/search_scroll_layout"
style="@style/MatchParent"
android:background="#66000000"
app:exitOffset="100dp"
app:isSupportExit="false"
app:maxOffset="100dp"
app:minOffset="100dp"
app:mode="open">
<RelativeLayout style="@style/MatchParent">
<LinearLayout
android:id="@+id/search_arrow_layout"
style="@style/WrapContent.WidthMatchParent"
android:orientation="vertical"
android:background="@color/colorWhite">
<ImageView
android:id="@+id/search_scroll_arrow_iv"
style="@style/WrapContent"
android:layout_gravity="center"
android:padding="@dimen/dimen_block_10"
android:src="@drawable/icon_search_line" />
</LinearLayout>
<cn.com.founder.arcgislib.widget.scrolllayout.content.ContentScrollView
style="@style/MatchParent"
android:layout_below="@+id/search_arrow_layout"
android:background="@color/colorWhite"
>
<LinearLayout
style="@style/MatchParent"
android:orientation="vertical"
android:focusable="true"
android:focusableInTouchMode="true"
>
<RelativeLayout style="@style/WrapContent.WidthMatchParent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen_block_20"
android:layout_marginLeft="@dimen/dimen_block_10"
android:layout_marginRight="@dimen/dimen_block_10"
android:background="@drawable/bg_white_stroke_gray_selector"
android:descendantFocusability="beforeDescendants"
android:gravity="center_vertical"
android:orientation="horizontal"
android:layout_toLeftOf="@+id/search_scroll_content_search_cancel_tv"
android:layout_centerVertical="true">
<ImageView
android:layout_width="20dip"
android:layout_height="20dip"
android:layout_marginLeft="@dimen/dimen_block_10"
android:layout_marginTop="2dip"
android:src="@drawable/icon_search" />
<EditText
android:id="@+id/search_scroll_content_search_et"
style="@style/WrapContent.WidthMatchParent"
android:textColor="@color/color_333333"
android:textSize="@dimen/dimen_font_16sp"
android:background="@null"
android:hint="@string/string_search_hint"
android:paddingLeft="@dimen/dimen_block_5"
android:paddingTop="@dimen/dimen_block_10"
android:paddingRight="@dimen/dimen_block_10"
android:paddingBottom="@dimen/dimen_block_10"
android:textColorHint="@color/color_CCCCCC"
android:imeOptions="actionSearch"
android:inputType="text"
android:textCursorDrawable="@drawable/bg_navi_et_cursor"
/>
</LinearLayout>
<TextView
android:id="@+id/search_scroll_content_search_cancel_tv"
style="@style/WrapContent.main_text_style"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="@string/string_common_cancel"
android:padding="@dimen/dimen_block_10"
android:layout_marginRight="@dimen/dimen_block_10"
android:visibility="gone"
/>
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/search_swipeRecyclerView"
style="@style/WrapContent.WidthMatchParent"
android:visibility="gone"
/>
<LinearLayout
android:id="@+id/search_empty"
style="@style/MatchParent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone"
>
<TextView
style="@style/WrapContent.main_text_style"
android:text="@string/string_common_nodata" />
</LinearLayout>
</LinearLayout>
</cn.com.founder.arcgislib.widget.scrolllayout.content.ContentScrollView>
</RelativeLayout>
</cn.com.founder.arcgislib.widget.scrolllayout.ScrollLayout>
</LinearLayout>
\ No newline at end of file
......@@ -28,7 +28,8 @@
<string name="string_navi_start_navi">开始导航</string>
<!--搜索-->
<string name="string_search_hint">请输入地点</string>
<string name="string_search_hint">请输入关键字</string>
<string name="string_search_prompt">请选择</string>
<!--热力图-->
<string name="string_hotpots_title">热力图</string>
<string name="string_hotpots_start_time">开始时间</string>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment