Android安卓实战项目(6)—健身运动 APP实现健身运动倒计时(源码在文末🐕🐕🐕)
一.项目运行介绍
【bilibili演示】 https://www.bilibili.com/video/BV1414y167WH/?share_source=copy_web&vd_source=b2e9b9ed746acda34f499009647748ed
二.具体实现
(1)功能一开机页面
MainActivity.java
package com.example.fitness;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import org.w3c.dom.Text;
public class MainActivity extends AppCompatActivity {
TextView titlepage,subtitlepage;
ImageView imgpage;
TextView btnexercise;
View bgprogress, bgprogresstop;
Animation animimgpage, bttone,bttwo, btthree,ltr;
Intent i1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
titlepage = findViewById(R.id.titlepage);
subtitlepage=findViewById(R.id.subtitlepage);
btnexercise = findViewById(R.id.btnexercise);
imgpage = findViewById(R.id.imgpage);
bgprogress = findViewById(R.id.bgprogress);
bgprogresstop = findViewById(R.id.bgprogresstop);
//animasyon ata
animimgpage= AnimationUtils.loadAnimation(this,R.anim.animimgpage);
bttone = AnimationUtils.loadAnimation(this,R.anim.bttone);
bttwo=AnimationUtils.loadAnimation(this,R.anim.bttwo);
btthree=AnimationUtils.loadAnimation(this,R.anim.btthree);
ltr=AnimationUtils.loadAnimation(this,R.anim.ltr);
imgpage.startAnimation(animimgpage);
titlepage.startAnimation(bttone);
subtitlepage.startAnimation(bttone);
btnexercise.startAnimation(btthree);
bgprogress.startAnimation(bttwo);
bgprogresstop.startAnimation(ltr);
//fontları import ediyoruz
Typeface MLight = Typeface.createFromAsset(getAssets(),"fonts/MLight.ttf");
Typeface MMedium = Typeface.createFromAsset(getAssets(),"fonts/MMedium.ttf");
Typeface Vidaloka = Typeface.createFromAsset(getAssets(),"fonts/Vidaloka.ttf");
//textView'a font atadık
titlepage.setTypeface(Vidaloka);
subtitlepage.setTypeface(MLight);
btnexercise.setTypeface(MMedium);
}
public void start(View v){
i1 = new Intent (MainActivity.this,WorkoutAct.class);
i1.addFlags(i1.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(i1);
}
}
- 导入必要的类和包:
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import org.w3c.dom.Text;
这部分代码导入了一些Android SDK和其他类,用于处理Activity、Intent、视图(View)、动画(Animation)、字体(Typeface)以及一些控件(Button、ImageView、TextView)的操作。
- 定义MainActivity类并继承AppCompatActivity:
public class MainActivity extends AppCompatActivity {
这段代码定义了一个名为MainActivity
的类,并让它继承自AppCompatActivity
。AppCompatActivity
是Android Support Library提供的类,它提供了与向后兼容性相关的功能。
- 声明各种控件和变量:
TextView titlepage, subtitlepage;
ImageView imgpage;
TextView btnexercise;
View bgprogress, bgprogresstop;
Animation animimgpage, bttone, bttwo, btthree, ltr;
Intent i1;
在这部分代码中,声明了各种控件的变量,如TextView
、ImageView
和View
等。这些变量将用于在后面的代码中与相应的布局中的控件进行关联。
onCreate
方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ... 以下代码略
}
onCreate
方法是Activity的生命周期方法之一,当Activity第一次创建时会调用这个方法。在这个方法中,我们完成了一些初始化工作。
- 找到控件并与变量关联:
titlepage = findViewById(R.id.titlepage);
subtitlepage = findViewById(R.id.subtitlepage);
btnexercise = findViewById(R.id.btnexercise);
imgpage = findViewById(R.id.imgpage);
bgprogress = findViewById(R.id.bgprogress);
bgprogresstop = findViewById(R.id.bgprogresstop);
这段代码通过findViewById
方法找到在布局文件(activity_main.xml)中定义的对应控件,并将它们与前面声明的变量关联起来。findViewById
方法通过传入控件的ID(R.id.xxx)来找到相应的控件对象。
- 加载动画资源:
animimgpage = AnimationUtils.loadAnimation(this, R.anim.animimgpage);
bttone = AnimationUtils.loadAnimation(this, R.anim.bttone);
bttwo = AnimationUtils.loadAnimation(this, R.anim.bttwo);
btthree = AnimationUtils.loadAnimation(this, R.anim.btthree);
ltr = AnimationUtils.loadAnimation(this, R.anim.ltr);
这部分代码加载了一系列动画资源。这些资源定义在res目录下的anim
文件夹中,分别对应着不同的动画效果。
- 为各个控件设置动画效果:
imgpage.startAnimation(animimgpage);
titlepage.startAnimation(bttone);
subtitlepage.startAnimation(bttone);
btnexercise.startAnimation(btthree);
bgprogress.startAnimation(bttwo);
bgprogresstop.startAnimation(ltr);
通过调用startAnimation
方法,将前面加载的动画资源分别应用到imgpage
、titlepage
、subtitlepage
、btnexercise
、bgprogress
和bgprogresstop
这些控件上,从而为它们添加了动画效果。
- 导入字体资源并为文本设置不同字体:
Typeface MLight = Typeface.createFromAsset(getAssets(), "fonts/MLight.ttf");
Typeface MMedium = Typeface.createFromAsset(getAssets(), "fonts/MMedium.ttf");
Typeface Vidaloka = Typeface.createFromAsset(getAssets(), "fonts/Vidaloka.ttf");
在这部分代码中,导入了字体资源,并通过createFromAsset
方法创建了三种不同的字体对象:MLight
、MMedium
和Vidaloka
。
titlepage.setTypeface(Vidaloka);
subtitlepage.setTypeface(MLight);
btnexercise.setTypeface(MMedium);
最后,通过调用setTypeface
方法,将前面创建的字体对象分别应用到titlepage
、subtitlepage
和btnexercise
这三个TextView
控件上,从而改变了这些文本的字体。
start
方法:
public void start(View v) {
i1 = new Intent(MainActivity.this, WorkoutAct.class);
i1.addFlags(i1.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(i1);
}
这是一个名为start
的公共方法,用于处理按钮的点击事件。当用户点击btnexercise
按钮时,会调用这个方法。
在这个方法中,首先创建了一个新的Intent
对象i1
,用于启动另一个活动WorkoutAct
。然后,通过调用addFlags
方法,给i1
对象添加了一个标记(FLAG_ACTIVITY_NO_ANIMATION
),这个标记表示在启动新的活动时,不播放切换动画。最后,通过调用startActivity
方法,启动了新的活动,实现了跳转到WorkoutAct
的功能。
至此,我们对这段代码进行了详细的分析。这个代码实现了一个简单的健身应用的主界面,并为其中的一些控件添加了动画效果和自定义字体。同时,点击按钮还可以跳转到另一个活动。
(2)功能二实现倒计时
WorkoutAct.java
package com.example.fitness;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.TextView;
public class WorkoutAct extends AppCompatActivity {
Intent i1;
TextView titlepage, subtitlepage, intropage, subintropage,
btnexercise, fitonetitle, fitonedesc, fittwotitle, fittwodesc,
fitthreetitle, fitthreedesc, fitfourtitle, fitfourdesc;
Animation bttone, bttwo, bttfour, bttfive, bttsix, bttseven, btteight;
View divpage, bgprogress;
LinearLayout fitone, fittwo, fitthree, fitfour;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_workout);
// load animations
bttone = AnimationUtils.loadAnimation(this, R.anim.bttone);
bttwo = AnimationUtils.loadAnimation(this, R.anim.bttwo);
bttfour = AnimationUtils.loadAnimation(this, R.anim.bttfour);
bttfive = AnimationUtils.loadAnimation(this, R.anim.bttfive);
bttsix = AnimationUtils.loadAnimation(this, R.anim.bttsix);
bttseven = AnimationUtils.loadAnimation(this, R.anim.bttseven);
btteight = AnimationUtils.loadAnimation(this, R.anim.btteight);
//fontları import ediyoruz
Typeface MLight = Typeface.createFromAsset(getAssets(),"fonts/MLight.ttf");
Typeface MMedium = Typeface.createFromAsset(getAssets(),"fonts/MMedium.ttf");
Typeface Vidaloka = Typeface.createFromAsset(getAssets(),"fonts/Vidaloka.ttf");
titlepage = (TextView) findViewById(R.id.titlepage);
subtitlepage = (TextView) findViewById(R.id.subtitlepage);
intropage = (TextView) findViewById(R.id.intropage);
subintropage = (TextView) findViewById(R.id.subintropage);
btnexercise = (TextView) findViewById(R.id.btnexercise);
divpage = (View) findViewById(R.id.divpage);
bgprogress = (View) findViewById(R.id.bgprogress);
// item fit layout
fitone = (LinearLayout) findViewById(R.id.fitone);
fittwo = (LinearLayout) findViewById(R.id.fittwo);
fitthree = (LinearLayout) findViewById(R.id.fitthree);
fitfour = (LinearLayout) findViewById(R.id.fitfour);
// item fit
fitonetitle = (TextView) findViewById(R.id.fitonetitle);
fitonedesc = (TextView) findViewById(R.id.fitonedesc);
fittwotitle = (TextView) findViewById(R.id.fittwotitle);
fittwodesc = (TextView) findViewById(R.id.fittwodesc);
fitthreetitle = (TextView) findViewById(R.id.fitthreetitle);
fitthreedesc = (TextView) findViewById(R.id.fitthreedesc);
fitfourtitle = (TextView) findViewById(R.id.fitfourtitle);
fitfourdesc = (TextView) findViewById(R.id.fitfourdesc);
//fit itemleri
fitonetitle=findViewById(R.id.fitonetitle);
fitonedesc=findViewById(R.id.fitonedesc);
//textView'a font atadık
titlepage.setTypeface(Vidaloka);
subtitlepage.setTypeface(MLight);
btnexercise.setTypeface(MMedium);
intropage.setTypeface(Vidaloka);
subintropage.setTypeface(MLight);
//fit itemler'a font ata
fitonedesc.setTypeface(MLight);
fitonetitle.setTypeface(MMedium);
// assign the animations
titlepage.startAnimation(bttone);
subtitlepage.startAnimation(bttone);
divpage.startAnimation(bttone);
intropage.startAnimation(bttwo);
subintropage.startAnimation(bttwo);
fitone.startAnimation(bttwo);
fittwo.startAnimation(bttfour);
fitthree.startAnimation(bttfive);
fitfour.startAnimation(bttsix);
btnexercise.startAnimation(btteight);
bgprogress.startAnimation(bttseven);
}
public void startNow(View v){
i1 = new Intent (this,StartWorkAct.class);
i1.addFlags(i1.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(i1);
}
}
StartWorkAct.java
package com.example.fitness;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Locale;
public class StartWorkAct extends AppCompatActivity {
TextView intropage, subintropage,fitonetitle,fitonedesc,
btnexercise,timerValue;
View divpage,bgprogress;
ImageView imgtimer;
LinearLayout fitone;
private static final long START_TIME_IN_MILLIS = 800000;
private CountDownTimer countDownTimer;
private boolean aTimerRunning;
private long mTimeLeftInMillis = START_TIME_IN_MILLIS;
Animation btthree,bttfour,ttbone,ttbtwo, alphagogo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_work);
//animasyonları tanımlıyoruz
btthree = AnimationUtils.loadAnimation(this,R.anim.btthree);
bttfour = AnimationUtils.loadAnimation(this,R.anim.bttfour);
ttbone = AnimationUtils.loadAnimation(this,R.anim.ttbone);
ttbtwo = AnimationUtils.loadAnimation(this,R.anim.ttbtwo);
alphagogo = AnimationUtils.loadAnimation(this,R.anim.alphagogo);
//fontları import ediyoruz
Typeface MLight = Typeface.createFromAsset(getAssets(),"fonts/MLight.ttf");
Typeface MMedium = Typeface.createFromAsset(getAssets(),"fonts/MMedium.ttf");
Typeface Vidaloka = Typeface.createFromAsset(getAssets(),"fonts/Vidaloka.ttf");
timerValue = findViewById(R.id.timerValue);
intropage = (TextView) findViewById(R.id.intropage);
subintropage = (TextView) findViewById(R.id.subintropage);
btnexercise = (TextView) findViewById(R.id.btnexercise);
//fit itemleri
fitonetitle=findViewById(R.id.fitonetitle);
fitonedesc=findViewById(R.id.fitonedesc);
bgprogress=findViewById(R.id.bgprogress);
divpage=findViewById(R.id.divpage);
fitone=findViewById(R.id.fitone);
imgtimer = findViewById(R.id.imgtimer);
intropage.setTypeface(Vidaloka);
subintropage.setTypeface(MLight);
btnexercise.setTypeface(MMedium);
//fit itemler'a font ata
fitonedesc.setTypeface(MLight);
fitonetitle.setTypeface(MMedium);
btnexercise.startAnimation(bttfour);
bgprogress.startAnimation(btthree);
fitone.startAnimation(ttbone);
intropage.startAnimation(ttbtwo);
subintropage.startAnimation(ttbtwo);
divpage.startAnimation(ttbtwo);
imgtimer.startAnimation(alphagogo);
timerValue.startAnimation(alphagogo);
startTimer();
}
private void startTimer(){
countDownTimer = new CountDownTimer(mTimeLeftInMillis,1000) {
@Override
public void onTick(long millisUntilFinished) {
mTimeLeftInMillis=millisUntilFinished;
updateCountDownText();
}
@Override
public void onFinish() {
Toast.makeText(getApplicationContext(),"Congratulations!",Toast.LENGTH_SHORT).show();
}
}.start();
}
private void updateCountDownText(){
int minutes = (int) (mTimeLeftInMillis/1000)/60;
int seconds = (int) (mTimeLeftInMillis/1000)%60;
String timeLeft = String.format(Locale.getDefault(),"%02d:%02d",minutes,seconds);
timerValue.setText(timeLeft);
}
}
- StartWorkAct.java:
这个类是一个Android活动(Activity),继承了AppCompatActivity
类。它似乎是一个基于计时器的健身锻炼活动。以下是代码的分解:
-
导入:在文件的开头导入了必要的Android类和库。
-
类和变量:定义了
StartWorkAct
类,并声明了各种TextView
、View
、ImageView
、LinearLayout
、Animation
和Typeface
对象作为类级变量。 -
常量:该类定义了一个名为
START_TIME_IN_MILLIS
的常量,其值为800,000毫秒(相当于8分钟)。 -
动画:使用
AnimationUtils.loadAnimation
从动画资源文件中加载动画对象,并将它们存储在类变量中。 -
视图和字体:使用相应的ID从布局XML文件中初始化各种视图。还从assets文件夹中加载自定义字体,并将其应用于某些视图。
-
onCreate:在
onCreate
方法中,使用setContentView(R.layout.activity_start_work)
设置了布局。使用setTypeface
为某些视图应用了字体样式。 -
动画:使用
startAnimation
在各个视图上启动了各种动画。 -
startTimer:定义了一个方法用于启动倒计时器。它创建了一个
CountDownTimer
,初始时间为START_TIME_IN_MILLIS
,并更新TextView
(timerValue
)以显示剩余时间(以分钟和秒为单位)。
- WorkoutAct.java:
这个类也是一个AppCompatActivity
,代表了Android应用中的另一个活动。它似乎是用于显示不同健身锻炼方案。以下是代码的分解:
-
导入:在文件的开头导入了必要的Android类和库。
-
类和变量:定义了
WorkoutAct
类,并声明了各种TextView
、View
、LinearLayout
、Animation
和Intent
对象作为类级变量。 -
动画:使用
AnimationUtils.loadAnimation
从动画资源文件中加载动画对象,并将它们存储在类变量中。 -
视图和字体:使用相应的ID从布局XML文件中初始化各种视图。使用
setTypeface
为某些视图应用了自定义字体样式。 -
onCreate:在
onCreate
方法中,使用setContentView(R.layout.activity_workout)
设置了布局。使用setTypeface
为某些视图应用了字体样式。 -
动画:使用
startAnimation
在各个视图上启动了各种动画。 -
startNow:这个方法在用户点击“立即开始”按钮(
btnexercise
)时被调用。它创建一个Intent用于导航到StartWorkAct
活动,并以无动画的方式启动它。
三.项目源码
链接:https://pan.baidu.com/s/1gBvP0f2HF0RF1T5jQxF8PA?pwd=jynl
提取码:jynl
已开源