Android动态片段

news2024/12/23 19:58:05

之前创建的片段都是静态的。一旦显示片段,片段的内容就不能改变了。尽管可以用一个新实例完全取代所显示的片段,但是并不能更新片段本身的内容。
之前已经创建过一个基础秒表应用,具体代码https://github.com/MADMAX110/Stopwatch。我们将这个应用增加到WorkoutDetailFragment,把它显示在训练项目的详细信息之下。

修改步骤

1、把StopwatchActivity转换为StopwatchFragment。
将其改为片段代码,还会在一个新的临时活动TempActivity中显示这个片段,以便检查它的具体工作。这里会暂时修改应用,使应用运行时启动TempActivity。
2、测试StopwatchFragment。
StopwatchActivity包含Start、Stop、Reset按钮。我们要检查将秒表代码放在一个片段中时这些按钮仍然能正常工作。
3、把StopwatchFragment增加到WorkoutDetailFragment。
让StopwatchFragment在一个新的临时活动TempActivity中工作。这样我们就能先确认StopwatchFragement能正常工作,然后再把它增加到WorkoutDetailFragment。

修改代码

回到之前创建的workout工程,在com.hfad.workout中创建一个新的活动TempActivity,布局名为activity_temp。
在这里插入图片描述
修改AndroidManifest.xml使得TempActivity为主活动:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Workout"
        tools:targetApi="31">
        <activity
            android:name=".TempActivity"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".DetailActivity"
            android:exported="false" />
        <activity
            android:name=".MainActivity"
            android:exported="true">
        </activity>
    </application>
</manifest>

我们要新增一个StopwatchFragment的秒表片段,鉴于片段和活动的生命周期有所不同,要对之前的秒表活动稍作修改使其成为片段。

package com.hfad.workout;

import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.Locale;
import android.os.Handler;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;


public class StopwatchFragment extends Fragment {

    private int seconds = 0;//记录已经过去的秒数
    private boolean running;//秒表是否正常运行
    //记录onStop之前秒表是否在运行,这样就知道是否需要恢复运行
    private boolean wasRunning;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState != null) {
            seconds = savedInstanceState.getInt("seconds");
            running = savedInstanceState.getBoolean("running");
            //保存wasRunning变量的状态
            wasRunning = savedInstanceState.getBoolean("wasRunning");
        }
    }

    @Nullable
    @Override
    //片段改为在onCreateView()方法中设置片段的布局
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View layout = inflater.inflate(R.layout.fragment_stopwatch, container, false);
        runTimer(layout);
        return layout;
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
        savedInstanceState.putInt("seconds", seconds);
        savedInstanceState.putBoolean("running", running);
    }

    @Override
    public void onResume() {
        super.onResume();
        if (wasRunning) {
            running = true;
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        wasRunning = running;
        running = false;
    }

    //启动秒表
    public void onClickStart(View view) {
        running = true;
    }

    //停止秒表
    public void onClickStop(View view) {
        running = false;
    }

    //单击reset按钮时会调用这个方法
    public void onClickReset(View view) {
        running = false;
        seconds = 0;
    }

    private void runTimer(View view) {
        //得到文本视图(片段不能为直接使用findViewById,使用view参数调用findViewById)
        final TextView timeView = (TextView) view.findViewById(R.id.time_view);
        //创建一个新地Handler
        final Handler handler = new Handler();
        //调用post()方法,传入一个新的Runnable。post()方法会立即运行代码
        handler.post(new Runnable() {
            public void run() {

                int hours = seconds / 3600;
                int minutes = (seconds%3600)/60;
                int secs = seconds % 60;
                //设置显示格式
                String time = String.format(Locale.getDefault(), "%d:%02d%02d", hours, minutes, secs);
                //设置文本视图
                timeView.setText(time);
                if (running) {
                    ++seconds;
                }

                //在1000ms后再次提交并运行Runnable中的代码,会反复调用
                handler.postDelayed(this, 1000);
            }
        });
    }
}

