Android 天气APP(十七)热门城市 - 国内城市
上一篇:Android 天气APP(十六)热门城市 - 海外城市
页面标题优化、添加加载弹窗
- 新版-------------------
- 一、主页面标题栏优化
- 二、加载等待弹窗
- 三、文章源码
- 旧版-------------------
- 前言
- 正文
- ① 修改API
- ② 修改订阅器
- ③ 创建选择弹窗
- ④ 修改列表item布局
- ⑤ 修改列表适配器
- ⑥ 样式调整
新版-------------------
在上一篇文章中完成了关于添加城市时通过搜索城市的方式,本篇文章就是对UI上进行一些优化,来看看有那些优化。
一、主页面标题栏优化
当前主页面布局activity_main.xml的标题代码如下:
<com.google.android.material.appbar.MaterialToolbarandroid: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"><TextViewandroid: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>
可以看到这里是用的一个MaterialToolbar,里面放置了TextView,将TextView作为标题,现在我们去掉这个TextView,直接使用MaterialToolbar,修改后代码如下所示:
<com.google.android.material.appbar.MaterialToolbarandroid:id="@+id/materialToolbar"android:layout_width="match_parent"android:layout_height="wrap_content"android:fitsSystemWindows="true"app:title="城市天气"app:titleTextColor="@color/white"app:titleCentered="true"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"/>
然后在代码中我们滑动的时候就要修改MaterialToolbar的title的内容,看一下MainActivity。
这里有报错,很正常,因为这个TextView已经被删掉了,那么我们替换一下,如下图所示:
还有一个地方需要修改
这里将setTitle的内容改成城市天气。
下面运行一下效果就和之前是差不多的了。
二、加载等待弹窗
现在进入主页面时会请求网络数据,然后会发现需要等一段时间才会显示所有数据,为了增加用户体验,现在增加一个加载弹窗,在请求网络数据的事情显示加载弹窗,然后在数据返回时隐藏弹窗,为了更好的时候,我将这个弹窗直接写到BaseActivity中,因为BaseActivity是在library模块中,所以下面的代码都是在library模块中增加。
首先在main下创建一个res文件夹,res下创建一个values文件夹,values文件夹下创建一个styles.xml文件,里面的代码如下所示:
<?xml version="1.0" encoding="utf-8"?>
<resources><!--加载弹窗的样式--><style name="loading_dialog" parent="@android:style/Theme.Dialog"><item name="android:windowFrame">@null</item><item name="android:windowIsFloating">true</item><item name="android:windowIsTranslucent">true</item><item name="android:windowNoTitle">true</item><item name="android:background">@null</item><item name="android:windowBackground">@null</item><item name="android:backgroundDimEnabled">false</item></style>
</resources>
这是弹窗的样式,下面在res下创建一个drawable文件夹,drawable文件夹下创建一个shape_loading_bg.xml文件,代码如下所示:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><corners android:radius="12dp" /><solid android:color="#90000000" />
</shape>
这是弹窗的背景样式,drawable下还有一个ic_loading.png的图标,你可以去我的源码中拿,贴出来尺寸格式就变了,下面就是写代码,在com.llw.library包下新建一个view包,里面创建一个LoadingView类,代码如下:
public class LoadingView extends androidx.appcompat.widget.AppCompatImageView {private int mCenterRotateX;//图片旋转点xprivate int mCenterRotateY;//图片旋转点yprivate LoadingRunnable mRunnable;public LoadingView(Context context) {this(context, null);}public LoadingView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public LoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {setScaleType(ScaleType.MATRIX);Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_loading);setImageBitmap(bitmap);mCenterRotateX = bitmap.getWidth() / 2;mCenterRotateY = bitmap.getHeight() / 2;}/*** onDraw()之前调用*/@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();if (mRunnable==null){mRunnable=new LoadingRunnable(this);}if (!mRunnable.isLoading){mRunnable.start();}}/*** view销毁时调用*/@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();if (mRunnable!=null){mRunnable.stop();}mRunnable=null;}class LoadingRunnable implements Runnable {private boolean isLoading;private final Matrix mMatrix;private final SoftReference<LoadingView> mLoadingViewSoftReference;private float mDegrees = 0f;public LoadingRunnable(LoadingView loadingView) {mLoadingViewSoftReference = new SoftReference<LoadingView>(loadingView);mMatrix = new Matrix();}@Overridepublic void run() {if (mLoadingViewSoftReference.get().mRunnable != null) {mDegrees += 30f;mMatrix.setRotate(mDegrees, mCenterRotateX, mCenterRotateY);mLoadingViewSoftReference.get().setImageMatrix(mMatrix);if (mDegrees==360){mDegrees=0f;}if (isLoading) {mLoadingViewSoftReference.get().postDelayed(mLoadingViewSoftReference.get().mRunnable, 100);}}}public void stop() {isLoading = false;}public void start() {isLoading = true;if (mLoadingViewSoftReference.get().mRunnable != null) {mLoadingViewSoftReference.get().postDelayed(mLoadingViewSoftReference.get().mRunnable, 100);}}}
}
这是一个旋转图片的View, 下面在view包下新建一个LoadingTextView类,代码如下:
public class LoadingTextView extends AppCompatTextView {private LinearGradient mLinearGradient;private Matrix mGradientMatrix;private int mViewWidth = 0;private int mTranslate = 0;public LoadingTextView(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);if (mViewWidth == 0) {mViewWidth = getMeasuredWidth();if (mViewWidth > 0) {Paint mPaint = getPaint();mLinearGradient = new LinearGradient(-mViewWidth, 0, 0, 0,new int[]{0x33ffffff, 0xff3286ED, 0x33ffffff},new float[]{0, 0.6f, 1}, Shader.TileMode.CLAMP);mPaint.setShader(mLinearGradient);mGradientMatrix = new Matrix();}}}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (mGradientMatrix != null) {mTranslate += mViewWidth / 10;if (mTranslate > 2 * mViewWidth) {mTranslate = -mViewWidth;}mGradientMatrix.setTranslate(mTranslate, 0);mLinearGradient.setLocalMatrix(mGradientMatrix);postInvalidateDelayed(20);}}
}
这里是加载弹窗的提示文字,里面的文字颜色是跑马灯效果,下面在res下新建一个layout文件夹,layout下新建一个dialog_loading.xml,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/layout_loading"android:layout_width="120dp"android:layout_height="120dp"android:layout_gravity="center"android:background="@drawable/shape_loading_bg"android:gravity="center"android:orientation="vertical"><!--旋转的图--><com.llw.library.view.LoadingViewandroid:layout_width="wrap_content"android:layout_height="wrap_content" /><!--变色的字--><com.llw.library.view.LoadingTextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="12dp"android:text="请稍后..."android:textColor="#fff"android:textSize="14sp" />
</LinearLayout>
现在关于加载弹窗的资源都准备好了,下面就是在BaseActivity中添加显示和隐藏加载弹窗的方法代码,如下所示:
private Dialog mDialog;protected void showLoadingDialog() {if (mDialog == null) {mDialog = new Dialog(mContext, R.style.loading_dialog);}mDialog.setContentView(R.layout.dialog_loading);mDialog.setCancelable(true);mDialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);mDialog.show();}protected void dismissLoadingDialog() {if (mDialog != null) {mDialog.dismiss();}mDialog = null;}
下面我们就可以在MainActivity中使用了,在获取定位结果的时候显示这个弹窗,如图所示:
在空气质量数据返回的时候隐藏这个弹窗
这个弹窗你手动点击页面其他区域也会隐藏,问题不大,下面运行一下看看效果。
三、文章源码
欢迎 Star 和 Fork
第十七篇文章源码地址: GoodWeather-New-17
旧版-------------------
前言
在上一篇做了国外的热门城市数据的展示,这一篇就简单一些,增加国内的热门城市。
效果图
正文
① 修改API
在ApiService中修改hotCity这个接口,将固定地址里面的group分离出来,作为请求参数。
/*** 热门城市(包含海外和国内)*/@GET("/top?key=3086e91d66c04ce588a7f538f917c7f4&number=50&lang=zh")Call<HotCityResponse> hotCity(@Query("group") String group);
② 修改订阅器
在HotCityContract中增加一个参数
③ 创建选择弹窗
之前是在HotActivity中默认查询海外热门城市的,现在增加了一个参数,就需要用户去手动选择了,我们可以通过一个弹窗来进行选择。
在layout下创建
布局代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="@dimen/dp_280"android:layout_height="@dimen/dp_120"android:background="@drawable/shape_white_5"android:gravity="center"android:orientation="vertical"><!--国内--><TextViewandroid:id="@+id/tv_inland"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:foreground="@drawable/bg_white"android:gravity="center"android:text="国内热门城市"android:textColor="@color/black"android:textSize="@dimen/sp_18" /><!--分割线--><Viewandroid:layout_width="match_parent"android:layout_height="0.5dp"android:background="@color/gray" /><!--海外--><TextViewandroid:id="@+id/tv_foreign"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:foreground="@drawable/bg_white"android:gravity="center"android:text="海外热门城市"android:textColor="@color/black"android:textSize="@dimen/sp_18" />
</LinearLayout>
然后就是使用了,我修改了一下LiWindow中的showCenterPopupWindow方法中的入参
将这个值放到外面就可以在调用的时候设置是否可以点击空白处关闭弹窗,为true是可以,false是不可以。
修改activity_hot_city.xml布局文件,完整代码如下,复制粘贴即可
<?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"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:fitsSystemWindows="true"android:id="@+id/lay_bg"android:orientation="vertical"android:layout_height="match_parent"tools:context=".ui.HotCityActivity"><androidx.appcompat.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"android:background="@color/white"app:layout_constraintEnd_toEndOf="parent"app:navigationIcon="@mipmap/icon_return"app:contentInsetLeft="@dimen/dp_16"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintTop_toTopOf="parent"app:popupTheme="@style/AppTheme.PopupOverlay"><TextViewandroid:id="@+id/tv_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:textSize="@dimen/sp_16"android:textColor="@color/black"android:text="热门城市" /></androidx.appcompat.widget.Toolbar><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv"android:layout_width="match_parent"android:layout_height="match_parent"/>
</LinearLayout>
修改的布局有什么变化呢?就是里面的布局增加了id,还有就是改了颜色,
之后在HotCityActivity中初始化
上图中标出来的就是新增的,然后创建一个显示弹窗的方法
/*** 显示选择类型弹窗*/private void showTypeWindow() {liWindow = new LiWindow(context);final View view = LayoutInflater.from(context).inflate(R.layout.window_hot_type, null);TextView tvInland = view.findViewById(R.id.tv_inland);//国内TextView tvForeign = view.findViewById(R.id.tv_foreign);//海外tvInland.setOnClickListener(v -> {type = 0;initList(type);showLoadingDialog();mPresent.hotCity(context, "cn");liWindow.closePopupWindow();});tvForeign.setOnClickListener(v -> {type = 1;initList(type);showLoadingDialog();mPresent.hotCity(context, "overseas");liWindow.closePopupWindow();});liWindow.showCenterPopupWindow(view, SizeUtils.dp2px(context, 280), SizeUtils.dp2px(context, 120), false);}
因为是要在页面启动的时候就出现这个弹窗,而popupWindow显示依赖activity,并且要等activity所有的生命周期方法全部执行完成才能显示,所以这里新开一个线程用于显示
④ 修改列表item布局
弹窗搞定之后就可以改动热门城市的列表item布局了,首先增加一个颜色
item_hot_city_list.xml布局完整代码如下:
<?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:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><androidx.cardview.widget.CardViewandroid:id="@+id/item_hot_city"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="@dimen/dp_6"android:foreground="@drawable/bg_white"app:cardBackgroundColor="@color/white"app:cardCornerRadius="@dimen/dp_8"app:cardElevation="@dimen/dp_4"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:orientation="horizontal"><!--增加id--><ImageViewandroid:id="@+id/iv_mark"android:layout_width="@dimen/dp_80"android:layout_height="@dimen/dp_80"android:background="@drawable/shape_orange_8"android:gravity="center"android:padding="@dimen/dp_20"android:src="@mipmap/icon_hot_city" /><LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center_vertical"android:orientation="vertical"android:paddingLeft="@dimen/dp_16"><TextViewandroid:id="@+id/tv_hot_city_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="巴黎"android:textColor="@color/black_3"android:textSize="@dimen/sp_16"android:textStyle="bold" /><TextViewandroid:id="@+id/tv_cnty_and_area"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="@dimen/dp_8"android:text="巴黎"android:textColor="@color/gray"android:textSize="@dimen/sp_14"android:textStyle="bold" /></LinearLayout><!--增加id--><ImageViewandroid:id="@+id/iv_open"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="@dimen/dp_12"android:src="@mipmap/icon_open_orange" /></LinearLayout></androidx.cardview.widget.CardView>
</LinearLayout>
图标也是要修改的
因为是白色的你看不见很正常,你把页面的主题改成黑色就可以看到了。
icon_hot_city_china.ping
icon_open_blue.png
⑤ 修改列表适配器
修改HotCityAdapter
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.HotCityResponse;import java.util.ArrayList;
import java.util.List;/*** 热门城市列表适配器*/
public class HotCityAdapter extends BaseQuickAdapter<HotCityResponse.HeWeather6Bean.BasicBean, BaseViewHolder> {private int mType;// 增加一个item样式类型,在Activity中传入public HotCityAdapter(int layoutResId, @Nullable List<HotCityResponse.HeWeather6Bean.BasicBean> data,int type) {super(layoutResId, data);this.mType = type;}@Overrideprotected void convert(BaseViewHolder helper, HotCityResponse.HeWeather6Bean.BasicBean item) {ImageView ivMark = helper.getView(R.id.iv_mark);ImageView ivOpen = helper.getView(R.id.iv_open);if (mType == 0) {//国内ivMark.setBackground(mContext.getResources().getDrawable(R.drawable.shape_blue_8));//背景ivMark.setImageDrawable(mContext.getDrawable(R.mipmap.icon_hot_city_china));//图标ivOpen.setImageDrawable(mContext.getDrawable(R.mipmap.icon_open_blue));//图标} else {//国外ivMark.setBackground(mContext.getResources().getDrawable(R.drawable.shape_orange_8));//背景ivMark.setImageDrawable(mContext.getDrawable(R.mipmap.icon_hot_city));//图标ivOpen.setImageDrawable(mContext.getDrawable(R.mipmap.icon_open_orange));//图标}helper.setText(R.id.tv_hot_city_name,item.getLocation()).setText(R.id.tv_cnty_and_area,item.getCnty()+" —— "+item.getAdmin_area());helper.addOnClickListener(R.id.item_hot_city);}}
⑥ 样式调整
然后回到HotCityActivity中首先是在initList方法中增加一个入参
这样传入的类型就会影响到适配器中的样式了,最后一步就是在getHotCityResult方法中对返回值中做数据的处理了。
新增部分的代码如下:
toolbar.setNavigationIcon(getResources().getDrawable(R.mipmap.icon_return_white));//返回箭头颜色tvTitle.setTextColor(getResources().getColor(R.color.white));//标题颜色if (type == 0) {//标题判断tvTitle.setText("国内热门城市");StatusBarUtil.setStatusBarColor(context, R.color.blue_one);//蓝色底状态栏toolbar.setBackgroundColor(getResources().getColor(R.color.blue_one));//标题 蓝色layBg.setBackgroundColor(getResources().getColor(R.color.shallow_blue));//背景 蓝色} else {tvTitle.setText("海外热门城市");StatusBarUtil.setStatusBarColor(context, R.color.orange);//橙色底 状态栏toolbar.setBackgroundColor(getResources().getColor(R.color.orange));//标题 橙色layBg.setBackgroundColor(getResources().getColor(R.color.shallow_orange));//背景 橙色}
运行一下,看看效果
源码地址:GoodWeather
欢迎 Star 和 Fork
下一篇:Android 天气APP(十八)常用城市
Android 天气APP(十七)热门城市 - 国内城市相关推荐
- Android 天气APP(十八)常用城市
上一篇:Android 天气APP(十七)热门城市 - 国内城市 完成此篇文章实现的效果图如下: 前言 常用城市对于那些经常在外面出差的朋友来说相信是不陌生的,因为涉及到在不同城市之间居住,所以对于其 ...
- Android 天气APP(十五)增加城市搜索、历史搜索记录
上一篇:Android 天气APP(十四)修复UI显示异常.优化业务代码逻辑.增加详情天气显示 添加城市 新版------------------- 一.推荐城市数据 二.推荐城市item布局和适配器 ...
- Android 天气APP(七)城市切换 之 城市数据源
上一篇:Android 天气APP(六)旋转风车显示风力.风向 9. 城市选择 既然是城市切换,那么首先得有城市的数据,数据来源有两种,本地和网络,但是网络数据对手机的网络要求比较高,看起来会延迟很大 ...
- Android 天气APP(三十二)快捷切换常用城市
上一篇:Android 天气APP(三十一)每日提醒弹窗 快捷切换常用城市及每日弹窗优化 前言 正文 一.创建适配器 二.配置列表加载常用城市数据 三.添加到常用城市列表 四.修改UI 文末 前言 ...
- Android 天气APP(二十七)增加地图天气的逐小时天气、太阳和月亮数据
上一篇:Android 天气APP(二十六)增加自动更新(检查版本.通知栏下载.自动安装) 效果图 开发流程 1.功能优化 2.地图天气中增加逐小时天气 3.地图天气中增加太阳和月亮数据 1.功能优化 ...
- Android 天气APP(四)搭建MVP框架与使用
上一篇:Android 天气APP(三)访问天气API与数据请求 MVP/MVVM框架搭建与使用 新版------------------- 一.创建依赖模块 二.模块初始化 三.搭建网络框架 四.基 ...
- Android 天气APP(二十六)增加自动更新(检查版本、通知栏下载、自动安装)
上一篇:Android 天气APP(二十五)地图天气(下)嵌套滑动布局渲染天气数据 效果图 开发流程 1.开发前言 2.上传应用到分发平台 3.版本数据请求与存储 4.检查版本更新.自定义更新提示弹窗 ...
- 制作一个功能丰富的Android天气App
简易天气是一个基于和风天气数据采用MD设计的Android天气App.目前的版本采用传统的MVC模式构建.通过丰富多彩的页面为用户提供日常所需的天气资讯. 项目说明 项目放在github上面 地址是: ...
- Android 天气APP(九)细节优化、必应每日一图
上一篇:Android 天气APP(八)城市切换 之 自定义弹窗与使用 重新定位.必应每日一图 新版------------------- 一.封装定位 二.重新定位 三.必应每日一图 ① 添加必应接 ...
最新文章
- Mysqli的批量CRUD数据
- MySQL性能优化的最佳20+条经验(转)
- iOS - Tools Using's Problem
- STM32 电机教程 23 - ST MCLIB实战之基于stm32f13c8tx构建FOC工程
- CentOS7使用yum安装Nginx
- boost::python::detail::is_string_literal相关的测试程序
- uniapp的目录结构反思与整理 app.vue【base】pages.json【配置】main.json【框架入口文件】
- 输出螺旋数字正方形java_Java实现顺时针输出螺旋二维数组的方法示例
- Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析(8)...
- 连续型切片与离散加减的思路学习
- ajax中xmlhttp.readyState==4 xmlhttp.status==200 是什么意思
- 基于SSM的大学拍卖网站(含文档)
- WINDOWS如何编写注册表文件
- webstorm汉化怎样切回英文_webstorm 单词快捷翻译设置
- trans系列是sci几区_怎么确定SCI论文期刊是几区的
- 通过windows启动流程分析rootkit的潜在位置
- scp 传目录_目录传输命令scp
- Kylin系列(二)—— Cube 构造算法
- speedoffice(Word)怎么修改纸张方向
- android pdf转换base64 服务端转为文件