Android MVVM框架搭建(八)高德地图定位、天气查询、BottomSheetDialog

这里只是简单的继承了一下BaseFragment,然后就是DataBinding的绑定。

② Navigation绑定

然后我们需要在nav_graph.xml中添加这个布局。

<fragment

android:id=“@+id/map_fragment”

android:name=“com.llw.mvvm.ui.fragment.MapFragment”

android:label=“map_fragment”

tools:layout=“@layout/map_fragment” />

这里配置了,那么底部的菜单同样要配置,毕竟我们是通过菜单去控制Fragment的切换的,打开navigation_menu.xml,在里面添加一个item,代码如下:

<item

android:id=“@+id/map_fragment”

android:icon=“@mipmap/ic_map”

android:title=“地图” />

这个图标可以去我的源码里面去找,或者自己去网上找一个也行。

下面进入到HomeActivity中去配置,配置切换菜单时的Fragment布局改变,如下图所示:

在这里插入图片描述

③ Fragment中地图生命周期绑定

要显示地图需要将地图的生命周期与Fragment的生命周期绑定起来,如下图所示:

在这里插入图片描述

如果你是线上的项目你需要在隐私政策中引入高德SDK的说明,然后在MapFragment中绑定地图的生命周期。

@Override

public void onSaveInstanceState(@NonNull @NotNull Bundle outState) {

super.onSaveInstanceState(outState);

binding.mapView.onSaveInstanceState(outState);

}

@Override

public void onResume() {

super.onResume();

binding.mapView.onResume();

}

@Override

public void onPause() {

super.onPause();

binding.mapView.onPause();

}

@Override

public void onDestroy() {

super.onDestroy();

binding.mapView.onDestroy();

}

下面运行一下:

在这里插入图片描述

现在只是显示了地图,但是并没有定位到我当前所在地,这当然是不行的。

四、显示当前所在地


显示当前所在地则需要定位权限,之前在AndroidManifest.xml中已经配置好了,下面则需要在代码中动态请求。

① 定位动态权限申请

在上一篇文章中写过一个PermissionUtils类,这里给这个类再加一点东西进去,在PermissionUtils中增加如下代码:

public static final String LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;

public static final int REQUEST_LOCATION_CODE = 1003;

然后在getPermissionRequestCode方法中增加一个case,如下图所示:

在这里插入图片描述

下面就是在HomeActivity中请求动态权限了,在HomeActivity中新增如下方法:

/**

  • 请求定位权限

*/

private void requestLocation() {

if (isAndroid6()) {

if (!hasPermission(PermissionUtils.LOCATION)) {

requestPermission(PermissionUtils.LOCATION);

}

} else {

showMsg(“您无需动态请求权限”);

}

}

然后在initView方法中调用它,如下图所示:

在这里插入图片描述

② 地图定位当前所在地

下面回到MapFragment,新增如下代码:

private static final String TAG = MapFragment.class.getSimpleName();

/**

  • 初始化地图

*/

private void initMap() {

//初始化地图控制器对象

AMap aMap = binding.mapView.getMap();

// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false

aMap.setMyLocationEnabled(true);

MyLocationStyle style = new MyLocationStyle();//初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)如果不设置myLocationType,默认也会执行此种模式。

style.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE) ;//定位一次,且将视角移动到地图中心点。

aMap.setMyLocationStyle(style);//设置定位蓝点的Style

aMap.getUiSettings().setMyLocationButtonEnabled(true);//设置默认定位按钮是否显示,非必需设置。

aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。

//设置SDK 自带定位消息监听

aMap.setOnMyLocationChangeListener(this);

}

@Override

public void onMyLocationChange(Location location) {

// 定位回调监听

if(location != null) {

Log.e(TAG, "onMyLocationChange 定位成功, lat: " + location.getLatitude() + " lon: " + location.getLongitude());

} else {

Log.e(TAG, “定位失败”);

}

}

实现位置监听

在这里插入图片描述

调用initMap()

在这里插入图片描述

运行一下

在这里插入图片描述

五、获取详细的地址信息


通过地图定位的方式定位在了当前所在地,但是onMyLocationChange的location中只有当前所在地的经纬度,如果我们需要拿到详细的地址信息要怎么做呢?通过SearchSDK实现,通过逆地理编码来将坐标转换成详细的地址。依然是在MapFragment,继承GeocodeSearch.OnGeocodeSearchListener,实现两个回调方法。代码如下:

/**

  • 坐标转地址

*/

@Override

public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int rCode) {

}

/**

  • 地址转坐标

*/

@Override

