【FAQ】关于无法判断和区分用户与地图交互手势类型的解决办法

一. 问题描述

当用户通过缩放手势、平移手势、倾斜手势和旋转手势与地图交互,控制地图移动改变其可见区域时,华为地图SDK没有提供直接获取用户手势类型的API。

二. 解决方案

  1. 华为地图SDK的地图相机有提供CameraPosition类,此类包括所有相机位置参数,如位置、方位、倾斜角度和缩放级别。具体可以查看下图:

  1. 华为地图SDK同时也有提供地图相机的移动侦听事件,应用层可以通过设置侦听器对地图相机的移动状态进行侦听,比如地图相机开始移动、停止移动等事件。

  2. 如果要判断用户与地图的交互手势,可以在地图相机开始移动的侦听事件中分别记录target、bearing、tilt和zoom的初始值。在地图相机移动结束的侦听事件中重新获取target、bearing、tilt和zoom的最终值。

  3. 分别计算target、bearing、tilt和zoom的初始值与最终值是否有变动,来判断用户与地图的交互手势类型。

三. 代码示例及效果展示

  1. 创建地图实例并实现地图相机移动的侦听事件。

a. 在Activity的布局文件中添加地图控件且设置地图属性。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="@+id/mapfragment_camera_gesturetype"
class="com.huawei.hms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraTargetLat="48.893478"
map:cameraTargetLng="2.334595"
map:cameraZoom="10" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:map="http://schemas.android.com/apk/res-auto"
        android:id="@+id/mapfragment_camera_gesturetype"
        class="com.huawei.hms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        map:cameraTargetLat="48.893478"
        map:cameraTargetLng="2.334595"
        map:cameraZoom="10" />

</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment xmlns:android="http://schemas.android.com/apk/res/android" xmlns:map="http://schemas.android.com/apk/res-auto" android:id="@+id/mapfragment_camera_gesturetype" class="com.huawei.hms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent" map:cameraTargetLat="48.893478" map:cameraTargetLng="2.334595" map:cameraZoom="10" /> </androidx.constraintlayout.widget.ConstraintLayout>

b. 在Activity中初始化SDK、加载地图并实现地图相机的侦听事件。

