基于Android平台开发,天气预报APP

1.项目功能思维导图

2. 项目涉及到的技术点

  1. 数据来源:和风天气API
  2. 使用okhttp网络请求框架获取api数据
  3. 使用gson库解析json数据
  4. 使用RecyclerView+adapter实现未来7天列表展示和天气指数
  5. 使用PopupMenu 实现弹出选项框
  6. 使用动画+定时器实现欢迎页倒计时和logo动画
  7. 使用TextToSpeech 实现语音播报

3.项目截图







4.部分代码功能实现

  1. 欢迎页实现
java 复制代码
public class WelcomeActivity extends AppCompatActivity {

    private TextView tvCountdown;
    private CardView card_logo;
    private CountDownTimer countDownTimer;
    private long timeLeftInMillis = 1000; // 设置倒计时时长,单位为毫秒



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_welcome);

        //初始化控件
        tvCountdown = findViewById(R.id.tv_countdown);
        card_logo = findViewById(R.id.card_logo);
        // 启动倒计时
        startCountdown();

        //实现logo缩放动画
        startAnim();

    }

    private void startAnim() {
        ViewCompat.animate(card_logo)
                .scaleX(1.0f)
                .scaleY(1.0f)
                .setDuration(1000)
                .setListener(new ViewPropertyAnimatorListener() {
                    @Override
                    public void onAnimationStart(View view) {

                    }

                    @Override
                    public void onAnimationEnd(View view) {

                    }

                    @Override
                    public void onAnimationCancel(View view) {

                    }
                })
                .start();
    }


    private void startCountdown() {
        countDownTimer = new CountDownTimer(timeLeftInMillis, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                timeLeftInMillis = millisUntilFinished;
                int secondsRemaining = (int) (millisUntilFinished / 1000);
                tvCountdown.setText(secondsRemaining + "s | 跳转");
            }

            @Override
            public void onFinish() {
                //跳转到登录页面(看自己逻辑想跳转哪个页面)
                startActivity(new Intent(WelcomeActivity.this, MainActivity.class));
                // 倒计时结束后的操作,例如跳转到主页面
                finish();

            }
        }.start();

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (countDownTimer != null) {
            countDownTimer.cancel();
        }
    }
}
  1. 天气指数
java 复制代码
public class IndicesActivity extends AppCompatActivity {
    private String city_id;

    private RecyclerView recyclerView;
    private IndicesListAdapter mIndicesListAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_indices);
        //获取跳转传值
        city_id = getIntent().getStringExtra("city_id");
        //获取生活指数
        getWeatherIndices(city_id);
        //初始化控件
        initViews();
        //初始化适配器
        mIndicesListAdapter = new IndicesListAdapter();
        //设置适配器
        recyclerView.setAdapter(mIndicesListAdapter);
        //设置监听器
        setListener();
    }


    /**
     * 初始化控件
     */
    private void initViews() {
        recyclerView = findViewById(R.id.recyclerView);

    }

    /**
     * 设置监听器
     */
    private void setListener() {

        findViewById(R.id.toolbar).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });
    }


    /**
     * 获取生活指数
     */
    private void getWeatherIndices(String city_id) {
        OkGo.<String>get("https://devapi.qweather.com/v7/indices/1d")
                .params("location", city_id)
                .params("key", ApiConstants.APP_KEY)
                .params("type", "0")
                .execute(new StringCallback() {
                    @Override
                    public void onStart(Request<String, ? extends Request> request) {
                        super.onStart(request);
                        ProgressDialogUtils.showProgressDialog(IndicesActivity.this);
                    }

                    @Override
                    public void onSuccess(Response<String> response) {
                        IndicesInfo indicesInfo = new Gson().fromJson(response.body(), IndicesInfo.class);
                        if (null != indicesInfo && indicesInfo.getCode().equals("200")) {
                            mIndicesListAdapter.setIndicesInfoList(indicesInfo.getDaily());
                        }
                    }

                    @Override
                    public void onFinish() {
                        super.onFinish();
                        ProgressDialogUtils.hideProgressDialog();
                    }
                });
    }
}
  1. 城市搜索
java 复制代码
public class SearchActivity extends AppCompatActivity {
    private EditText et_search_city;
    private RecyclerView recyclerView;
    private LinearLayoutCompat ll_empty;

