赞
踩
上一篇:Android 天气APP(十)下拉刷新页面天气数据
在上篇文章中,更新了每日壁纸的BUG,同时增加了下拉刷新和滑动改变标题,本篇文章中将增加逐小时天气预报以及UI的优化。
本篇文章中我们先改动一下UI,实际上就是对于activity_main.xml的控件改动,首先改动activity_main.xml,代码如下所示:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/lay_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/main_bg"
android:fitsSystemWindows="true"
tools:context=".ui.MainActivity">
<!--顶部标题-->
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/materialToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:ellipsize="middle"
android:singleLine="true"
android:text="城市天气"
android:textColor="@color/white"
android:textSize="@dimen/sp_16" />
</com.google.android.material.appbar.MaterialToolbar>
<!--下拉刷新视图-->
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/lay_refresh"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_0"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialToolbar">
<!--滚动视图-->
<androidx.core.widget.NestedScrollView
android:id="@+id/lay_scroll"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--页面主要内容视图-->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dp_0">
<!--滑动距离布局-->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/lay_scroll_height"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<!--天气状况-->
<TextView
android:id="@+id/tv_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_8"
android:text="天气状况"
android:textColor="@color/white"
android:textSize="@dimen/sp_18"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!--温度-->
<TextView
android:id="@+id/tv_temp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_24"
android:text="0"
android:textColor="@color/white"
android:textSize="@dimen/sp_60"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_info" />
<!--摄氏度符号-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="℃"
android:textColor="@color/white"
android:textSize="@dimen/sp_24"
app:layout_constraintStart_toEndOf="@+id/tv_temp"
app:layout_constraintTop_toTopOf="@+id/tv_temp" />
<!--当天最高温和最低温-->
<LinearLayout
android:id="@+id/lay_temp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="@+id/tv_temp"
app:layout_constraintStart_toStartOf="@+id/tv_temp"
app:layout_constraintTop_toBottomOf="@+id/tv_temp">
<!--最高温-->
<TextView
android:id="@+id/tv_height"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize="@dimen/sp_14" />
<!--最低温-->
<TextView
android:id="@+id/tv_low"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/temp_min_tx"
android:textSize="@dimen/sp_14" />
</LinearLayout>
<!--城市-->
<TextView
android:id="@+id/tv_city"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="城市"
android:textColor="@color/white"
android:textSize="@dimen/sp_20"
app:layout_constraintEnd_toEndOf="@+id/tv_temp"
app:layout_constraintStart_toStartOf="@+id/tv_temp"
app:layout_constraintTop_toBottomOf="@+id/lay_temp" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!--App名称-->
<TextView
android:id="@+id/tv_app_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_16"
android:drawableStart="@mipmap/icon_weather_sun"
android:drawablePadding="@dimen/dp_4"
android:text="Good Weather New"
android:textColor="@color/white"
android:textSize="@dimen/sp_12"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lay_scroll_height" />
<!--上一次更新时间-->
<TextView
android:id="@+id/tv_update_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_16"
android:text="最近更新时间:"
android:textColor="@color/white"
android:textSize="@dimen/sp_12"
app:layout_constraintBottom_toBottomOf="@+id/tv_app_name"
app:layout_constraintEnd_toEndOf="@+id/lay_scroll_height"
app:layout_constraintTop_toTopOf="@+id/tv_app_name" />
<!--分隔线 增加UI效果-->
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_1"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_8"
android:layout_marginEnd="@dimen/dp_16"
android:alpha="0.1"
android:background="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_app_name" />
<!--逐小时天气预报列表-->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_hourly"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_16"
android:paddingStart="@dimen/dp_16"
android:paddingEnd="@dimen/dp_16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/view" />
<!--天气预报列表-->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_daily"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingStart="@dimen/dp_16"
android:paddingEnd="@dimen/dp_16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/rv_hourly" />
<!--风向风力-->
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="8dp"
android:text="风向风力"
android:textColor="@color/white"
android:textSize="@dimen/sp_18"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/rv_daily" />
<!--大风车-->
<com.llw.goodweather.ui.view.WhiteWindmills
android:id="@+id/ww_big"
android:layout_width="100dp"
android:layout_height="120dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2"
tools:ignore="MissingConstraints" />
<!--小风车-->
<com.llw.goodweather.ui.view.WhiteWindmills
android:id="@+id/ww_small"
android:layout_width="50dp"
android:layout_height="60dp"
android:layout_marginStart="32dp"
app:layout_constraintBottom_toBottomOf="@+id/ww_big"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toStartOf="@+id/ww_big"
tools:ignore="MissingConstraints" />
<!--纵向辅助线-->
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="205dp" />
<!--风向风力文字-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="@+id/ww_big"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline2"
app:layout_constraintTop_toTopOf="@+id/ww_big">
<!--风向-->
<TextView
android:id="@+id/tv_wind_direction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize="@dimen/sp_14" />
<!--风力-->
<TextView
android:id="@+id/tv_wind_power"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_24"
android:textColor="@color/white"
android:textSize="@dimen/sp_14" />
</LinearLayout>
<!--生活建议-->
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="16dp"
android:text="生活建议"
android:textColor="@color/white"
android:textSize="@dimen/sp_18"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ww_big" />
<!--生活建议列表-->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_lifestyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:paddingStart="@dimen/dp_16"
android:paddingEnd="@dimen/dp_16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
这里的布局就是整篇文章中改动后的布局,这里我改动了UI,并且增加了一个逐小时天气数据列表,首先是显示当天的最高温和最低温,在MainActivity中,天气预报返回中增加如下代码:
binding.tvHeight.setText(String.format("%s℃", daily.get(0).getTempMax()));
binding.tvLow.setText(String.format(" / %s℃", daily.get(0).getTempMin()));
添加位置如下图所示:
同时修改最近更新时间的位置和时间显示格式,位置我通过布局进行了改动,时间显示通过代码来改动,在实况天气的返回中添加如下代码:
String time = EasyDate.updateTime(nowResponse.getUpdateTime());
binding.tvUpdateTime.setText(String.format("最近更新时间:%s%s", EasyDate.showTimeInfo(time), time));
添加位置如下图所示:
现在UI基本上就改动完了,下面开始增加逐小时天气预报。
作为免费用户,可以获取24小时的逐小时天气预报,下面我们来使用它。
首先通过返回的示例数据手写一个实体类,在bean包下新建一个HourlyResponse类,代码如下所示:
public class HourlyResponse {
private String code;
private String updateTime;
private String fxLink;
private ReferBean refer;
private List<HourlyBean> hourly;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
public String getFxLink() {
return fxLink;
}
public void setFxLink(String fxLink) {
this.fxLink = fxLink;
}
public ReferBean getRefer() {
return refer;
}
public void setRefer(ReferBean refer) {
this.refer = refer;
}
public List<HourlyBean> getHourly() {
return hourly;
}
public void setHourly(List<HourlyBean> hourly) {
this.hourly = hourly;
}
public static class ReferBean {
private List<String> sources;
private List<String> license;
public List<String> getSources() {
return sources;
}
public void setSources(List<String> sources) {
this.sources = sources;
}
public List<String> getLicense() {
return license;
}
public void setLicense(List<String> license) {
this.license = license;
}
}
public static class HourlyBean {
private String fxTime;
private String temp;
private String icon;
private String text;
private String wind360;
private String windDir;
private String windScale;
private String windSpeed;
private String humidity;
private String pop;
private String precip;
private String pressure;
private String cloud;
private String dew;
public String getFxTime() {
return fxTime;
}
public void setFxTime(String fxTime) {
this.fxTime = fxTime;
}
public String getTemp() {
return temp;
}
public void setTemp(String temp) {
this.temp = temp;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getWind360() {
return wind360;
}
public void setWind360(String wind360) {
this.wind360 = wind360;
}
public String getWindDir() {
return windDir;
}
public void setWindDir(String windDir) {
this.windDir = windDir;
}
public String getWindScale() {
return windScale;
}
public void setWindScale(String windScale) {
this.windScale = windScale;
}
public String getWindSpeed() {
return windSpeed;
}
public void setWindSpeed(String windSpeed) {
this.windSpeed = windSpeed;
}
public String getHumidity() {
return humidity;
}
public void setHumidity(String humidity) {
this.humidity = humidity;
}
public String getPop() {
return pop;
}
public void setPop(String pop) {
this.pop = pop;
}
public String getPrecip() {
return precip;
}
public void setPrecip(String precip) {
this.precip = precip;
}
public String getPressure() {
return pressure;
}
public void setPressure(String pressure) {
this.pressure = pressure;
}
public String getCloud() {
return cloud;
}
public void setCloud(String cloud) {
this.cloud = cloud;
}
public String getDew() {
return dew;
}
public void setDew(String dew) {
this.dew = dew;
}
}
}
在ApiService接口中,增加如下代码:
@GET("/v7/weather/24h?key=" + API_KEY)
Observable<HourlyResponse> hourlyWeather(@Query("location") String location);
然后是使用的地方,在WeatherRepository中增加如下方法代码:
public void hourlyWeather(MutableLiveData<HourlyResponse> responseLiveData,
MutableLiveData<String> failed, String cityId) {
String type = "逐小时天气预报-->";
NetworkApi.createService(ApiService.class, ApiType.WEATHER).hourlyWeather(cityId)
.compose(NetworkApi.applySchedulers(new BaseObserver<>() {
@Override
public void onSuccess(HourlyResponse hourlyResponse) {
if (hourlyResponse == null) {
failed.postValue("逐小时天气预报数据为null,请检查城市ID是否正确。");
return;
}
//请求接口成功返回数据,失败返回状态码
if (Constant.SUCCESS.equals(hourlyResponse.getCode())) {
responseLiveData.postValue(hourlyResponse);
} else {
failed.postValue(type + hourlyResponse.getCode());
}
}
@Override
public void onFailure(Throwable e) {
Log.e(TAG, "onFailure: " + e.getMessage());
failed.postValue(type + e.getMessage());
}
}));
}
在MainViewModel中使用,增加如下代码:
public MutableLiveData<HourlyResponse> hourlyResponseMutableLiveData = new MutableLiveData<>();
public void hourlyWeather(String cityId) {
WeatherRepository.getInstance().hourlyWeather(hourlyResponseMutableLiveData, failed, cityId);
}
现在只差调用了,不过因为是列表,所以还需要适配器。
在layout下新增一个item_hourly_rv.xml,代码如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_hourly"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="@dimen/dp_8">
<!--时间-->
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上午10:00"
android:textColor="@color/white"
android:textSize="@dimen/sp_14" />
<!--气候图标-->
<ImageView
android:id="@+id/iv_status"
android:layout_width="@dimen/dp_32"
android:layout_height="@dimen/dp_32"
android:layout_marginTop="@dimen/dp_12"
android:layout_marginBottom="@dimen/dp_8"
android:background="@mipmap/icon_100" />
<!--温度-->
<TextView
android:id="@+id/tv_temperature"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="25℃"
android:textColor="@color/white"
android:textSize="@dimen/sp_20" />
</LinearLayout>
然后在adapter包下新建一个HourlyAdapter ,代码如下所示:
public class HourlyAdapter extends RecyclerView.Adapter<HourlyAdapter.ViewHolder> {
private final List<HourlyResponse.HourlyBean> hourlyBeans;
public HourlyAdapter(List<HourlyResponse.HourlyBean> dailyBeans) {
this.hourlyBeans = dailyBeans;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemHourlyRvBinding binding = ItemHourlyRvBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new ViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
HourlyResponse.HourlyBean hourlyBean = hourlyBeans.get(position);
String time = EasyDate.updateTime(hourlyBean.getFxTime());
holder.binding.tvTime.setText(String.format("%s%s", EasyDate.showTimeInfo(time), time));
WeatherUtil.changeIcon(holder.binding.ivStatus, Integer.parseInt(hourlyBean.getIcon()));
holder.binding.tvTemperature.setText(String.format("%s℃", hourlyBean.getTemp()));
}
@Override
public int getItemCount() {
return hourlyBeans.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ItemHourlyRvBinding binding;
public ViewHolder(@NonNull ItemHourlyRvBinding itemHourlyRvBinding) {
super(itemHourlyRvBinding.getRoot());
binding = itemHourlyRvBinding;
}
}
}
这里面的代码很简单,就是数据显示而已,下面在MainActivity中使用。
在MainActivity中声明变量:
private final List<HourlyResponse.HourlyBean> hourlyBeanList = new ArrayList<>();
private final HourlyAdapter hourlyAdapter = new HourlyAdapter(hourlyBeanList);
然后在initView()方法中增加如下代码,对逐小时天气预报列表进行设置,代码如下:
LinearLayoutManager hourlyLayoutManager = new LinearLayoutManager(this);
hourlyLayoutManager.setOrientation(RecyclerView.HORIZONTAL);
binding.rvHourly.setLayoutManager(hourlyLayoutManager);
binding.rvHourly.setAdapter(hourlyAdapter);
添加位置如下图所示:
这里设置了横向滑动,下面就是逐小时天气请求数据的返回了,在onObserveData()方法中,添加如下代码:
viewModel.hourlyResponseMutableLiveData.observe(this, hourlyResponse -> {
List<HourlyResponse.HourlyBean> hourly = hourlyResponse.getHourly();
if (hourly != null) {
if (hourlyBeanList.size() > 0) {
hourlyBeanList.clear();
}
hourlyBeanList.addAll(hourly);
hourlyAdapter.notifyDataSetChanged();
}
});
添加位置如下图所示:
然后也不要忘记在搜索城市的回调中调用逐小时天气请求方法,如下图所示:
最后再改动一个地方,修改WeatherUtil中的changeIcon()方法,如下图所示:
因为有151这个天气状态编码,之前没有设置,所以就会显示N/A的图,这里补充一下,现在可以运行了。
这里看到的UI就是有了调整的。
欢迎 Star 和 Fork
第十一篇文章源码地址:GoodWeather-New-11
如果你看到这里那么你应该看过前面十篇文章了,这是第十一篇,其实写作的原意,并不是我想分这么多章节的,但是不得不分章节,我不能只考虑自己不考虑阅读的人,试问,我这里有一篇20万字的博客,你要不要看一下呢?你可能会望而却步吧,从而失去兴趣,故分章节,但请放心,我不是标题党,也不做无意义的分章节,标题肯定是要对应里面的内容的,现在有些博主写文章花里胡哨的,就靠标题吸引人,里面的内容都在胡扯,没有一点意义,题不对意,别人提问也不回复,这样就是不负责任,对此,我表示强烈的谴责和抗议。
还记得之前注册这个和风天气的API吗?之前是用普通用户(作为白嫖党,如果不多搞一些,就亏了,所以我们要从普通用户升级到开发者,当然还是不要钱的,只不过拿到的数据会多一点,我们要的七天的天气预报就在开发者的版本里面,而且开发者的API访问是比普通用户要多的。当然你们要是有钱可以使用商业版,商业版的数据足够你开发一个商业级别的APP了,只不过商业版很贵就是了,我一个穷人用不起,当然我们也可以合作,你出钱,我出力,美滋滋),现在升级到开发者,点击和风天气登录,进入控制台
点击升级,会让你绑定手机号,输入验证码后下一步就是升级为开发者
作为开发者你就要对自己的APP负责了,所以就需要你的身份证号码和正反面照片了,还是应用的名称及应用的类型,相信你们也知道该怎么填,填完之后点击同意并变更
然后就会进入审核阶段,
审核的结果会发到你注册时的邮箱里面。慢慢等吧(建议你可以先把文章收藏,等你的审核通过之后继续看,有些文章,错过就不在了)。
反正你现在闲着也是闲着,来改UI吧,天气预报列表中的天气状态之前是用文字来描述的,现在改成用图标来描述,那么这个图标哪里来呢?羊毛出在羊身上,薅羊毛就要彻底一些,当然是去和风天气官网去拿图标了。
下载之后解压,你会看到很多图标,但是这些图标的颜色是蓝色的,而我希望是白色,这样才符合我这个APP的UI整体效果,所以还是要自己改一下图标的颜色,这么多图标,这也是个体力活啊,慢慢改吧。
打开你的PhotoShop,然后随便拖一个图标进去,比如这个图标。
颜色叠加
将默认的红色改成白色
然后点击确定,再点一次,回到PS主页面,可以看到就变成白色了
接下来保存图标,点击左上角的文件->存储为
格式保存为png格式,然后就是覆盖它原来的蓝色图标,然后一路保存,最后看到你的文件夹中的图标就变成白色的了。
好了,还有那么多图标呢,你慢慢改,不着急。磨刀不误砍柴工啊。
图标名中带“ n ”的是表示晚上,不带的就是白天的,你也可以改成白色的,并且在APP上增加现在是白天还是晚上的状态判断,也算是进一步优化,这个目前先不做。
Android不允许纯数字命名的图片,你可以把100.png改成icon_100.png。
所有图片都改好之后复制到你项目的mipmap-xhdpi文件夹下。
然后对照这个天气代码表来做判断显示
天气代码对照表
代码 | 中文 | 英文 | 图标 |
---|---|---|---|
100 | 晴 | Sunny/Clear | 100.png |
101 | 多云 | Cloudy | 101.png |
102 | 少云 | Few Clouds | 102.png |
103 | 晴间多云 | Partly Cloudy | 103.png |
104 | 阴 | Overcast | 104.png |
200 | 有风 | Windy | 200.png |
201 | 平静 | Calm | 201.png |
202 | 微风 | Light Breeze | 202.png |
203 | 和风 | Moderate/Gentle Breeze | 203.png |
204 | 清风 | Fresh Breeze | 204.png |
205 | 强风/劲风 | Strong Breeze | 205.png |
206 | 疾风 | High Wind, Near Gale | 206.png |
207 | 大风 | Gale | 207.png |
208 | 烈风 | Strong Gale | 208.png |
209 | 风暴 | Storm | 209.png |
210 | 狂爆风 | Violent Storm | 210.png |
211 | 飓风 | Hurricane | 211.png |
212 | 龙卷风 | Tornado | 212.png |
213 | 热带风暴 | Tropical Storm | 213.png |
300 | 阵雨 | Shower Rain | 300.png |
301 | 强阵雨 | Heavy Shower Rain | 301.png |
302 | 雷阵雨 | Thundershower | 302.png |
303 | 强雷阵雨 | Heavy Thunderstorm | 303.png |
304 | 雷阵雨伴有冰雹 | Thundershower with hail | 304.png |
305 | 小雨 | Light Rain | 305.png |
306 | 中雨 | Moderate Rain | 306.png |
307 | 大雨 | Heavy Rain | 307.png |
308 | 极端降雨 | Extreme Rain | 308.png |
309 | 毛毛雨/细雨 | Drizzle Rain | 309.png |
310 | 暴雨 | Storm | 310.png |
311 | 大暴雨 | Heavy Storm | 311.png |
312 | 特大暴雨 | Severe Storm | 312.png |
313 | 冻雨 | Freezing Rain | 313.png |
314 | 小到中雨 | Light to moderate rain | 314.png |
315 | 中到大雨 | Moderate to heavy rain | 315.png |
316 | 大到暴雨 | Heavy rain to storm | 316.png |
317 | 暴雨到大暴雨 | Storm to heavy storm | 317.png |
318 | 大暴雨到特大暴雨 | Heavy to severe storm | 318.png |
399 | 雨 | Rain | 399.png |
400 | 小雪 | Light Snow | 400.png |
401 | 中雪 | Moderate Snow | 401.png |
402 | 大雪 | Heavy Snow | 402.png |
403 | 暴雪 | Snowstorm | 403.png |
404 | 雨夹雪 | Sleet | 404.png |
405 | 雨雪天气 | Rain And Snow | 405.png |
406 | 阵雨夹雪 | Shower Snow | 406.png |
407 | 阵雪 | Snow Flurry | 407.png |
408 | 小到中雪 | Light to moderate snow | 408.png |
409 | 中到大雪 | Moderate to heavy snow | 409.png |
410 | 大到暴雪 | Heavy snow to snowstorm | 410.png |
499 | 雪 | Snow | 499.png |
500 | 薄雾 | Mist | 500.png |
501 | 雾 | Foggy | 501.png |
502 | 霾 | Haze | 502.png |
503 | 扬沙 | Sand | 503.png |
504 | 浮尘 | Dust | 504.png |
507 | 沙尘暴 | Duststorm | 507.png |
508 | 强沙尘暴 | Sandstorm | 508.png |
509 | 浓雾 | Dense fog | 509.png |
510 | 强浓雾 | Strong fog | 510.png |
511 | 中度霾 | Moderate haze | 511.png |
512 | 重度霾 | Heavy haze | 512.png |
513 | 严重霾 | Severe haze | 513.png |
514 | 大雾 | Heavy fog | 514.png |
515 | 特强浓雾 | Extra heavy fog | 515.png |
900 | 热 | Hot | 900.png |
901 | 冷 | Cold | 901.png |
999 | 未知 | Unknown | 999.png |
在我修改图标颜色的过程中,发现有好几个天气代码的图标是一模一样的,所以代码中判断显示的时候会有几个状态码对应的图标一样,提前说明,不要见怪。
接下里就是修改天气预报列表的item的布局文件了。
item_weather_forecast_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:gravity="center_vertical"
android:padding="@dimen/sp_12"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--日期-->
<TextView
android:id="@+id/tv_date"
android:text="1234"
android:textSize="@dimen/sp_14"
android:textColor="#FFF"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>
<!--天气描述 文字 隐藏-->
<TextView
android:visibility="gone"
android:gravity="center"
android:id="@+id/tv_info"
android:textSize="@dimen/sp_14"
android:textColor="#FFF"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>
<!--天气描述 图标-->
<ImageView
android:id="@+id/iv_weather_state"
android:background="@mipmap/icon_100"
android:layout_width="30dp"
android:layout_height="30dp"/>
<!--最低温、最高温-->
<TextView
android:gravity="right"
android:id="@+id/tv_low_and_height"
android:textSize="@dimen/sp_14"
android:textColor="#FFF"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
改动并不大,加了一个ImageView而已,然后在创建工具类
在utils包下创建一个WeatherUtil类
代码如下:
package com.llw.goodweather.utils;
import android.widget.ImageView;
import com.llw.goodweather.R;
/**
* 天气工具类
*/
public class WeatherUtil {
/**
* 根据传入的状态码修改填入的天气图标
* @param weatherStateIcon 显示的ImageView
* @param code 天气状态码
*/
public static void changeIcon(ImageView weatherStateIcon,int code){
switch (code){
case 100://晴
weatherStateIcon.setBackgroundResource(R.mipmap.icon_100);
break;
case 101://多云
weatherStateIcon.setBackgroundResource(R.mipmap.icon_101);
break;
case 102://少云
weatherStateIcon.setBackgroundResource(R.mipmap.icon_102);
break;
case 103://晴间多云
weatherStateIcon.setBackgroundResource(R.mipmap.icon_103);
break;
case 200://有风
case 202://微风
case 203://和风
case 204://清风
weatherStateIcon.setBackgroundResource(R.mipmap.icon_200);//因为这几个状态的图标是一样的
break;
case 201://平静
weatherStateIcon.setBackgroundResource(R.mipmap.icon_201);
break;
case 205://强风/劲风
case 206://疾风
case 207://大风
weatherStateIcon.setBackgroundResource(R.mipmap.icon_205);//因为这几个状态的图标是一样的
break;
case 208://烈风
case 209://风暴
case 210://狂爆风
case 211://飓风
case 212://龙卷风
case 213://热带风暴
weatherStateIcon.setBackgroundResource(R.mipmap.icon_208);//因为这几个状态的图标是一样的
break;
case 300://阵雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_300);
break;
case 301://强阵雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_301);
break;
case 302://雷阵雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_302);
break;
case 303://强雷阵雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_303);
break;
case 304://雷阵雨伴有冰雹
weatherStateIcon.setBackgroundResource(R.mipmap.icon_304);
break;
case 305://小雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_305);
break;
case 306://中雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_306);
break;
case 307://大雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_307);
break;
case 308://极端降雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_312);
break;
case 309://毛毛雨/细雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_309);
break;
case 310://暴雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_310);
break;
case 311://大暴雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_311);
break;
case 312://特大暴雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_312);
break;
case 313://冻雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_313);
break;
case 314://小到中雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_306);
break;
case 315://中到大雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_307);
break;
case 316://大到暴雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_310);
break;
case 317://大暴雨到特大暴雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_312);
break;
case 399://雨
weatherStateIcon.setBackgroundResource(R.mipmap.icon_399);
break;
case 400://小雪
weatherStateIcon.setBackgroundResource(R.mipmap.icon_400);
break;
case 401://中雪
weatherStateIcon.setBackgroundResource(R.mipmap.icon_401);
break;
case 402://大雪
weatherStateIcon.setBackgroundResource(R.mipmap.icon_402);
break;
case 403://暴雪
weatherStateIcon.setBackgroundResource(R.mipmap.icon_403);
break;
case 404://雨夹雪
weatherStateIcon.setBackgroundResource(R.mipmap.icon_404);
break;
case 405://雨雪天气
weatherStateIcon.setBackgroundResource(R.mipmap.icon_405);
break;
case 406://阵雨夹雪
weatherStateIcon.setBackgroundResource(R.mipmap.icon_406);
break;
case 407://阵雪
weatherStateIcon.setBackgroundResource(R.mipmap.icon_407);
break;
case 408://小到中雪
weatherStateIcon.setBackgroundResource(R.mipmap.icon_408);
break;
case 409://中到大雪
weatherStateIcon.setBackgroundResource(R.mipmap.icon_409);
break;
case 410://大到暴雪
weatherStateIcon.setBackgroundResource(R.mipmap.icon_410);
break;
case 499://雪
weatherStateIcon.setBackgroundResource(R.mipmap.icon_499);
break;
case 500://薄雾
weatherStateIcon.setBackgroundResource(R.mipmap.icon_500);
break;
case 501://雾
weatherStateIcon.setBackgroundResource(R.mipmap.icon_501);
break;
case 502://霾
weatherStateIcon.setBackgroundResource(R.mipmap.icon_502);
break;
case 503://扬沙
weatherStateIcon.setBackgroundResource(R.mipmap.icon_503);
break;
case 504://扬沙
weatherStateIcon.setBackgroundResource(R.mipmap.icon_504);
break;
case 507://沙尘暴
weatherStateIcon.setBackgroundResource(R.mipmap.icon_507);
break;
case 508://强沙尘暴
weatherStateIcon.setBackgroundResource(R.mipmap.icon_508);
break;
case 509://浓雾
case 510://强浓雾
case 514://大雾
case 515://特强浓雾
weatherStateIcon.setBackgroundResource(R.mipmap.icon_509);
break;
case 511://中度霾
weatherStateIcon.setBackgroundResource(R.mipmap.icon_511);
break;
case 512://重度霾
weatherStateIcon.setBackgroundResource(R.mipmap.icon_512);
break;
case 513://严重霾
weatherStateIcon.setBackgroundResource(R.mipmap.icon_513);
break;
case 900://热
weatherStateIcon.setBackgroundResource(R.mipmap.icon_900);
break;
case 901://冷
weatherStateIcon.setBackgroundResource(R.mipmap.icon_901);
break;
case 999://未知
weatherStateIcon.setBackgroundResource(R.mipmap.icon_999);
break;
}
}
}
WeatherForecastAdapter.java中做判断显示图标,代码如下:
package com.llw.goodweather.adapter;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.llw.goodweather.R;
import com.llw.goodweather.bean.WeatherForecastResponse;
import com.llw.goodweather.utils.WeatherUtil;
import java.util.List;
/**
* 天气预报列表展示适配器
*/
public class WeatherForecastAdapter extends BaseQuickAdapter<WeatherForecastResponse.HeWeather6Bean.DailyForecastBean, BaseViewHolder> {
public WeatherForecastAdapter(int layoutResId, @Nullable List<WeatherForecastResponse.HeWeather6Bean.DailyForecastBean> data) {
super(layoutResId, data);
}
@Override
protected void convert(BaseViewHolder helper, WeatherForecastResponse.HeWeather6Bean.DailyForecastBean item) {
helper.setText(R.id.tv_date, item.getDate())//日期
// .setText(R.id.tv_info, item.getCond_txt_d())//天气
.setText(R.id.tv_low_and_height, item.getTmp_min() + "/" + item.getTmp_max() + "℃");//最低温和最高温
//天气状态图片
ImageView weatherStateIcon = helper.getView(R.id.iv_weather_state);
int code = Integer.parseInt(item.getCond_code_d());//获取天气状态码,根据状态码来显示图标
WeatherUtil.changeIcon(weatherStateIcon,code);//调用工具类中写好的方法
}
}
因为写作过程中,还有其他事情,所以并不是一蹴而就的,当我写适配器代码的时候就我的邮箱就已经收到通过审核的短信了,你如果没有收到也不要着急,只要资料没有问题,审核还是蛮快的,关键看审核的人员那个时候有没有帮你审核。现在我成为一个认证开发者了,那么可以直接运行一下。
再切换一个城市
从这个运行的效果图来看,完成了两件事,第一个就是未来七天的天气预报,这个只要你通过了审核,成为开发者,返回的数据自然就变成7天的,第二个就是UI优化,感觉图标显示还是比文字显示更好一些,这个就属于细节优化问题了,因为这个细节,你还是要做很多准备工作的。
https://free-api.heweather.net/s6/weather/hourly?location=%E7%A6%8F%E7%94%B0&key=3086e91d66c04ce588a7f538f917c7f4
访问测试地址,请以自己的Key去访问,返回的结果
在bean包下创建一个HourlyResponse.java,里面的代码如下:
package com.llw.goodweather.bean;
import java.util.List;
public class HourlyResponse {
private List<HeWeather6Bean> HeWeather6;
public List<HeWeather6Bean> getHeWeather6() {
return HeWeather6;
}
public void setHeWeather6(List<HeWeather6Bean> HeWeather6) {
this.HeWeather6 = HeWeather6;
}
public static class HeWeather6Bean {
/**
* basic : {"cid":"CN101280603","location":"福田","parent_city":"深圳","admin_area":"广东","cnty":"中国","lat":"22.5410099","lon":"114.05095673","tz":"+8.00"}
* update : {"loc":"2020-04-28 19:56","utc":"2020-04-28 11:56"}
* status : ok
* hourly : [{"cloud":"43","cond_code":"101","cond_txt":"多云","dew":"19","hum":"71","pop":"0","pres":"1010","time":"2020-04-28 22:00","tmp":"23","wind_deg":"82","wind_dir":"东风","wind_sc":"1-2","wind_spd":"2"},{"cloud":"35","cond_code":"100","cond_txt":"晴","dew":"18","hum":"74","pop":"0","pres":"1011","time":"2020-04-29 01:00","tmp":"22","wind_deg":"14","wind_dir":"东北风","wind_sc":"1-2","wind_spd":"11"},{"cloud":"69","cond_code":"100","cond_txt":"晴","dew":"18","hum":"72","pop":"0","pres":"1011","time":"2020-04-29 04:00","tmp":"21","wind_deg":"43","wind_dir":"东北风","wind_sc":"1-2","wind_spd":"4"},{"cloud":"90","cond_code":"101","cond_txt":"多云","dew":"19","hum":"62","pop":"0","pres":"1008","time":"2020-04-29 07:00","tmp":"21","wind_deg":"53","wind_dir":"东北风","wind_sc":"1-2","wind_spd":"9"},{"cloud":"91","cond_code":"101","cond_txt":"多云","dew":"19","hum":"58","pop":"0","pres":"1008","time":"2020-04-29 10:00","tmp":"27","wind_deg":"45","wind_dir":"东北风","wind_sc":"1-2","wind_spd":"10"},{"cloud":"75","cond_code":"101","cond_txt":"多云","dew":"18","hum":"59","pop":"0","pres":"1009","time":"2020-04-29 13:00","tmp":"29","wind_deg":"32","wind_dir":"东北风","wind_sc":"1-2","wind_spd":"4"},{"cloud":"59","cond_code":"100","cond_txt":"晴","dew":"18","hum":"60","pop":"0","pres":"1009","time":"2020-04-29 16:00","tmp":"27","wind_deg":"50","wind_dir":"东北风","wind_sc":"1-2","wind_spd":"6"},{"cloud":"37","cond_code":"101","cond_txt":"多云","dew":"19","hum":"61","pop":"0","pres":"1008","time":"2020-04-29 19:00","tmp":"26","wind_deg":"-1","wind_dir":"无持续风向","wind_sc":"1-2","wind_spd":"2"}]
*/
private BasicBean basic;
private UpdateBean update;
private String status;
private List<HourlyBean> hourly;
public BasicBean getBasic() {
return basic;
}
public void setBasic(BasicBean basic) {
this.basic = basic;
}
public UpdateBean getUpdate() {
return update;
}
public void setUpdate(UpdateBean update) {
this.update = update;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public List<HourlyBean> getHourly() {
return hourly;
}
public void setHourly(List<HourlyBean> hourly) {
this.hourly = hourly;
}
public static class BasicBean {
/**
* cid : CN101280603
* location : 福田
* parent_city : 深圳
* admin_area : 广东
* cnty : 中国
* lat : 22.5410099
* lon : 114.05095673
* tz : +8.00
*/
private String cid;
private String location;
private String parent_city;
private String admin_area;
private String cnty;
private String lat;
private String lon;
private String tz;
public String getCid() {
return cid;
}
public void setCid(String cid) {
this.cid = cid;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getParent_city() {
return parent_city;
}
public void setParent_city(String parent_city) {
this.parent_city = parent_city;
}
public String getAdmin_area() {
return admin_area;
}
public void setAdmin_area(String admin_area) {
this.admin_area = admin_area;
}
public String getCnty() {
return cnty;
}
public void setCnty(String cnty) {
this.cnty = cnty;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public String getLon() {
return lon;
}
public void setLon(String lon) {
this.lon = lon;
}
public String getTz() {
return tz;
}
public void setTz(String tz) {
this.tz = tz;
}
}
public static class UpdateBean {
/**
* loc : 2020-04-28 19:56
* utc : 2020-04-28 11:56
*/
private String loc;
private String utc;
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
public String getUtc() {
return utc;
}
public void setUtc(String utc) {
this.utc = utc;
}
}
public static class HourlyBean {
/**
* cloud : 43
* cond_code : 101
* cond_txt : 多云
* dew : 19
* hum : 71
* pop : 0
* pres : 1010
* time : 2020-04-28 22:00
* tmp : 23
* wind_deg : 82
* wind_dir : 东风
* wind_sc : 1-2
* wind_spd : 2
*/
private String cloud;
private String cond_code;
private String cond_txt;
private String dew;
private String hum;
private String pop;
private String pres;
private String time;
private String tmp;
private String wind_deg;
private String wind_dir;
private String wind_sc;
private String wind_spd;
public String getCloud() {
return cloud;
}
public void setCloud(String cloud) {
this.cloud = cloud;
}
public String getCond_code() {
return cond_code;
}
public void setCond_code(String cond_code) {
this.cond_code = cond_code;
}
public String getCond_txt() {
return cond_txt;
}
public void setCond_txt(String cond_txt) {
this.cond_txt = cond_txt;
}
public String getDew() {
return dew;
}
public void setDew(String dew) {
this.dew = dew;
}
public String getHum() {
return hum;
}
public void setHum(String hum) {
this.hum = hum;
}
public String getPop() {
return pop;
}
public void setPop(String pop) {
this.pop = pop;
}
public String getPres() {
return pres;
}
public void setPres(String pres) {
this.pres = pres;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getTmp() {
return tmp;
}
public void setTmp(String tmp) {
this.tmp = tmp;
}
public String getWind_deg() {
return wind_deg;
}
public void setWind_deg(String wind_deg) {
this.wind_deg = wind_deg;
}
public String getWind_dir() {
return wind_dir;
}
public void setWind_dir(String wind_dir) {
this.wind_dir = wind_dir;
}
public String getWind_sc() {
return wind_sc;
}
public void setWind_sc(String wind_sc) {
this.wind_sc = wind_sc;
}
public String getWind_spd() {
return wind_spd;
}
public void setWind_spd(String wind_spd) {
this.wind_spd = wind_spd;
}
}
}
}
页面渲染的数据从这些返回实体里面取,下一步,创建接口,打开ApiService.java
在里面增加
注意Key用自己的,然后创建订阅,打开WeatherContract.java
订阅方法
/**
* 逐小时预报
* @param context
* @param location
*/
public void hourly(final Context context,String location){
ApiService service = ServiceGenerator.createService(ApiService.class,0);
service.getHourly(location).enqueue(new NetCallBack<HourlyResponse>() {
@Override
public void onSuccess(Call<HourlyResponse> call, Response<HourlyResponse> response) {
if(getView() != null){
getView().getHourlyResult(response);
}
}
@Override
public void onFailed() {
if(getView() != null){
getView().getDataFailed();
}
}
});
}
接口返回值
//查询逐小时天气的数据返回
void getHourlyResult(Response<HourlyResponse> response);
接下来就是MainActivity.java
代码如下:
//逐小时天气预报返回
@Override
public void getHourlyResult(Response<HourlyResponse> response) {
dismissLoadingDialog();//关闭弹窗
if (("ok").equals(response.body().getHeWeather6().get(0).getStatus())) {
} else {
ToastUtils.showShortToast(context, response.body().getHeWeather6().get(0).getStatus());
}
}
需要在三个地方进行请求,拿到定位之后、下拉的时候、切换城市之后
通过断点查看到了返回的数据,这一步你可以跳过,不会有什么影响,往下走
现在数据已经拿到了,接下来就是数据的渲染了,依然使用列表来做显示,这里我们用横向的列表,摆放的位置就放在7天天气预报的上方,这样会比较合理。
接下来在layout下创建一个item_weather_hourly_list.xml文件,
这就是每一个item的显示效果,只不过背景是无色的,这里之所以放黑色背景,是在写布局的时候易于调整。
item_weather_hourly_list.xml代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center_horizontal"
android:padding="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<!--时间-->
<TextView
android:id="@+id/tv_time"
android:textColor="#FFF"
android:text="上午10:00"
android:textSize="14sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<!--气候图标-->
<ImageView
android:layout_marginTop="12dp"
android:layout_marginBottom="8dp"
android:id="@+id/iv_weather_state"
android:background="@mipmap/icon_100"
android:layout_width="30dp"
android:layout_height="30dp"/>
<!--温度-->
<TextView
android:textSize="20sp"
android:id="@+id/tv_temperature"
android:textColor="#FFF"
android:text="25℃"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
然后在WeatherUtil.java中再增加一个方法showTimeInfo
/**
* 根据传入的时间显示时间段描述信息
* @param timeData
* @return
*/
public static String showTimeInfo(String timeData){
String timeInfo = null;
int time = 0;
time = Integer.parseInt(timeData.trim().substring(0,2));
if (time >= 0 && time <= 6) {
timeInfo = "凌晨";
}else if (time > 6 && time <= 12) {
timeInfo = "上午";
}else if (time > 12 && time <= 13) {
timeInfo = "中午";
}else if (time > 13 && time <= 18) {
timeInfo = "下午";
} else if (time > 18 && time <= 24) {
timeInfo = "晚上";
} else {
timeInfo = "未知";
}
return timeInfo;
}
接下来在adapter包下创建一个WeatherHourlyAdapter.java
package com.llw.goodweather.adapter;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.llw.goodweather.R;
import com.llw.goodweather.bean.HourlyResponse;
import com.llw.goodweather.utils.WeatherUtil;
import java.util.List;
public class WeatherHourlyAdapter extends BaseQuickAdapter<HourlyResponse.HeWeather6Bean.HourlyBean, BaseViewHolder> {
public WeatherHourlyAdapter(int layoutResId, @Nullable List<HourlyResponse.HeWeather6Bean.HourlyBean> data) {
super(layoutResId, data);
}
@Override
protected void convert(BaseViewHolder helper, HourlyResponse.HeWeather6Bean.HourlyBean item) {
//首先是对时间格式的处理,因为拿到的时间是 2020-04-28 22:00 要改成 晚上22:00
//分两步,第一个是字符串的截取,第二个是时间段的判断返回文字描述
String datetime = item.getTime();//赋值
String time = datetime.substring(11);//截去前面的字符,保留后面所有的字符,就剩下 22:00
helper.setText(R.id.tv_time,WeatherUtil.showTimeInfo(time)+time)//时间
.setText(R.id.tv_temperature,item.getTmp()+"℃");//温度
//天气状态图片
ImageView weatherStateIcon = helper.getView(R.id.iv_weather_state);
int code = Integer.parseInt(item.getCond_code());//获取天气状态码,根据状态码来显示图标
WeatherUtil.changeIcon(weatherStateIcon,code);
}
}
适配器写完了,接下来修改一下activity_main.xml布局文件
icon_weather_sun.png
上方是一个图标。因为是白色所以你看到不到而已
我改动之前的这个更新时间的布局,下方放了一个分割线和一个列表,列表用于显示逐小时天气、原来的天气预报列表增加了内边距
修改地方的代码如下:
<!--上一次更新时间-->
<LinearLayout
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:drawableLeft="@mipmap/icon_weather_sun"
android:drawablePadding="4dp"
android:text="Good Weather"
android:textSize="@dimen/sp_12"
android:textColor="#FFF"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:gravity="right"
android:id="@+id/tv_old_time"
android:textColor="#FFF"
android:text="上次更新时间:"
android:textSize="@dimen/sp_12"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>
</LinearLayout>
<!--分隔线 增加UI效果-->
<View
android:layout_marginTop="8dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#FFF"
android:alpha="0.1"/>
<!--用于显示逐小时天气-->
<androidx.recyclerview.widget.RecyclerView
android:padding="12dp"
android:id="@+id/rv_hourly"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<!--用于显示天气预报数据-->
<androidx.recyclerview.widget.RecyclerView
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
接下来就是在MainActivity.java中渲染数据了。
初始列表和适配器
List<HourlyResponse.HeWeather6Bean.HourlyBean> mListHourly;//初始化数据源 -> 逐小时天气预报
WeatherHourlyAdapter mAdapterHourly;//初始化适配器 逐小时天气预报
改动的地方大概就这么多了,然后可以运行一下了。
运行效果图如下
这一篇文章就结束了,但是这个APP并没有结束,后续我有什么想法还会一直在里面加,当然各位有什么好的建议也可以评论或者私信我,写完才发现这篇文章也有34000多字,说短也不短了,如果你看了里面的内容不明白的话,就请从第一篇看起,你就一定知道是怎么回事了。
源码地址:GoodWeather
欢迎 Star 和 Fork
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。