public void onGeocodeSearched(GeocodeResult geocodeResult, int rCode) {

}

然后这个也需要初始化,代码如下:

//解析成功标识码

private static final int PARSE_SUCCESS_CODE = 1000;

private GeocodeSearch geocoderSearch = null;

private String district = null;// 区/县

下面写一个方法初始化搜索

/**

  • 初始化搜索

*/

private void initSearch() {

try {

geocoderSearch = new GeocodeSearch(requireActivity());

geocoderSearch.setOnGeocodeSearchListener(this);

} catch (AMapException e) {

e.printStackTrace();

}

}

调用的地方如下图:

在这里插入图片描述

当收位置信息改变时,进行坐标的搜索,在onMyLocationChange中添加如下代码:

//创建一个经纬度点,参数一是纬度,参数二是经度

LatLonPoint latLonPoint = new LatLonPoint(location.getLatitude(), location.getLongitude());

// 第一个参数表示一个Latlng,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系

RegeocodeQuery query = new RegeocodeQuery(latLonPoint, 20, GeocodeSearch.AMAP);

//通过经纬度获取地址信息

geocoderSearch.getFromLocationAsyn(query);

添加位置如下:

在这里插入图片描述

然后就会触发onRegeocodeSearched的回调,在onRegeocodeSearched中则对所在地的信息进行打印和简单的区/县赋值,在onRegeocodeSearched方法中添加如下代码:

//解析result获取地址描述信息

if (rCode == PARSE_SUCCESS_CODE) {

RegeocodeAddress regeocodeAddress = regeocodeResult.getRegeocodeAddress();

//显示解析后的地址

Log.e(TAG, "地址: " + regeocodeAddress.getFormatAddress());

district = regeocodeAddress.getDistrict();

Log.e(TAG, "区: " + district);

} else {

showMsg(“获取地址失败”);

}

添加位置如下:

在这里插入图片描述

下面运行一下:

在这里插入图片描述

这样就拿到了详细的位置信息。

六、获取天气数据


高德是自带了天气数据接口的,可以用,只不过数据不是很多,如果需要更多的数据的话可以自己去对接天气API,例如和风、彩云。

在MapFragment创建变量

private LocalWeatherLive liveResult;

private LocalWeatherForecast forecastResult;

然后MapFragment继承WeatherSearch.OnWeatherSearchListener,实现两个方法。

/**

  • 实时天气返回

*/

@Override

public void onWeatherLiveSearched(LocalWeatherLiveResult localWeatherLiveResult, int code) {

liveResult = localWeatherLiveResult.getLiveResult();

if (liveResult != null) {

Log.e(TAG, "onWeatherLiveSearched: " + new Gson().toJson(liveResult));

} else {

showMsg(“实时天气数据为空”);

}

}

/**

  • 天气预报返回

*/

@Override

public void onWeatherForecastSearched(LocalWeatherForecastResult localWeatherForecastResult, int code) {

forecastResult = localWeatherForecastResult.getForecastResult();

if (forecastResult != null) {

Log.e(TAG, "onWeatherForecastSearched: " + new Gson().toJson(forecastResult));

} else {

showMsg(“天气预报数据为空”);

}

}

在方法回调中打印一下返回的数据,然后写一个搜索天气的方法,根据传入不同的天气类型,进行不同的天气数据搜索,代码如下:

/**

  • 搜索天气

  • @param type WEATHER_TYPE_LIVE 实时天气 WEATHER_TYPE_FORECAST 预报天气

*/

private void searchWeather(int type) {

WeatherSearchQuery weatherSearchQuery = new WeatherSearchQuery(district, type);

try {

WeatherSearch weatherSearch = new WeatherSearch(requireActivity());

weatherSearch.setOnWeatherSearchListener(this);

weatherSearch.setQuery(weatherSearchQuery);

weatherSearch.searchWeatherAsyn(); //异步搜索

} catch (AMapException e) {

e.printStackTrace();

}

}

最后在onRegeocodeSearched中,拿到地址信息时调用searchWeather方法,代码如下:

//搜索天气 实时天气和预报天气

searchWeather(WeatherSearchQuery.WEATHER_TYPE_LIVE);

searchWeather(WeatherSearchQuery.WEATHER_TYPE_FORECAST);

添加位置如下:

在这里插入图片描述

下面运行一下,查看日志,天气的数据就有了

在这里插入图片描述

七、显示天气数据


有了天气数据之后就是显示天气数据了,这里我们可以这么做,就是在MapFragment中添加一个浮动按钮,点击之后从屏幕底部弹出一个,先来修改一下map_fragment中的代码,我们增加一个浮动按钮。