StopwatchFragment仍然使用Stopwatch原来的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    >
    <TextView
        android:id="@+id/time_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textAppearance="@android:style/TextAppearance.Large"
        android:textSize="56sp"
        />
    <Button
        android:id="@+id/start_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="20dp"
        android:onClick="onClickStart"
        android:text="@string/start"
        />
    <Button
        android:id="@+id/stop_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="8dp"
        android:onClick="onClickStop"
        android:text="@string/stop"
        />
    <Button
        android:id="@+id/reset_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="8dp"
        android:onClick="onClickReset"
        android:text="@string/reset"
        />
</LinearLayout>

增加三个字符串资源:

    <string name="start">Start</string>
    <string name="stop">Stop</string>
    <string name="reset">Reset</string>

修改activity_temp.xml:

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:name = "com.hfad.workout.StopwatchFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
</fragment>

在单击按钮时调用片段中的方法

此时尝试应用单击按钮时将会崩溃,其原因在于onClick调用的是活动中的方法,而不是片段中的方法。 Android不会调用片段中的方法,而只会调用父活动中的方法。如果在这个活动中无法找到相应的方法,应用就会崩溃。
如何在单击按钮时调用片段中的方法:
1、从片段布局中删除android:onClick的引用。
使用android:onCLick属性时,按钮就会调用活动中的方法,所以要从片段布局中将它们删除。
2、修改onClick方法签名(可选)
创建onClickStart、onClickStop和onCLickReset方法,声明它们是公共方法,并提供一个View参数。这样当用户单击一个按钮时就会调用这些方法。由于我们不在布局中使用android:onCLick属性,所以可以把这些方法设置为私有。
3、实现一个onCLickListener,将按钮绑定到片段中的方法。

完整的StopwatvhFragment:

package com.hfad.workout;

import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import java.util.Locale;
import android.os.Handler;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;


public class StopwatchFragment extends Fragment implements View.OnClickListener {

    private int seconds = 0;//记录已经过去的秒数
    private boolean running;//秒表是否正常运行
    //记录onStop之前秒表是否在运行,这样就知道是否需要恢复运行
    private boolean wasRunning;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState != null) {
            seconds = savedInstanceState.getInt("seconds");
            running = savedInstanceState.getBoolean("running");
            //保存wasRunning变量的状态
            wasRunning = savedInstanceState.getBoolean("wasRunning");
        }
    }

    @Nullable
    @Override
    //片段改为在onCreateView()方法中设置片段的布局
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View layout = inflater.inflate(R.layout.fragment_stopwatch, container, false);
        runTimer(layout);

        Button startButton = (Button)layout.findViewById(R.id.start_button);
        startButton.setOnClickListener(this);
        Button stopButton = (Button)layout.findViewById(R.id.stop_button);
        startButton.setOnClickListener(this);
        Button resetButton = (Button)layout.findViewById(R.id.reset_button);
        startButton.setOnClickListener(this);

        return layout;
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.start_button:
                onClickStart();
                break;
            case R.id.stop_button:
                onClickStop();
                break;
            case R.id.reset_button:
                onClickReset();
                break;
        }
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
        savedInstanceState.putInt("seconds", seconds);
        savedInstanceState.putBoolean("running", running);
    }

    @Override
    public void onResume() {
        super.onResume();
        if (wasRunning) {
            running = true;
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        wasRunning = running;
        running = false;
    }

    //启动秒表
    public void onClickStart() {
        running = true;
    }

    //停止秒表
    public void onClickStop() {
        running = false;
    }

    //单击reset按钮时会调用这个方法
    public void onClickReset() {
        running = false;
        seconds = 0;
    }

    private void runTimer(View view) {
        //得到文本视图(片段不能为直接使用findViewById,使用view参数调用findViewById)
        final TextView timeView = (TextView) view.findViewById(R.id.time_view);
        //创建一个新地Handler
        final Handler handler = new Handler();
        //调用post()方法,传入一个新的Runnable。post()方法会立即运行代码
        handler.post(new Runnable() {
            public void run() {

                int hours = seconds / 3600;
                int minutes = (seconds%3600)/60;
                int secs = seconds % 60;
                //设置显示格式
                String time = String.format(Locale.getDefault(), "%d:%02d%02d", hours, minutes, secs);
                //设置文本视图
                timeView.setText(time);
                if (running) {
                    ++seconds;
                }

                //在1000ms后再次提交并运行Runnable中的代码,会反复调用
                handler.postDelayed(this, 1000);
            }
        });
    }
}