public class HwMapCameraGestureTypeActivity extends AppCompatActivity implements OnMapReadyCallback,
HuaweiMap.OnCameraMoveStartedListener, HuaweiMap.OnCameraMoveListener, HuaweiMap.OnCameraIdleListener {
public static String LOG_TAG_MAP = "HW_MAP_LOG";
private SupportMapFragment mSupportMapFragment;
//HuaweiMap对象
private HuaweiMap huaweiMap;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 初始化SDK
MapsInitializer.initialize(this);
setContentView(R.layout.activity_hwmap_camera_gesturetype);
//加载地图
mSupportMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapfragment_camera_gesturetype);
mSupportMapFragment.getMapAsync(this);
}
//地图初始化成功的回调方法
@Override
public void onMapReady(HuaweiMap huaweiMap) {
this.huaweiMap = huaweiMap;
//设置地图相机的移动侦听事件
this.huaweiMap.setOnCameraMoveStartedListener(this);
this.huaweiMap.setOnCameraMoveListener(this);
this.huaweiMap.setOnCameraIdleListener(this);
}
//地图相机开始移动的回调
@Override
public void onCameraMoveStarted(int i) {
Log.w(LOG_TAG_MAP, "地图相机开始移动");
}
//地图相机移动过程中的回调
@Override
public void onCameraMove() {
}
//地图相机移动结束的回调
@Override
public void onCameraIdle() {
Log.w(LOG_TAG_MAP, "地图相机结束移动");
}
}
public class HwMapCameraGestureTypeActivity extends AppCompatActivity implements OnMapReadyCallback,
        HuaweiMap.OnCameraMoveStartedListener, HuaweiMap.OnCameraMoveListener, HuaweiMap.OnCameraIdleListener {
    public static String LOG_TAG_MAP = "HW_MAP_LOG";
    private SupportMapFragment mSupportMapFragment;
    //HuaweiMap对象
    private HuaweiMap huaweiMap;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 初始化SDK
        MapsInitializer.initialize(this);
        setContentView(R.layout.activity_hwmap_camera_gesturetype);
        //加载地图
        mSupportMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapfragment_camera_gesturetype);
        mSupportMapFragment.getMapAsync(this);
    }

    //地图初始化成功的回调方法
    @Override
    public void onMapReady(HuaweiMap huaweiMap) {
        this.huaweiMap = huaweiMap;
        //设置地图相机的移动侦听事件
        this.huaweiMap.setOnCameraMoveStartedListener(this);
        this.huaweiMap.setOnCameraMoveListener(this);
        this.huaweiMap.setOnCameraIdleListener(this);
    }

    //地图相机开始移动的回调
    @Override
    public void onCameraMoveStarted(int i) {
        Log.w(LOG_TAG_MAP, "地图相机开始移动");
    }

    //地图相机移动过程中的回调
    @Override
    public void onCameraMove() {

    }

    //地图相机移动结束的回调
    @Override
    public void onCameraIdle() {
        Log.w(LOG_TAG_MAP, "地图相机结束移动");
    }
}
public class HwMapCameraGestureTypeActivity extends AppCompatActivity implements OnMapReadyCallback, HuaweiMap.OnCameraMoveStartedListener, HuaweiMap.OnCameraMoveListener, HuaweiMap.OnCameraIdleListener { public static String LOG_TAG_MAP = "HW_MAP_LOG"; private SupportMapFragment mSupportMapFragment; //HuaweiMap对象 private HuaweiMap huaweiMap; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 初始化SDK MapsInitializer.initialize(this); setContentView(R.layout.activity_hwmap_camera_gesturetype); //加载地图 mSupportMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapfragment_camera_gesturetype); mSupportMapFragment.getMapAsync(this); } //地图初始化成功的回调方法 @Override public void onMapReady(HuaweiMap huaweiMap) { this.huaweiMap = huaweiMap; //设置地图相机的移动侦听事件 this.huaweiMap.setOnCameraMoveStartedListener(this); this.huaweiMap.setOnCameraMoveListener(this); this.huaweiMap.setOnCameraIdleListener(this); } //地图相机开始移动的回调 @Override public void onCameraMoveStarted(int i) { Log.w(LOG_TAG_MAP, "地图相机开始移动"); } //地图相机移动过程中的回调 @Override public void onCameraMove() { } //地图相机移动结束的回调 @Override public void onCameraIdle() { Log.w(LOG_TAG_MAP, "地图相机结束移动"); } }

c. 经下方的Gif图可看出,当地图相机开始移动和结束移动时,分别有对应的日志打印出来:

2.gif

2.gif
2. 新建initZoomValue, initTiltValue, initBearingValue对象,用来记录地图相机移动时的初始属性值,并在onCameraMoveStarted(int i)监听方法中对新建对象进行赋值:

/**
* 初始值对象
* initZoomValue-屏幕中心附近的缩放级别初始值。
* initTiltValue-相机角度与垂直于地球表面的线的夹角初始值。
* initBearingValue-相机指向的方向初始值。
*/
private float initZoomValue, initTiltValue, initBearingValue;
//地图相机开始移动的回调
@Override
public void onCameraMoveStarted(int i) {
Log.w(LOG_TAG_MAP, "地图相机开始移动");
if (null != huaweiMap && null != huaweiMap.getCameraPosition()) {
//记录相机移动时的相机各个属性的初始值
initZoomValue = huaweiMap.getCameraPosition().zoom;
initTiltValue = huaweiMap.getCameraPosition().tilt;
initBearingValue = huaweiMap.getCameraPosition().bearing;
}
}
/**
 * 初始值对象
 * initZoomValue-屏幕中心附近的缩放级别初始值。
 * initTiltValue-相机角度与垂直于地球表面的线的夹角初始值。
 * initBearingValue-相机指向的方向初始值。
 */
private float initZoomValue, initTiltValue, initBearingValue;

//地图相机开始移动的回调
@Override
public void onCameraMoveStarted(int i) {
    Log.w(LOG_TAG_MAP, "地图相机开始移动");
    if (null != huaweiMap && null != huaweiMap.getCameraPosition()) {
        //记录相机移动时的相机各个属性的初始值
        initZoomValue = huaweiMap.getCameraPosition().zoom;
        initTiltValue = huaweiMap.getCameraPosition().tilt;
        initBearingValue = huaweiMap.getCameraPosition().bearing;
    }
}
/** * 初始值对象 * initZoomValue-屏幕中心附近的缩放级别初始值。 * initTiltValue-相机角度与垂直于地球表面的线的夹角初始值。 * initBearingValue-相机指向的方向初始值。 */ private float initZoomValue, initTiltValue, initBearingValue; //地图相机开始移动的回调 @Override public void onCameraMoveStarted(int i) { Log.w(LOG_TAG_MAP, "地图相机开始移动"); if (null != huaweiMap && null != huaweiMap.getCameraPosition()) { //记录相机移动时的相机各个属性的初始值 initZoomValue = huaweiMap.getCameraPosition().zoom; initTiltValue = huaweiMap.getCameraPosition().tilt; initBearingValue = huaweiMap.getCameraPosition().bearing; } }

3. 在onCameraIdle()方法中,计算用户与地图相机的交互类型。

//地图相机移动结束的回调
@Override
public void onCameraIdle() {
//计算用户与相机的交互手势类型
if (null != huaweiMap && null != huaweiMap.getCameraPosition()) {
//通过计算zoom的值是否发生变化 判断用户与地图交互类型是平移还是旋转
if (initZoomValue != huaweiMap.getCameraPosition().zoom) {
Log.w(LOG_TAG_MAP, "地图相机结束移动,移动类型为:缩放");
} else {
Log.w(LOG_TAG_MAP, "地图相机结束移动,移动类型为:平移");
}
//通过计算Tilt的值是否发生变化 判断用户与地图交互类型是否是倾斜手势
if (initTiltValue != huaweiMap.getCameraPosition().tilt) {
Log.w(LOG_TAG_MAP, "地图相机结束移动,移动类型为:倾斜");
}
//通过计算Bearing的值是否发生变化 判断用户与地图交互类型是否是旋转手势
if (initBearingValue != huaweiMap.getCameraPosition().bearing) {
Log.w(LOG_TAG_MAP, "地图相机结束移动,移动类型为:旋转");
}
}
}
//地图相机移动结束的回调
@Override
public void onCameraIdle() {
    //计算用户与相机的交互手势类型
    if (null != huaweiMap && null != huaweiMap.getCameraPosition()) {
        //通过计算zoom的值是否发生变化 判断用户与地图交互类型是平移还是旋转
        if (initZoomValue != huaweiMap.getCameraPosition().zoom) {
            Log.w(LOG_TAG_MAP, "地图相机结束移动,移动类型为:缩放");
        } else {
            Log.w(LOG_TAG_MAP, "地图相机结束移动,移动类型为:平移");
        }
        //通过计算Tilt的值是否发生变化 判断用户与地图交互类型是否是倾斜手势
        if (initTiltValue != huaweiMap.getCameraPosition().tilt) {
            Log.w(LOG_TAG_MAP, "地图相机结束移动,移动类型为:倾斜");
        }
        //通过计算Bearing的值是否发生变化 判断用户与地图交互类型是否是旋转手势
        if (initBearingValue != huaweiMap.getCameraPosition().bearing) {
            Log.w(LOG_TAG_MAP, "地图相机结束移动,移动类型为:旋转");
        }
    }
}
//地图相机移动结束的回调 @Override public void onCameraIdle() { //计算用户与相机的交互手势类型 if (null != huaweiMap && null != huaweiMap.getCameraPosition()) { //通过计算zoom的值是否发生变化 判断用户与地图交互类型是平移还是旋转 if (initZoomValue != huaweiMap.getCameraPosition().zoom) { Log.w(LOG_TAG_MAP, "地图相机结束移动,移动类型为:缩放"); } else { Log.w(LOG_TAG_MAP, "地图相机结束移动,移动类型为:平移"); } //通过计算Tilt的值是否发生变化 判断用户与地图交互类型是否是倾斜手势 if (initTiltValue != huaweiMap.getCameraPosition().tilt) { Log.w(LOG_TAG_MAP, "地图相机结束移动,移动类型为:倾斜"); } //通过计算Bearing的值是否发生变化 判断用户与地图交互类型是否是旋转手势 if (initBearingValue != huaweiMap.getCameraPosition().bearing) { Log.w(LOG_TAG_MAP, "地图相机结束移动,移动类型为:旋转"); } } }

4. 可通过下方的Gif图看一下具体效果:

a. 平移和缩放手势类型:

3.gif

b. 旋转手势类型:

4.gif

c. 倾斜手势类型:

5.gif

四. 参考资料

  1. 创建地图实例

  2. 地图相机移动侦听

  3. 地图相机属性

了解更多详情>>

访问地图服务联盟官网

获取地图服务开发指导文档

访问HMS Core 联盟官网

获取HMS Core 开发指导文档

关注我们,第一时间了解 HMS Core 最新技术资讯~

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MY2Nues7' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片