目录
原创 天气预报:Android Studio 实现天气预报App
一、项目测试视频
网络资源模板--基于Android studio 实现天气预报
二、项目简介
本次项目主要实现了天气预报功能。通过调用天气预报接口来获得天气数据,用LIstView和GridView来搭建每个界面,将查询的天气信息存储在SQLiteDatabase中。应用包括了五大界面:
- 首页面:有各种组件装饰,显示天气、温度、风向及各种指数,还有未来三天的天气
- 城市管理界面:在这里可以对添加的城市进行管理
- 搜索更多城市页面:可以添加想要查看的城市
- 删除城市页面:可以删除已经添加的城市信息
- 更多设置页面:可以设置壁纸、查看版本信息和分享软件
功能分析:
- 通过天气预报接口获取网络数据
- 展示选择城市的天气情况、温度、风向,各种指数以及未来三天的基础天气情况
- 将从网络中获取到的城市信息保存到数据库中,便于没有网时候进行数据请求
- 对数据库中的存储的信息,进行增删改查等操作
三、项目测试环境
四、项目详情设计
在 MainActivity
中,执行了以下操作:
- 设置了界面的背景图片。
- 初始化了 ViewPager 和相关的页面指示器。
- 通过
CityFragmentPagerAdapter
创建了城市天气信息的页面,并将其添加到 ViewPager 中。 - 实现了页面切换时的监听器,以及点击事件的处理。
在 onRestart
方法中,您更新了页面的数据源,并根据数据源的变化更新了页面和页面指示器。
package com.animee.forecast;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import com.animee.forecast.city_manager.CityManagerActivity;
import com.animee.forecast.db.DBManager;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
ImageView addCityIv,moreIv;
LinearLayout pointLayout;
RelativeLayout outLayout;
ViewPager mainVp;
// ViewPager的数据源
List<Fragment>fragmentList;
// 表示需要显示的城市的集合
List<String>cityList;
// 表示ViewPager的页数指数器显示集合
List<ImageView>imgList;
private CityFragmentPagerAdapter adapter;
private SharedPreferences pref;
private int bgNum;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addCityIv = findViewById(R.id.main_iv_add);
moreIv = findViewById(R.id.main_iv_more);
pointLayout = findViewById(R.id.main_layout_point);
outLayout = findViewById(R.id.main_out_layout);
exchangeBg();
mainVp = findViewById(R.id.main_vp);
// 添加点击事件
addCityIv.setOnClickListener(this);
moreIv.setOnClickListener(this);
fragmentList = new ArrayList<>();
cityList = DBManager.queryAllCityName(); //获取数据库包含的城市信息列表
imgList = new ArrayList<>();
if (cityList.size()==0) {
cityList.add("北京");
}
/* 因为可能搜索界面点击跳转此界面,会传值,所以此处获取一下*/
try {
Intent intent = getIntent();
String city = intent.getStringExtra("city");
if (!cityList.contains(city)&&!TextUtils.isEmpty(city)) {
cityList.add(city);
}
}catch (Exception e){
Log.i("animee","程序出现问题了!!");
}
// 初始化ViewPager页面的方法
initPager();
adapter = new CityFragmentPagerAdapter(getSupportFragmentManager(), fragmentList);
mainVp.setAdapter(adapter);
// 创建小圆点指示器
initPoint();
// 设置最后一个城市信息
mainVp.setCurrentItem(fragmentList.size()-1);
// 设置ViewPager页面监听
setPagerListener();
}
// 换壁纸的函数
public void exchangeBg(){
pref = getSharedPreferences("bg_pref", MODE_PRIVATE);
bgNum = pref.getInt("bg", 2);
switch (bgNum) {
case 0:
outLayout.setBackgroundResource(R.mipmap.bg);
break;
case 1:
outLayout.setBackgroundResource(R.mipmap.bg2);
break;
case 2:
outLayout.setBackgroundResource(R.mipmap.bg3);
break;
}
}
private void setPagerListener() {
/* 设置监听事件*/
mainVp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
for (int i = 0; i < imgList.size(); i++) {
imgList.get(i).setImageResource(R.mipmap.a1);
}
imgList.get(position).setImageResource(R.mipmap.a2);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void initPoint() {
// 创建小圆点 ViewPager页面指示器的函数
for (int i = 0; i < fragmentList.size(); i++) {
ImageView pIv = new ImageView(this);
pIv.setImageResource(R.mipmap.a1);
pIv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) pIv.getLayoutParams();
lp.setMargins(0,0,20,0);
imgList.add(pIv);
pointLayout.addView(pIv);
}
imgList.get(imgList.size()-1).setImageResource(R.mipmap.a2);
}
private void initPager() {
/* 创建Fragment对象,添加到ViewPager数据源当中*/
for (int i = 0; i < cityList.size(); i++) {
CityWeatherFragment cwFrag = new CityWeatherFragment();
Bundle bundle = new Bundle();
bundle.putString("city",cityList.get(i));
cwFrag.setArguments(bundle);
fragmentList.add(cwFrag);
}
}
@Override
public void onClick(View v) {
Intent intent = new Intent();
switch (v.getId()) {
case R.id.main_iv_add:
intent.setClass(this,CityManagerActivity.class);
break;
case R.id.main_iv_more:
intent.setClass(this,MoreActivity.class);
break;
}
startActivity(intent);
}
/* 当页面重写加载时会调用的函数,这个函数在页面获取焦点之前进行调用,此处完成ViewPager页数的更新*/
@Override
protected void onRestart() {
super.onRestart();
// 获取数据库当中还剩下的城市集合
List<String> list = DBManager.queryAllCityName();
if (list.size()==0) {
list.add("北京");
}
cityList.clear(); //重写加载之前,清空原本数据源
cityList.addAll(list);
// 剩余城市也要创建对应的fragment页面
fragmentList.clear();
initPager();
adapter.notifyDataSetChanged();
// 页面数量发生改变,指示器的数量也会发生变化,重写设置添加指示器
imgList.clear();
pointLayout.removeAllViews(); //将布局当中所有元素全部移除
initPoint();
mainVp.setCurrentItem(fragmentList.size()-1);
}
}
这段代码实现了一个城市管理界面 `CityManagerActivity`,用户可以查看和管理已添加的城市列表。以下是代码的详细功能和流程:
1. **布局与初始化**:
- 在 `onCreate` 方法中,设置了布局文件 `activity_city_manager`,并初始化了界面上的控件。
- `ImageView` 控件 `addIv` 用于添加城市按钮。
- `ImageView` 控件 `backIv` 用于返回按钮。
- `ImageView` 控件 `deleteIv` 用于删除城市按钮。
- `ListView` 控件 `cityLv` 显示已添加城市的列表。
- 创建了一个空的 `List<DatabaseBean>` 类型的数据源 `mDatas` 用于显示城市列表。
- 设置了点击事件监听器,监听添加、返回和删除按钮的点击事件。
2. **数据更新**:
- `onResume` 方法中,通过 `DBManager.queryAllInfo()` 方法从数据库中获取所有城市的信息。
- 清空当前的数据源 `mDatas`,将获取到的新数据添加到 `mDatas` 中。
- 调用 `adapter.notifyDataSetChanged()` 更新 `ListView` 的显示。
3. **点击事件处理**:
- `onClick` 方法中根据点击的按钮执行不同的操作:
- 点击 `addIv` 添加按钮时,先检查当前已添加城市的数量是否小于5。
- 如果是,跳转至 `SearchCityActivity` 页面进行城市搜索和添加。
- 如果否,显示一个短暂的 Toast 提示用户存储城市数量已达上限。
- 点击 `backIv` 返回按钮时,调用 `finish()` 方法结束当前界面,返回上一个界面。
- 点击 `deleteIv` 删除按钮时,跳转至 `DeleteCityActivity` 页面进行城市删除操作。
4. **适配器**:
- 使用 `CityManagerAdapter` 适配器将数据 `mDatas` 显示在 `ListView` 中,以展示已添加的城市列表。
这段代码实现了城市管理界面的基本功能,包括添加、删除城市以及显示城市列表。通过数据库管理工具类 `DBManager` 实现数据的持久化存储和更新,确保用户可以方便地管理他们关注的城市信息。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="match_parent">
<RelativeLayout
android:id="@+id/city_top_layout"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#F5F5F5">
<ImageView
android:id="@+id/city_iv_back"
android:layout_marginLeft="10dp"
android:src="@mipmap/icon_back"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/city_iv_delete"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@mipmap/icon_write"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"/>
<TextView
android:id="@+id/city_tv_title"
android:text="城市管理"
android:textSize="18sp"
android:textStyle="bold"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
<ImageView
android:id="@+id/city_line"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#DCDCDC"
android:layout_below="@id/city_top_layout"/>
<ListView
android:id="@+id/city_lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/city_line"
android:divider="@null"></ListView>
<ImageView
android:id="@+id/city_iv_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_add"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_margin="30dp"
android:background="#87CEEB"
android:padding="3dp"/>
</RelativeLayout>
这段代码实现了一个城市搜索界面 `SearchCityActivity`,用于用户搜索城市并显示天气信息。以下是代码的详细功能和流程:
1. **布局与初始化**:
- 在 `onCreate` 方法中,设置了布局文件 `activity_search_city`,并初始化了界面上的控件。
- `EditText` 控件 `searchEt` 用于用户输入城市名。
- `ImageView` 控件 `submitIv` 是搜索按钮。
- `GridView` 控件 `searchGv` 显示热门城市列表。
- 使用 `ArrayAdapter` 将 `hotCitys` 数组中的城市名绑定到 `searchGv` 中。
2. **事件监听**:
- `submitIv` 的点击事件在 `onClick` 方法中处理。当用户点击搜索按钮时,获取输入的城市名 `city`。
- 如果输入不为空,构建天气信息查询的 URL,并调用 `loadData(url)` 方法加载数据。
- 如果输入为空,显示一个短暂的 Toast 提示用户输入内容不能为空。
3. **热门城市点击事件**:
- `searchGv` 的 `OnItemClickListener` 监听用户点击热门城市的事件。
- 当用户点击热门城市时,获取点击位置的城市名 `city`,构建天气信息查询的 URL,并调用 `loadData(url)` 方法加载数据。
4. **数据加载与处理**:
- `loadData(url)` 方法用于发送网络请求获取天气信息。请求成功后,会回调 `onSuccess` 方法。
- 在 `onSuccess` 方法中,使用 Gson 解析返回的 JSON 数据为 `JHTempBean` 对象。
- 如果返回的 `JHTempBean` 对象中 `error_code` 为 0(表示查询成功),则创建一个新的 `Intent` 跳转到主界面 `MainActivity`。
- 将城市名 `city` 作为额外数据传递给 `MainActivity`,并设置 `Intent` 标志为清除任务栈和新任务。
- 如果 `error_code` 不为 0,显示一个 Toast 提示暂时未收录此城市的天气信息。
5. **跳转至主界面**:
- 使用 `startActivity(intent)` 方法启动 `MainActivity`,显示所选城市的天气信息。
这段代码通过 `SearchCityActivity` 实现了城市搜索和天气信息查询的功能,并在查询成功时跳转到主界面显示天气信息,同时提供了热门城市供用户选择。
package com.animee.forecast.city_manager;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;
import com.animee.forecast.MainActivity;
import com.animee.forecast.R;
import com.animee.forecast.base.BaseActivity;
import com.animee.forecast.bean.WeatherBean;
import com.animee.forecast.juhe.JHTempBean;
import com.animee.forecast.juhe.URLUtils;
import com.google.gson.Gson;
public class SearchCityActivity extends BaseActivity implements View.OnClickListener{
EditText searchEt;
ImageView submitIv;
GridView searchGv;
String[]hotCitys = {"北京","上海","广州","深圳","珠海","佛山","南京","苏州","厦门","长沙","成都","福州",
"杭州","武汉","青岛","西安","太原","沈阳","重庆","天津","南宁"};
private ArrayAdapter<String> adapter;
String city;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_city);
searchEt = findViewById(R.id.search_et);
submitIv = findViewById(R.id.search_iv_submit);
searchGv = findViewById(R.id.search_gv);
submitIv.setOnClickListener(this);
// 设置适配器
adapter = new ArrayAdapter<>(this, R.layout.item_hotcity, hotCitys);
searchGv.setAdapter(adapter);
setListener();
}
/* 设置监听事件*/
private void setListener() {
searchGv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
city = hotCitys[position];
String url = URLUtils.getTemp_url(city);
loadData(url);
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.search_iv_submit:
city = searchEt.getText().toString();
if (!TextUtils.isEmpty(city)) {
// 判断是否能够找到这个城市
String url = URLUtils.getTemp_url(city);
loadData(url);
}else {
Toast.makeText(this,"输入内容不能为空!",Toast.LENGTH_SHORT).show();
}
break;
}
}
@Override
public void onSuccess(String result) {
JHTempBean weatherBean = new Gson().fromJson(result, JHTempBean.class);
if (weatherBean.getError_code()==0) {
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("city",city);
startActivity(intent);
}else{
Toast.makeText(this,"暂时未收入此城市天气信息...",Toast.LENGTH_SHORT).show();
}
}
}
Get 项目模板源码
👇👇👇快捷获取方式👇👇👇