现在可以试试应用了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1010119.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

发生以下的报错怎么办?

报错问题&#xff1a; 解决办法&#xff1a; 根据你提供的代码和错误信息&#xff0c;问题出在使用了nullptr。这个错误是因为你的编译器不支持C11标准。 nullptr是C11引入的空指针常量。为了解决这个问题&#xff0c;你可以尝试以下两种方法之一&#xff1a; 1. 将nullptr…

想要精通算法和SQL的成长之路 - 可以攻击国王的皇后

想要精通算法和SQL的成长之路 - 可以攻击国王的皇后 前言一. 可以攻击国王的皇后 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 可以攻击国王的皇后 原题链接 这个题目其实并没有涉及到什么很难的算法&#xff0c;其实就是一个简单的遍历题目。核心思想&#xff1a; 以…

CRM系统销售自动化功能如何提高销售效率

销售效率对企业的盈利能力有着至关重要的联系。提高销售效率&#xff0c;就是要提高销售人员的工作效率和销售转化率。那么&#xff0c;企业如何提高销售效率呢&#xff1f;CRM销售自动化功能可以帮助企业实现这一目标。 一、线索管理 线索是指有潜在购买意向的客户&#xff…

kali必杀器之三剑客

Kali常见攻击手段 注意:仅用于教程和科普&#xff0c;切勿做违法之事&#xff0c;否则后果自负 1 网络攻击手段 请正确使用DDos和CC攻击&#xff0c;不要用来做违反当地法律法规的事情&#xff0c;否则后果自负 使用之前kali需要能够上网 参考:kali安装 1.1 DDos攻击…

新加坡打车软件平台Ryde Group申请1700万美元纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;新加坡打车软件平台Ryde Group近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c;申请在纳斯达克IPO上市&#xff0c;股票代码为&#xff08;RYDE&#xff09;&#x…

学习javaEE初阶的第一堂课

学习金字塔 java发展简史 Java最初诞生的时候是用来写前端的!! 199x年 199x年,互联网还处在比较早期的阶段,当时主流的编程语言是 C/C, 有个大佬要搞个"智能面包机",觉得用C来做太难了 于是就基于C搞了个简单点的语言,Java 就诞生了~~ 遗憾的是项目流产了,没做成…

【SpringMVC】自定义注解

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《Spring MVC》。&#x1f3…

MMrotate_dev 1.x训练自己的数据集

因为MMRotate dev 1.x 新增了PSC角度编码器以及RTMDet目标检测算法&#xff0c;而之前从官网下载的MMRotate是main分支&#xff0c;没有新增的东西&#xff0c;所以重新搞了一下&#xff0c;以此记录。 环境配置 1.创建虚拟环境 注意&#xff1a;如果之前安装了MMRotate的其…

基于小程序的理发店预约系统

一、项目背景及简介 现在很多的地方都在使用计算机开发的各种管理系统来提高工作的效率&#xff0c;给人们带来很多的方便。计算机技术从很大的程度上解放了人们的双手&#xff0c;并扩大了人们的活动范围&#xff0c;是人们足不出户就可以通过电脑进行各种事情的管理。信息系…

pycharm安装jupyter,用德古拉主题,但是输入行全白了,看不清,怎么办?

问题描述 今天换了以下pycharm主题&#xff0c;但是jupyter界面输入代码行太白了&#xff0c;白到看不清楚这行的字&#xff0c;更不知道写的是什么&#xff0c;写到哪了&#xff0c;这还是挺烦人的&#xff0c;其他都挺正常的。 问题分析 目前来看有两个原因&#xff1a; 1、…

深化产教融合,知了汇智助力高校数字化人才培养

