网络资源模板--基于 Android Studio 实现的天气预报App

目录

一、项目测试视频

二、项目简介

三、项目测试环境

四、项目详情设计

Get 项目模板源码


原创 天气预报:Android Studio 实现天气预报App

一、项目测试视频

网络资源模板--基于Android studio 实现天气预报

二、项目简介

本次项目主要实现了天气预报功能。通过调用天气预报接口来获得天气数据,用LIstView和GridView来搭建每个界面,将查询的天气信息存储在SQLiteDatabase中。应用包括了五大界面:

  • 首页面:有各种组件装饰,显示天气、温度、风向及各种指数,还有未来三天的天气
  • 城市管理界面:在这里可以对添加的城市进行管理
  • 搜索更多城市页面:可以添加想要查看的城市
  • 删除城市页面:可以删除已经添加的城市信息
  • 更多设置页面:可以设置壁纸、查看版本信息和分享软件

功能分析:

  1. 通过天气预报接口获取网络数据
  2. 展示选择城市的天气情况、温度、风向,各种指数以及未来三天的基础天气情况
  3. 将从网络中获取到的城市信息保存到数据库中,便于没有网时候进行数据请求
  4. 对数据库中的存储的信息,进行增删改查等操作

三、项目测试环境

四、项目详情设计

在 MainActivity 中,执行了以下操作:

  1. 设置了界面的背景图片。
  2. 初始化了 ViewPager 和相关的页面指示器。
  3. 通过 CityFragmentPagerAdapter 创建了城市天气信息的页面,并将其添加到 ViewPager 中。
  4. 实现了页面切换时的监听器,以及点击事件的处理。

在 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 项目模板源码

👇👇👇快捷获取方式👇👇👇

  • 35
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程乐学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值