<com.google.android.material.floatingactionbutton.FloatingActionButton

android:id=“@+id/fab_weather”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_gravity=“end|bottom”

android:layout_margin=“20dp”

android:visibility=“gone”

android:contentDescription=“天气”

android:src=“@mipmap/ic_weather”

app:backgroundTint=“@color/white”

app:fabSize=“auto”

tools:ignore=“UsingOnClickInXml” />

添加的位置就如下图所示:

在这里插入图片描述

这里我先把这个按钮给隐藏了,当地图上获取了当前的位置,查询到了天气之后再显示这个按钮。下面回到MapFragment中,在initMap方法中增加一行代码,

//修改放大缩小按钮的位置

aMap.getUiSettings().setZoomPosition(AMapOptions.ZOOM_POSITION_RIGHT_CENTER);

这样做就是让我们的浮动按钮不至于挡住这个地图的放大缩小按钮。

在MapFragment中添加一个变量

//天气预报列表

private List weatherForecast;

然后在onWeatherForecastSearched回调中对找个变量赋值,这才是实际的天气数据

在这里插入图片描述

查询到天气预报数据后,显示这个按钮。

① 实时天气数据

现在已经可以看到所在地的天气了,当需要显示出来的时候你会发现找个数据里面是没有所在地的区/县的,只有省和市。因此在model包下新建一个LiveWeather,把我们在通过你地理编码返回时的区/县的值放进去,代码如下:

public class LiveWeather {

private String district;

private LocalWeatherLive localWeatherLive;

public LiveWeather(String district, LocalWeatherLive localWeatherLive) {

this.district = district;

this.localWeatherLive = localWeatherLive;

}

public String getDistrict() {

return district;

}

public void setDistrict(String district) {

this.district = district;

}

public LocalWeatherLive getLocalWeatherLive() {

return localWeatherLive;

}

public void setLocalWeatherLive(LocalWeatherLive localWeatherLive) {

this.localWeatherLive = localWeatherLive;

}

}

这个数据将会绑定到我们的天气弹窗,现在来创建这个弹窗的布局。

② 天气弹窗布局

弹窗布局分为两个环节,一个是实时天气,一个是预报天气。首先colors.xml创建一个颜色值,如下:

#90000000

然后在drawable下创建一个shape_translucent_radius_12.xml样式文件,代码如下:

<?xml version="1.0" encoding="utf-8"?>

下面创建弹窗的布局,在layout下新建一个dialog_weather.xml,里面的代码如下:

<?xml version="1.0" encoding="utf-8"?>

<variable

name=“liveWeather”

type=“com.llw.mvvm.model.LiveWeather” />

<RelativeLayout

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:background=“#00000000”

android:orientation=“vertical”

android:paddingStart=“12dp”

android:paddingEnd=“12dp”

android:paddingBottom=“?attr/actionBarSize”>

<TextView

android:id=“@+id/tv_city”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:layout_marginBottom=“12dp”

android:background=“@drawable/shape_translucent_radius_12”

android:gravity=“center”

android:padding=“12dp”

android:text=“@{liveWeather.district}”

android:textColor=“@color/white”

android:textSize=“28sp” />

<TextView

android:id=“@+id/tv_weather”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_above=“@+id/tv_report_time”

android:layout_below=“@+id/tv_city”

android:layout_alignParentStart=“true”

android:layout_marginEnd=“12dp”

android:layout_marginBottom=“12dp”

android:background=“@drawable/shape_translucent_radius_12”

android:gravity=“center”

android:padding=“12dp”

android:text=“@{liveWeather.localWeatherLive.weather}”

android:textColor=“@color/white”

android:textSize=“24sp” />

<LinearLayout

android:id=“@+id/wind_lay”

android:layout_width=“wrap_content”

android:layout_height=“44dp”

android:layout_below=“@+id/tv_city”

android:layout_toStartOf=“@+id/tv_temp”

android:layout_toEndOf=“@+id/tv_weather”

android:background=“@drawable/shape_translucent_radius_12”

android:gravity=“center”

android:orientation=“horizontal”>

<TextView

android:id=“@+id/tv_wind_direction”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_marginEnd=“12dp”

android:text=“@{liveWeather.localWeatherLive.windDirection+}”

android:textColor=“@color/white” />

<TextView

android:id=“@+id/tv_wind_power”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_marginStart=“12dp”

android:text=“@{liveWeather.localWeatherLive.windPower+}”

android:textColor=“@color/white” />

<LinearLayout

android:id=“@+id/humidity_lay”

android:layout_width=“wrap_content”