随着数字经济的不断深入和发展&#xff0c;数字人才短缺的问题逐渐凸显&#xff0c;根据相关报告&#xff0c;目前我国数字人才缺口在2500万到3000万左右&#xff0c;且缺口仍在不断扩大。为了满足数字经济的发展需求&#xff0c;如何培养出具备创新型、复合型、应用型能力的数…

C++学习笔记一(重载、类)

C 1、函数重载2、类2.1、类的方法和属性2.2、类的方法的定义2.3、构造器和析构器2.4、类的实例化2.5、基类与子类2.6、类的public、protected、private继承2.7、类的方法的重载2.8、子类方法的覆盖2.9、继承中的构造函数和析构函数 1、函数重载 函数重载大概可以理解为&#x…

再次理解Android账号管理体系

目录 ✅ 0. 需求 &#x1f4c2; 1. 前言 &#x1f531; 2. 使用 2.1 账户体系前提 2.2 创建账户服务 2.3 操作账户-增删改查 &#x1f4a0; 3. 源码流程 ✅ 0. 需求 试想&#xff0c;自己去实现一个账号管理体系&#xff0c;该如何做呢&#xff1f; ——————————…

竞赛 基于大数据的时间序列股价预测分析与可视化 - lstm

文章目录 1 前言2 时间序列的由来2.1 四种模型的名称&#xff1a; 3 数据预览4 理论公式4.1 协方差4.2 相关系数4.3 scikit-learn计算相关性 5 金融数据的时序分析5.1 数据概况5.2 序列变化情况计算 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &…

2004-2020年中小企业板上市公司财务报表股票交易董事高管1200+变量数据及说明

2004-2020年中小企业板上市公司财务报表股票交易董事高管1200变量数据及说明 1、时间&#xff1a;2004-2020年 2、范围&#xff1a;中小企业板上市公司&#xff0c;具体名单参看下文链接内数据预览 3、指标&#xff1a;1200变量 变量说明、证券代码、证券代码-字符串、年份…

HTML基础标签 CSS选择器 JavaScript基础语法 WebAPI_ 页面设计 HTTP协议

第 1 题&#xff08;简答题&#xff09; 题目名称&#xff1a; 编写博客, 总结 HTML 中的常用标签用法 题目内容&#xff1a; 编写博客, 总结 HTML 中的常用标签用法 第 2 题&#xff08;简答题&#xff09; 题目名称&#xff1a; image 标签的 alt 和 title 属性有什么…

基于红黑树对map和set容器的封装

本章代码gitee仓库&#xff1a;map和set模拟实现、stl_map_set_tree源码 文章目录 &#x1f431;1. 红黑树的泛型&#x1f408;1.1 红黑树节点&#x1f408;1.2 红黑树迭代器&#x1f408;1.3 仿函数 &#x1f42f;2. 对set的封装&#x1f984;3. 对map的封装 &#x1f431;1. …

android获取设备的IMEI号

在Android 8.0 (API级别26)和更高版本的平台上的 &#xff0c;64位数字(表示为十六进制字符串)&#xff0c;对于应用程序签名密钥、用户和设备的每个组合都是唯一的。ANDROID_ID的值由签名密钥和用户限定作用域。如果在设备上执行出厂重置或如果APK签名密钥更改&#xff0c;则该…

【校招VIP】前端操作系统之存储管理加密

考点介绍 加密算法有很多&#xff0c;如不可逆的摘要算法MD5、SHA&#xff08;安全哈希算法&#xff09;&#xff0c;可逆的Base64编码&#xff0c;对称加密算法DES、AES&#xff0c;还有非对称加密算法DH、RSA等。那是不是说明我们可以使用任何一种加密算法就能保证网站的安全…

认养一头牛———众筹+合伙人商业模式解析

2016年成立以来&#xff0c;认养一头牛致力于打造数字化乳业第一品牌&#xff0c;只为一杯好牛奶。公司在创立三年内完成了10个亿销售目标&#xff0c;被业界称为新消费品牌黑马&#xff0c;一举闯入互联网新消费梯队的视线。未来三年&#xff0c;认养一头牛将着力打造全国最大…