    private SearchListAdapter mSearchListAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);

        // 1. 初始化控件
        initViews();
        //创建适配器
        mSearchListAdapter = new SearchListAdapter();
        //设置适配器
        recyclerView.setAdapter(mSearchListAdapter);
        // 2. 点击事件
        setListener();


    }

    /**
     * 初始化控件
     */
    private void initViews() {
        et_search_city = findViewById(R.id.et_search_city);
        recyclerView = findViewById(R.id.recyclerView);
        ll_empty = findViewById(R.id.ll_empty);
    }

    /**
     * 点击事件
     */
    private void setListener() {
        findViewById(R.id.btn_search).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 1. 获取输入框的值
                String cityName = et_search_city.getText().toString().trim();
                // 2. 判断是否为空
                if (cityName.isEmpty()) {
                    // 提示用户
                    Toast.makeText(SearchActivity.this, "城市名不能为空", Toast.LENGTH_SHORT).show();
                } else {
                    searchCity(cityName);
                }
            }
        });


        //返回
        findViewById(R.id.toolbar).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });


        //recyclerView点击事件
        mSearchListAdapter.setOnItemClickListener(new SearchListAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(CityLocationInfo.LocationDTO locationDTO) {
                // 1. 获取城市名
                String cityName = locationDTO.getName();
                Intent intent = new Intent();
                intent.putExtra("cityName", cityName);
                intent.putExtra("id", locationDTO.getId());
                //设置跳转回传的值
                setResult(1000, intent);
                // 3. 关闭当前界面
                finish();
            }
        });
    }


    /**
     * 城市搜索
     */
    private void searchCity(String cityName) {

        OkGo.<String>get("https://geoapi.qweather.com/v2/city/lookup").params("location", cityName).params("key", ApiConstants.APP_KEY).execute(new StringCallback() {
            @Override
            public void onStart(Request<String, ? extends Request> request) {
                super.onStart(request);
                ProgressDialogUtils.showProgressDialog(SearchActivity.this);
            }

            @Override
            public void onSuccess(Response<String> response) {
                CityLocationInfo cityLocationInfo = new Gson().fromJson(response.body(), CityLocationInfo.class);
                if (null != cityLocationInfo && cityLocationInfo.getCode().equals("200")) {
                    if (null != mSearchListAdapter) {
                        mSearchListAdapter.setCityLocationInfoList(cityLocationInfo.getLocation());
                    }
                    //判断是否显示空布局
                    if (mSearchListAdapter.getItemCount() > 0) {
                        ll_empty.setVisibility(View.GONE);
                    } else {
                        ll_empty.setVisibility(View.VISIBLE);
                    }
                } else {
                    Toast.makeText(SearchActivity.this, "未查询到该城市", Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onError(Response<String> response) {
                super.onError(response);
            }

            @Override
            public void onFinish() {
                super.onFinish();
                ProgressDialogUtils.hideProgressDialog();
            }
        });


    }
}
相关推荐
yzx99101313 分钟前
构建未来:深度学习、嵌入式与安卓开发的融合创新之路
android·人工智能·深度学习
前行的小黑炭28 分钟前
Android :如何快速让布局适配手机和平板?
android·java·kotlin
Yang-Never4 小时前
Kotlin协程 -> Job.join() 完整流程图与核心源码分析
android·开发语言·kotlin·android studio
一笑的小酒馆10 小时前
Android性能优化之截屏时黑屏卡顿问题
android
懒人村杂货铺13 小时前
Android BLE 扫描完整实战
android
TeleostNaCl15 小时前
如何安装 Google 通用的驱动以便使用 ADB 和 Fastboot 调试(Bootloader)设备
android·经验分享·adb·android studio·android-studio·android runtime
fatiaozhang952716 小时前
中国移动浪潮云电脑CD1000-系统全分区备份包-可瑞芯微工具刷机-可救砖
android·网络·电脑·电视盒子·刷机固件·机顶盒刷机
2501_9159184117 小时前
iOS 开发全流程实战 基于 uni-app 的 iOS 应用开发、打包、测试与上架流程详解
android·ios·小程序·https·uni-app·iphone·webview
lichong95117 小时前
【混合开发】vue+Android、iPhone、鸿蒙、win、macOS、Linux之dist打包发布在Android工程asserts里
android·vue.js·iphone
Android出海17 小时前
Android 15重磅升级:16KB内存页机制详解与适配指南
android·人工智能·新媒体运营·产品运营·内容运营