快捷切换常用城市及每日弹窗优化
前言
在2021年正式到来之前再更新几篇天气APP的文章,说实话现在对于这个APP的更新速度是比较缓慢的,一方面我有工作在进行,同时在写其他的文章,其次我正在使用Kotlin语言重写天气APP,还有一个原因就是功能的迭代问题,因为作为天气APP该满足用户的其实都已经满足了,我本来还有好多的想法打算加进去,又怕这个变得不伦不类,因此有些东西就搁置了,而这篇文章就是在对于用户的体验上做提升,嗯,来看看吧。
正文
快捷切换城市自然要在App的主页面进行了,那么首先修改一下布局文件activity_main.xml。
<!--切换城市--> <!--常用城市快捷切换--> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:animateLayoutChanges="true"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rv_change_city" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="12dp" android:visibility="gone" /> </LinearLayout>
放置的位置就在城市的下方,只不过是隐藏的列表,所以你还看不见的。
然后在MainActivity绑定控件
@BindView(R.id.rv_change_city) RecyclerView rvChangeCity;//点击切换常用城市
再创建两个变量用于控制是否显示和是否展开常用城市列表
private boolean changeCityState = false;//常用城市列表 收缩状态 false 收缩 true 展开 private boolean isChangeCity = false;//是否可以展开,如果没有添加常用城市,自然不能展开
一、创建适配器
既然有列表自然就有适配器。然后在layout中创建一个item_main_city_change.xml
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tv_city" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/selected_bg_color" android:paddingStart="@dimen/dp_16" android:paddingTop="@dimen/dp_4" android:paddingEnd="@dimen/dp_16" android:paddingBottom="@dimen/dp_4" android:text="常用城市" android:textColor="@drawable/selected_text_color" android:textSize="@dimen/sp_18" />
这里我改变了触摸item时的背景样式和文字颜色样式,样式都放在drawable下。
selected_bg_color.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@drawable/selected_bg_radius"/> </selector>
selected_bg_radius.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="@color/white_4"/> <corners android:radius="@dimen/dp_12"/> </shape>
selected_text_color.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:color="@color/white"/> <item android:state_pressed="false" android:color="@color/white_8"/> </selector>
item写完了,下面到适配器了。
在adapter包下新建一个MainChangeCommonlyCityAdapter类,代码如下:
package com.llw.goodweather.adapter; 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.mvplibrary.bean.ResidentCity; import java.util.List; /** * 主页面左右滑动切换常用城市列表适配器 * * @author llw */ public class MainChangeCommonlyCityAdapter extends BaseQuickAdapter<ResidentCity, BaseViewHolder> { public MainChangeCommonlyCityAdapter(int layoutResId, @Nullable List<ResidentCity> data) { super(layoutResId, data); } @Override protected void convert(BaseViewHolder helper, ResidentCity item) { helper.setText(R.id.tv_city, item.getLocation()) .addOnClickListener(R.id.tv_city); } }
二、配置列表加载常用城市数据
刚才适配器写好了,然后进入到MainActivity中,再创建两个变量
//主页面切换城市列表适配器 private MainChangeCommonlyCityAdapter changeCityAdapter; //常用城市切换列表 private List<ResidentCity> residentCityList = new ArrayList<>();
一个适配器一个数据列表,然后下面新增一个方法用于加载适配器数据并且渲染,还有点击事件。这里先查询数据,然后判断数据,之后渲染数据,最后是点击item之后搜索城市,然后查找天气数据。
/** * 加载常用城市数据 */ private void loadingCommonlyUsedCity() { residentCityList = LitePal.findAll(ResidentCity.class); //先判断是否有常用城市 if (residentCityList != null && residentCityList.size() > 0) { isChangeCity = true; } else { isChangeCity = false; } //配置适配器 changeCityAdapter = new MainChangeCommonlyCityAdapter(R.layout.item_main_city_change, residentCityList); LinearLayoutManager manager = new LinearLayoutManager(context); manager.setOrientation(RecyclerView.HORIZONTAL); rvChangeCity.setLayoutManager(manager); rvChangeCity.setAdapter(changeCityAdapter); //常用城市点击 changeCityAdapter.setOnItemChildClickListener((adapter, view, position) -> { showLoadingDialog(); district = residentCityList.get(position).getLocation(); mPresent.newSearchCity(district); flag = false; //隐藏列表 rvChangeCity.setVisibility(View.GONE); changeCityState = false; }); }
三、添加到常用城市列表
这里我判断了一下是否为定位城市的返回,是的话我就添加到数据库中,当然也不能重复添加数据,因此还需要判断一下。
/** * 添加到常用城市列表 * * @param locationBean */ private void addCommonlyUsedCity(NewSearchCityResponse.LocationBean locationBean) { if (flag) {//定位到的城市 List<ResidentCity> residentCityList = LitePal.findAll(ResidentCity.class); if (residentCityList != null && residentCityList.size() > 0) { //查询要添加的城市是否已经存在 List<ResidentCity> residentCities = LitePal .where("location = ? and parent_city = ?", locationBean.getName(), locationBean.getAdm2()) .find(ResidentCity.class); if (residentCities.size() == 0) { ResidentCity residentCity = new ResidentCity(); residentCity.setLocation(locationBean.getName());//地区/城市名称 residentCity.setParent_city(locationBean.getAdm2());//该地区/城市的上级城市 residentCity.setAdmin_area(locationBean.getAdm1());//该地区/城市所属行政区域 residentCity.setCnty(locationBean.getCountry());//该地区/城市所属国家名称 residentCity.save();//保存数据到数据库中 } } else { ResidentCity residentCity = new ResidentCity(); residentCity.setLocation(locationBean.getName());//地区/城市名称 residentCity.setParent_city(locationBean.getAdm2());//该地区/城市的上级城市 residentCity.setAdmin_area(locationBean.getAdm1());//该地区/城市所属行政区域 residentCity.setCnty(locationBean.getCountry());//该地区/城市所属国家名称 residentCity.save();//保存数据到数据库中 } } //加载常用城市数据 loadingCommonlyUsedCity(); }
然后你还需要在initData中调用loadingCommonlyUsedCity方法。
其次就是在接收事件的时候再加载一次数据,因为我在常用城市中添加数据之后会发起事件,然后关闭常用城市页面,回到主页面,此时需要把数据加载一下,后面会演示一下。
四、修改UI
因为我是点击城市触发常用城市列表的判断处理,因此之前的代码需要修改一下,有两处,在initData中
在onReceiveLocation方法中
最后在tv_city的点击事件中先判断当前城市是否定位到,定位到则判断有无数据,有数据则可以判断点击后不同的控件样式。
那么下面就可以运行一下了。
文末
这篇文章比较的简洁,那么也到这里了,山高水长,后会有期~