android:layout_height=“44dp”

android:layout_below=“@+id/wind_lay”

android:layout_marginTop=“12dp”

android:layout_toStartOf=“@+id/tv_temp”

android:layout_toEndOf=“@+id/tv_weather”

android:background=“@drawable/shape_translucent_radius_12”

android:gravity=“center”

android:orientation=“horizontal”>

<TextView

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_marginEnd=“24dp”

android:text=“湿度”

android:textColor=“@color/white” />

<TextView

android:id=“@+id/tv_humidity”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“@{liveWeather.localWeatherLive.humidity+%}”

android:textColor=“@color/white” />

<TextView

android:id=“@+id/tv_temp”

android:layout_width=“100dp”

android:layout_height=“100dp”

android:layout_below=“@+id/tv_city”

android:layout_alignParentEnd=“true”

android:layout_marginStart=“12dp”

android:layout_marginBottom=“12dp”

android:background=“@drawable/shape_translucent_radius_12”

android:gravity=“center”

android:padding=“12dp”

android:text=“@{liveWeather.localWeatherLive.temperature+}”

android:textColor=“@color/white”

android:textSize=“32sp” />

<TextView

android:id=“@+id/tv_report_time”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:layout_below=“@+id/tv_temp”

android:background=“@drawable/shape_translucent_radius_12”

android:gravity=“center”

android:padding=“12dp”

android:text=“@{liveWeather.localWeatherLive.reportTime+发布}”

android:textColor=“@color/white” />

<androidx.recyclerview.widget.RecyclerView

android:id=“@+id/rv_forecast”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:layout_below=“@+id/tv_report_time”

android:layout_marginTop=“12dp” />

有列表就有对应的item布局,在layout下创建item_forecast.xml布局,代码如下:

<?xml version="1.0" encoding="utf-8"?>

<variable

name=“forecast”

type=“com.amap.api.services.weather.LocalDayWeatherForecast” />

<RelativeLayout

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:layout_marginBottom=“12dp”

android:background=“@drawable/shape_translucent_radius_12”

android:padding=“12dp”>

<TextView

android:id=“@+id/tv_date”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“@{forecast.date}”

android:textColor=“@color/white” />

<TextView

android:id=“@+id/tv_week”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_marginStart=“12dp”

android:layout_toEndOf=“@+id/tv_date”

android:text=“@{EasyDate.getWeek(forecast.date)}”

android:textColor=“@color/white” />

<TextView

android:id=“@+id/tv_temp”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_alignParentEnd=“true”

android:text=“@{forecast.dayTemp+° /+ forecast.nightTemp+°}”

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

架构师筑基包括哪些内容

我花了将近半个月时间将:深入 Java 泛型.、注解深入浅出、并发编程.、数据传输与序列化、Java 虚拟机原理、反射与类加载、高效 IO、Kotlin项目实战等等Android架构师筑基必备技能整合成了一套系统知识笔记PDF,相信看完这份文档,你将会对这些Android架构师筑基必备技能有着更深入、更系统的理解。

由于文档内容过多,为了避免影响到大家的阅读体验,在此只以截图展示部分内容

注:资料与上面思维导图一起看会更容易学习哦!每个点每个细节分支,都有对应的目录内容与知识点!



这份资料就包含了所有Android初级架构师所需的所有知识!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

Temp+°}"

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-Aq3g5dBk-1713720713705)]

[外链图片转存中…(img-HBYSzAIf-1713720713706)]

[外链图片转存中…(img-jLMKcPbm-1713720713707)]

[外链图片转存中…(img-uom3HuxL-1713720713708)]

[外链图片转存中…(img-45gvSIul-1713720713710)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

[外链图片转存中…(img-bDzSymOa-1713720713711)]

架构师筑基包括哪些内容

我花了将近半个月时间将:深入 Java 泛型.、注解深入浅出、并发编程.、数据传输与序列化、Java 虚拟机原理、反射与类加载、高效 IO、Kotlin项目实战等等Android架构师筑基必备技能整合成了一套系统知识笔记PDF,相信看完这份文档,你将会对这些Android架构师筑基必备技能有着更深入、更系统的理解。

由于文档内容过多,为了避免影响到大家的阅读体验,在此只以截图展示部分内容

注:资料与上面思维导图一起看会更容易学习哦!每个点每个细节分支,都有对应的目录内容与知识点!

[外链图片转存中…(img-E2k72GPG-1713720713712)]
[外链图片转存中…(img-svvtGtMA-1713720713713)]
这份资料就包含了所有Android初级架构师所需的所有知识!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 27
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值