Android安卓实战项目(10)---详细记录饮食与训练计划App【大Demo】可记录每日消耗和数据面板(源码在文末)可用于比赛项目或者作业参考中

news2024/11/28 14:48:32

Android安卓实战项目(10)—详细记录饮食与训练计划App【大Demo】可记录每日消耗和数据面板(源码在文末🐕🐕🐕)可用于比赛项目或者作业参考中

【bilibili演示】
https://www.bilibili.com/video/BV1iz4y1p7jS/?share_source=copy_web&vd_source=b2e9b9ed746acda34f499009647748ed

一.项目运行介绍

app—logo

image-20230807180647917

主页

image-20230807180708703

添加餐食

image-20230807180725591

餐食分类

image-20230807180809178

对已有的餐食进行添加

image-20230807180836412

添加新的餐食

image-20230807180854488

查看今日餐食

image-20230807180947105

对今日的餐食进行详细的概览

image-20230807181055804

产看之前的餐食信息

image-20230807181150970

每日目标界面

image-20230807181227569

每日锻炼进行增加

image-20230807181320514

控件选择

image-20230807181330112

编辑锻炼计划

image-20230807181349467

编辑锻炼日程

image-20230807181409588

编辑锻炼

image-20230807181431770

源码概览

image-20230807181559995

image-20230807181546979

二.具体实现

Activity_Main.java
package com.falyrion.gymtonicapp;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.os.Bundle;
import android.view.MenuItem;

import com.falyrion.gymtonicapp.data.DatabaseHelper;
import com.falyrion.gymtonicapp.fragments.Fragment_Nutrition;
import com.falyrion.gymtonicapp.fragments.Fragment_Workout;
import com.falyrion.gymtonicapp.fragments.Fragment_Settings;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationBarView;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class Activity_Main extends AppCompatActivity {

    public String date;
    private int currentFragmentID = 0;
    public DatabaseHelper databaseHelper;


    private void setFragmentFood(String date) {
        Fragment_Nutrition fragment = new Fragment_Nutrition();
        Bundle args = new Bundle();
        args.putString("date", date);
        fragment.setArguments(args);
        getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commit();
    }

    private void setFragmentBodyStats() {
        // Pass
    }

    private void setFragmentWorkout() {
        Fragment_Workout fragment = new Fragment_Workout();
        getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commit();
    }

    private void setFragmentSettings() {
        Fragment_Settings fragment = new Fragment_Settings();
        getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commit();
    }

    private static void updateLanguage(Context context, String language) {

        if (language.equals("system")) {
            return;
        }

        Locale locale = new Locale(language);
        Locale.setDefault(locale);

        Resources resources = context.getResources();

        Configuration configuration = resources.getConfiguration();
        configuration.locale = locale;

        resources.updateConfiguration(configuration, resources.getDisplayMetrics());
    }


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

        // Database
        databaseHelper = new DatabaseHelper(Activity_Main.this);

        // Update language
        Cursor cursor = databaseHelper.getSettingsLanguage();
        if (cursor.getCount() > 0) {
            cursor.moveToFirst();
            updateLanguage(this, cursor.getString(0));
        }
        cursor.close();

        // -----------------------------------------------------------------------------------------
        // Get data if activity was started by another activity
        Intent intent = getIntent();

        // Get current date
        if (getIntent().hasExtra("date")) {
            date = intent.getStringExtra("date");
        } else {
            SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH);
            date = formatter.format(new Date());
        }

        // If there is a fragmentID submitted take it. Else keep previously set or default one (=0)
        if (getIntent().hasExtra("fragmentID")) {
            currentFragmentID = intent.getIntExtra("fragmentID", 0);
        }

        // Set current fragment based on fragmentID
        switch (currentFragmentID) {
            case 0:
                setFragmentFood(date);
                break;

            case 1:
                setFragmentBodyStats();
                break;

            case 2:
                setFragmentWorkout();
                break;

            case 3:
                setFragmentSettings();
                break;

            default:
                break;
        }

        // -----------------------------------------------------------------------------------------
        // Setup navigation bar
        BottomNavigationView navBar = findViewById(R.id.bottom_navigation);
        navBar.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.nav_bar_home:
                        if (currentFragmentID != 0) {
                            setFragmentFood(date);
                            currentFragmentID = 0;
                        }
                        return true;

                    case R.id.nav_bar_stats:
                        if (currentFragmentID != 1) {
                            setFragmentBodyStats();
                            currentFragmentID = 1;
                        }
                        return true;

                    case R.id.nav_bar_exersises:
                        if (currentFragmentID != 2) {
                            setFragmentWorkout();
                            currentFragmentID = 2;
                        }
                        return true;

                    case R.id.nav_bar_settings:
                        if (currentFragmentID != 3) {
                            setFragmentSettings();
                            currentFragmentID = 3;
                        }
                        return true;
                }
                return false;
            }
        });
    }

    @Override
    protected void onDestroy() {
        databaseHelper.close();
        super.onDestroy();
    }

}
package com.falyrion.gymtonicapp;

该代码所在的Java包名为com.falyrion.gymtonicapp

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.os.Bundle;
import android.view.MenuItem;
import com.falyrion.gymtonicapp.data.DatabaseHelper;
import com.falyrion.gymtonicapp.fragments.Fragment_Nutrition;
import com.falyrion.gymtonicapp.fragments.Fragment_Workout;
import com.falyrion.gymtonicapp.fragments.Fragment_Settings;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationBarView;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

这部分是导入所需的类和库。其中包括AppCompatActivity(用于支持较旧的Android版本),以及其他一些用于处理数据库、日期和语言设置的类和库。

public class Activity_Main extends AppCompatActivity {

这里声明了一个名为Activity_Main的类,并让它继承自AppCompatActivity,即这是一个Android的活动(Activity)类。

public String date;
private int currentFragmentID = 0;
public DatabaseHelper databaseHelper;

在类的顶部,声明了一些成员变量。date是一个字符串,currentFragmentID是一个整数,默认值为0,databaseHelper是一个DatabaseHelper对象用于数据库操作。

private void setFragmentFood(String date) {
    Fragment_Nutrition fragment = new Fragment_Nutrition();
    Bundle args = new Bundle();
    args.putString("date", date);
    fragment.setArguments(args);
    getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commit();
}

这是一个私有方法,用于设置显示Fragment_Nutrition(营养Fragment)。

  1. 创建一个Fragment_Nutrition的实例对象。
  2. 创建一个Bundle,并将当前日期(date)以"date"为键存入Bundle中。
  3. 将Bundle设置为Fragment的参数。
  4. 使用FragmentManager获取Fragment事务(FragmentTransaction)并将Fragment_Nutrition替换(replace)为activity_main.xml布局文件中指定ID为fragment_container的FrameLayout。
  5. 最后提交(commit)Fragment事务,完成Fragment的显示。
private void setFragmentBodyStats() {
    // Pass
}

这是一个私有方法,用于设置显示Fragment_BodyStats(身体统计Fragment)。但该方法没有实现任何具体的操作,即"// Pass"表示此处不执行任何代码。

private void setFragmentWorkout() {
    Fragment_Workout fragment = new Fragment_Workout();
    getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commit();
}

这是一个私有方法,用于设置显示Fragment_Workout(训练Fragment)。

  1. 创建一个Fragment_Workout的实例对象。
  2. 使用FragmentManager获取Fragment事务(FragmentTransaction)并将Fragment_Workout替换为activity_main.xml布局文件中指定ID为fragment_container的FrameLayout。
  3. 最后提交(commit)Fragment事务,完成Fragment的显示。
private void setFragmentSettings() {
    Fragment_Settings fragment = new Fragment_Settings();
    getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commit();
}

这是一个私有方法,用于设置显示Fragment_Settings(设置Fragment)。

  1. 创建一个Fragment_Settings的实例对象。
  2. 使用FragmentManager获取Fragment事务(FragmentTransaction)并将Fragment_Settings替换为activity_main.xml布局文件中指定ID为fragment_container的FrameLayout。
  3. 最后提交(commit)Fragment事务,完成Fragment的显示。
private static void updateLanguage(Context context, String language) {
    if (language.equals("system")) {
        return;
    }
    Locale locale = new Locale(language);
    Locale.setDefault(locale);
    Resources resources = context.getResources();
    Configuration configuration = resources.getConfiguration();
    configuration.locale = locale;
    resources.updateConfiguration(configuration, resources.getDisplayMetrics());
}

这是一个私有静态方法,用于更新应用程序的显示语言。

  1. 如果传入的language值为"system",则直接返回,不进行语言设置,保持系统默认语言。
  2. 创建一个新的Locale对象,根据传入的language值设定新的语言。
  3. 将新的Locale对象设定为应用程序的默认语言。
  4. 获取应用程序的资源(Resources)对象。
  5. 获取当前的配置信息(Configuration)对象,并将其语言设置为新的Locale。
  6. 使用更新后的配置信息更新应用程序的资源。
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Database
    databaseHelper = new DatabaseHelper(Activity_Main.this);

    // Update language
    Cursor cursor = databaseHelper.getSettingsLanguage();
    if (cursor.getCount() > 0) {
        cursor.moveToFirst();
        updateLanguage(this, cursor.getString(0));
    }
    cursor.close();

    // -----------------------------------------------------------------------------------------
    // Get data if activity was started by another activity
    Intent intent = getIntent();

    // Get current date
    if (getIntent().hasExtra("date")) {
        date = intent.getStringExtra("date");
    } else {
        SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH);
        date = formatter.format(new Date());
    }

    // If there is a fragmentID submitted take it. Else keep previously set or default one (=0)
    if (getIntent().hasExtra("fragmentID")) {
        currentFragmentID = intent.getIntExtra("fragmentID", 0);
    }

    // Set current fragment based on fragmentID
    switch (currentFragmentID) {
        case 0:
            setFragmentFood(date);
            break;

        case 1:
            setFragmentBodyStats();
            break;

        case 2:
            setFragmentWorkout();
            break;

        case 3:
            setFragmentSettings();
            break;

        default:
            break;
    }

    // -----------------------------------------------------------------------------------------
    // Setup navigation bar
    BottomNavigationView navBar = findViewById(R.id.bottom_navigation);
    navBar.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.nav_bar_home:
                    if (currentFragmentID != 0) {
                        setFragmentFood(date);
                        currentFragmentID = 0;
                    }
                   

 return true;

                case R.id.nav_bar_stats:
                    if (currentFragmentID != 1) {
                        setFragmentBodyStats();
                        currentFragmentID = 1;
                    }
                    return true;

                case R.id.nav_bar_exercises:
                    if (currentFragmentID != 2) {
                        setFragmentWorkout();
                        currentFragmentID = 2;
                    }
                    return true;

                case R.id.nav_bar_settings:
                    if (currentFragmentID != 3) {
                        setFragmentSettings();
                        currentFragmentID = 3;
                    }
                    return true;
            }
            return false;
        }
    });
}

这是Activity的主要方法,用于初始化Activity,并设置底部导航栏。

  1. 调用super.onCreate(savedInstanceState)来执行AppCompatActivity的onCreate()方法。
  2. 使用setContentView(R.layout.activity_main)指定显示的布局文件,即activity_main.xml。
  3. 初始化数据库:创建一个DatabaseHelper对象并关联到当前的Activity(Activity_Main.this)。
  4. 获取当前的语言设置并更新应用程序的显示语言。首先,从数据库中获取语言设置(使用getSettingsLanguage()方法),然后根据获取的设置调用updateLanguage()方法进行语言更新。
  5. 从上一个Activity传递的Intent中获取数据:
    • 如果Intent中包含名为"date"的额外数据,则获取其值并存入变量date中。
    • 如果Intent中包含名为"fragmentID"的额外数据,则获取其值并存入变量currentFragmentID中。否则,保持currentFragmentID的默认值0。
  6. 根据currentFragmentID的值,通过调用不同的私有方法,设置显示不同的Fragment。例如,如果currentFragmentID为0,则显示营养Fragment(Fragment_Nutrition);如果为1,则显示身体统计Fragment(Fragment_BodyStats);如果为2,则显示训练Fragment(Fragment_Workout);如果为3,则显示设置Fragment(Fragment_Settings)。
  7. 设置底部导航栏的点击监听器:查找底部导航栏(BottomNavigationView),并为其设置一个选项选择监听器(setOnItemSelectedListener)。当用户点击导航栏的不同选项时,通过切换Fragment的方式切换显示内容。例如,点击"首页"时,如果当前显示的不是营养Fragment,则切换到营养Fragment,并将currentFragmentID设置为0。
@Override
protected void onDestroy() {
    databaseHelper.close();
    super.onDestroy();
}

这是Activity的onDestroy()方法,当Activity被销毁时调用。在这里,关闭数据库连接,释放资源。


Fragment_Nutrition.java
package com.falyrion.gymtonicapp.fragments;

import android.animation.ObjectAnimator;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TableLayout;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.falyrion.gymtonicapp.Activity_Main;
import com.falyrion.gymtonicapp.R;
import com.falyrion.gymtonicapp.activities.Activity_Calendar;
import com.falyrion.gymtonicapp.activities.Activity_Meals_AddDailyEntry;
import com.falyrion.gymtonicapp.activities.Activity_Meals_MealsOfDay;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;


public class Fragment_Nutrition extends Fragment {

    // TODO: - Add more nutrition details (spurenelemente, metalle, vitamine, etc)
    // - in Add_Meal_Actitvity funktion hinzufügen das man auf ein preset clicken kann und es bearbeiten und löschen
    // - Noch mal schauen ob datum zwischen add_meal_activity und createmealactitvity richtig hin und her gegeben wird
    // - Funktion zum löschen von bereits zum tag hinzugefügten meals
    // - Progress bars schöner machen


    private String date;
    private double[] dataFood;
    private double[] dataGoals;

    private int percentOf(double current, double max) {
        return (int) ((current / max) * 100);
    }

    private String convertDataToDoubleText(double value) {
        // Convert given double to string.
        if (value % 1 == 0) {
            // -> Value has only .0 decimals. Cut it out by converting to int.
            return String.valueOf((int) value);
        } else {
            // -> Value has decimals. Round up to 2 decimal-digits.
            DecimalFormat df = new DecimalFormat("#####.##");
            return String.valueOf(df.format(value));
        }
    }

    private String convertDataToIntText(double value) {
        return String.valueOf((int) value);
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Get date from arguments
        if (getArguments().containsKey("date")) {
            date = getArguments().getString("date");
        } else {
            SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH);
            date = formatter.format(new Date());
        }

        // Load data from database
        Cursor cursorDataFood = ((Activity_Main) requireContext()).databaseHelper.getConsumedMealsSums(date);
        if (cursorDataFood.getCount() > 0) {
            cursorDataFood.moveToFirst();
            dataFood = new double[31];
            for (int i = 0; i <= 30; i++) {
                dataFood[i] = cursorDataFood.getDouble(i);
            }

        } else {
            dataFood = new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        }
        cursorDataFood.close();

        Cursor cursorSettings = ((Activity_Main) requireContext()).databaseHelper.getSettingsGoals();
        if (cursorSettings.getCount() > 0) {
            cursorSettings.moveToFirst();
            dataGoals = new double[] {
                    cursorSettings.getDouble(0),  // Goal Calories
                    cursorSettings.getDouble(1),  // Goal Fat
                    cursorSettings.getDouble(2),  // Goal Carbohydrates
                    cursorSettings.getDouble(3)  // Goal Protein
            };
        } else {
            dataGoals = new double[] {2000, 2000, 2000, 2000};
        }
        cursorSettings.close();

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_nutrition, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        // Date
        TextView textDate = view.findViewById(R.id.textViewDBNDate);
        textDate.setText(date);

        // Set values for main-dashboard
        ProgressBar progressBarMain = getView().findViewById(R.id.progressBarDBNCaloriesMain);
        TextView textProgressMain = getView().findViewById(R.id.textViewDNCaloriesMain);
        ObjectAnimator.ofInt(progressBarMain, "progress", percentOf(dataFood[0], dataGoals[0])).start();
        textProgressMain.setText(convertDataToIntText(dataFood[0]));

        ProgressBar progressBarFat = getView().findViewById(R.id.progressBarDBNFatMain);
        TextView textProgressFat = getView().findViewById(R.id.textViewProgressDBNFatMain);
        ObjectAnimator.ofInt(progressBarFat, "progress", percentOf(dataFood[1], dataGoals[1])).start();
        String textFat = convertDataToIntText(dataFood[1]) + " g";
        textProgressFat.setText(textFat);

        ProgressBar progressBarCarbohydrates = getView().findViewById(R.id.progressBarDBNCarbsMain);
        TextView textProgressCarbohydrates = getView().findViewById(R.id.textViewProgressCarbohydrates);
        ObjectAnimator.ofInt(progressBarCarbohydrates, "progress", percentOf(dataFood[3], dataGoals[2])).start();
        String textCarbohydrates = convertDataToIntText(dataFood[3]) + " g";
        textProgressCarbohydrates.setText(textCarbohydrates);

        ProgressBar progressBarProtein = getView().findViewById(R.id.progressBarDBNProteinMain);
        TextView textProgressProtein = getView().findViewById(R.id.textViewProgressDBNProteinMain);
        ObjectAnimator.ofInt(progressBarProtein, "progress", percentOf(dataFood[5], dataGoals[3])).start();
        String textProtein = convertDataToIntText(dataFood[5]) + " g";
        textProgressProtein.setText(textProtein);

        // Set values for details-dashboard
        TextView textViewDetailsCal = getView().findViewById(R.id.textViewDBNDetailsCalories);
        textViewDetailsCal.setText(convertDataToDoubleText(dataFood[0]));

        TextView textViewDetailsFat = getView().findViewById(R.id.textViewDBNDetailsFat);
        textViewDetailsFat.setText(convertDataToDoubleText(dataFood[1]));

        TextView textViewDetailsFatSat = getView().findViewById(R.id.textViewDBNDetailsFatSat);
        textViewDetailsFatSat.setText(convertDataToDoubleText(dataFood[2]));

        TextView textViewDetailsCarbs = getView().findViewById(R.id.textViewDBNDetailsCarbs);
        textViewDetailsCarbs.setText(convertDataToDoubleText(dataFood[3]));

        TextView textViewDetailsSugar = getView().findViewById(R.id.textViewDBNDetailsSugar);
        textViewDetailsSugar.setText(convertDataToDoubleText(dataFood[4]));

        TextView textViewDetailsProtein = getView().findViewById(R.id.textViewDBNDetailsProtein);
        textViewDetailsProtein.setText(convertDataToDoubleText(dataFood[5]));

        TextView textViewDetailsSalt = getView().findViewById(R.id.textViewDBNDetailsSalt);
        textViewDetailsSalt.setText(convertDataToDoubleText(dataFood[6]));

        TextView textViewDetailsFiber = getView().findViewById(R.id.textViewDBNDetailsFiber);
        textViewDetailsFiber.setText(convertDataToDoubleText(dataFood[7]));

        TextView textViewDetailsChol = getView().findViewById(R.id.textViewDBNDetailsChol);
        textViewDetailsChol.setText(convertDataToDoubleText(dataFood[8]));

        TextView textViewDetailsCreatine = getView().findViewById(R.id.textViewDBNDetailsCreatine);
        textViewDetailsCreatine.setText(convertDataToDoubleText(dataFood[9]));

        TextView textViewDetailsCa = getView().findViewById(R.id.textViewDBNDetailsCa);
        textViewDetailsCa.setText(convertDataToDoubleText(dataFood[10]));

        TextView textViewDetailsFe = getView().findViewById(R.id.textViewDBNDetailsFe);
        textViewDetailsFe.setText(convertDataToDoubleText(dataFood[11]));

        TextView textViewDetailsKa = getView().findViewById(R.id.textViewDBNDetailsKa);
        textViewDetailsKa.setText(convertDataToDoubleText(dataFood[12]));

        TextView textViewDetailsMg = getView().findViewById(R.id.textViewDBNDetailsMg);
        textViewDetailsMg.setText(convertDataToDoubleText(dataFood[13]));

        TextView textViewDetailMn = getView().findViewById(R.id.textViewDBNDetailsMn);
        textViewDetailMn.setText(convertDataToDoubleText(dataFood[14]));

        TextView textViewDetailsNa = getView().findViewById(R.id.textViewDBNDetailsNa);
        textViewDetailsNa.setText(convertDataToDoubleText(dataFood[15]));

        TextView textViewDetailsP = getView().findViewById(R.id.textViewDBNDetailsP);
        textViewDetailsP.setText(convertDataToDoubleText(dataFood[16]));

        TextView textViewDetailsZn = getView().findViewById(R.id.textViewDBNDetailsZn);
        textViewDetailsZn.setText(convertDataToDoubleText(dataFood[17]));

        TextView textViewDetailsVitA = getView().findViewById(R.id.textViewDBNDetailsVitA);
        textViewDetailsVitA.setText(convertDataToDoubleText(dataFood[18]));

        TextView textViewDetailsVitB1 = getView().findViewById(R.id.textViewDBNDetailsVitB1);
        textViewDetailsVitB1.setText(convertDataToDoubleText(dataFood[19]));

        TextView textViewDetailsVitB2 = getView().findViewById(R.id.textViewDBNDetailsVitB2);
        textViewDetailsVitB2.setText(convertDataToDoubleText(dataFood[20]));

        TextView textViewDetailsVitB3 = getView().findViewById(R.id.textViewDBNDetailsVitB3);
        textViewDetailsVitB3.setText(convertDataToDoubleText(dataFood[21]));

        TextView textViewDetailsVitB5 = getView().findViewById(R.id.textViewDBNDetailsVitB5);
        textViewDetailsVitB5.setText(convertDataToDoubleText(dataFood[22]));

        TextView textViewDetailsVitB6 = getView().findViewById(R.id.textViewDBNDetailsVitB6);
        textViewDetailsVitB6.setText(convertDataToDoubleText(dataFood[23]));

        TextView textViewDetailsVitB7 = getView().findViewById(R.id.textViewDBNDetailsVitB7);
        textViewDetailsVitB7.setText(convertDataToDoubleText(dataFood[24]));

        TextView textViewDetailsVitB11 = getView().findViewById(R.id.textViewDBNDetailsVitB11);
        textViewDetailsVitB11.setText(convertDataToDoubleText(dataFood[25]));

        TextView textViewDetailsVitB12 = getView().findViewById(R.id.textViewDBNDetailsVitB12);
        textViewDetailsVitB12.setText(convertDataToDoubleText(dataFood[26]));

        TextView textViewDetailsVitC = getView().findViewById(R.id.textViewDBNDetailsVitC);
        textViewDetailsVitC.setText(convertDataToDoubleText(dataFood[27]));

        TextView textViewDetailsVitE = getView().findViewById(R.id.textViewDBNDetailsVitE);
        textViewDetailsVitE.setText(convertDataToDoubleText(dataFood[28]));

        TextView textViewDetailsVitK = getView().findViewById(R.id.textViewDBNDetailsVitK);
        textViewDetailsVitK.setText(convertDataToDoubleText(dataFood[29]));

        TextView textViewDetailsVitH = getView().findViewById(R.id.textViewDBNDetailsVitH);
        textViewDetailsVitH.setText(convertDataToDoubleText(dataFood[30]));

        // Set buttons
        Button buttonAddMeal = getView().findViewById(R.id.buttonDashboardNutritionAddMeal);
        buttonAddMeal.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(view.getContext(), Activity_Meals_AddDailyEntry.class);
                intent.putExtra("date", date);
                intent.putExtra("fragmentID", 0);
                // intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);  // Start activity without animation
                startActivity(intent);
            }
        });

        Button buttonShowEatenMeals = getView().findViewById(R.id.buttonEatenMeals);
        buttonShowEatenMeals.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(view.getContext(), Activity_Meals_MealsOfDay.class);
                intent.putExtra("date", date);
                intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);  // Start activity without animation
                startActivity(intent);
            }
        });

        ImageButton buttonCalendar = getView().findViewById(R.id.buttonDBNCalendar);
        buttonCalendar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(view.getContext(), Activity_Calendar.class);
                intent.putExtra("date", date);
                intent.putExtra("fragmentID", 0);
                intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);  // Start activity without animation
                startActivity(intent);
            }
        });

        TableLayout tableLayoutDetails = view.findViewById(R.id.tableLayoutDashboardNutritionDetails);

        ImageButton buttonToggleDetails = view.findViewById(R.id.buttonExpandNutritionDetails);
        buttonToggleDetails.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (tableLayoutDetails.getVisibility() == View.GONE) {
                    tableLayoutDetails.setVisibility(View.VISIBLE);
                    buttonToggleDetails.setImageResource(R.drawable.ic_baseline_expand_less_24);
                    return;
                }
                tableLayoutDetails.setVisibility(View.GONE);
                buttonToggleDetails.setImageResource(R.drawable.ic_baseline_expand_more_24);
            }
        });

//        ScrollView mainLayout = view.findViewById(R.id.scrollViewMainLayout);
//        mainLayout.setVisibility(View.VISIBLE);
//
//        FrameLayout loadingLayout = view.findViewById(R.id.loadingLayout);
//        loadingLayout.setVisibility(View.GONE);
    }

}
  1. private String date;
    声明了一个私有成员变量date,用于保存日期信息的字符串。

  2. private double[] dataFood;
    声明了一个私有成员变量dataFood,用于保存食物摄入量的数组,包含31个元素,分别对应不同的营养项。

  3. private double[] dataGoals;
    声明了一个私有成员变量dataGoals,用于保存营养目标值的数组,包含4个元素,分别对应目标卡路里、脂肪、碳水化合物和蛋白质。

  4. private int percentOf(double current, double max) { ... }
    这是一个私有方法,用于计算当前值相对于最大值的百分比,返回整数类型。它接收两个参数:current表示当前值,max表示最大值。通过(current / max) * 100计算百分比并将结果转换为整数返回。

  5. private String convertDataToDoubleText(double value) { ... }
    这是一个私有方法,用于将给定的double类型数值转换成字符串。如果数值只有整数部分(小数部分为0),则返回整数形式;否则,保留两位小数并返回。

  6. private String convertDataToIntText(double value) { ... }
    这是一个私有方法,用于将给定的double类型数值转换成整数形式的字符串。

  7. @Override public void onCreate(Bundle savedInstanceState) { ... }
    在Fragment创建时调用。首先调用父类的onCreate方法,然后从传入的参数中获取日期信息并赋值给date变量。接下来,通过数据库助手类获取当天已消耗的餐食总和和用户设定的营养目标值,并分别存储在dataFooddataGoals数组中。

  8. @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ... }
    在Fragment创建View时调用。通过加载名为fragment_nutrition的布局文件来创建界面,并返回该View。

  9. @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { ... }
    当Fragment的View创建完成后调用,此时可以对View进行操作。

  10. onViewCreated方法中,将获取到的日期信息设置到界面上的日期文本框(TextView)。

  11. 设置主界面中的营养项进度条(ProgressBar)和文本信息(TextView)。首先通过getView()获取视图对象,然后通过findViewById方法找到对应的控件。通过动画效果(ObjectAnimator.ofInt)实现进度条的填充效果。数据从dataFooddataGoals数组中获取,并经过转换成字符串后显示在界面上。

  12. 设置详细营养信息界面中的各个营养项文本信息(TextView)。同样,数据从dataFood数组中获取,并经过转换成字符串后显示在界面上。

  13. 设置两个按钮的点击事件监听器:

  • buttonAddMeal按钮:点击后跳转到添加当天餐食的界面(Activity_Meals_AddDailyEntry),并传递当前日期和Fragment ID作为参数。
  • buttonShowEatenMeals按钮:点击后跳转到查看当天已吃餐食的界面(Activity_Meals_MealsOfDay),并传递当前日期作为参数。
  1. 设置日历按钮buttonCalendar的点击事件监听器,点击后跳转到日历界面(Activity_Calendar),并传递当前日期和Fragment ID作为参数。

  2. 设置buttonToggleDetails按钮的点击事件监听器,用于切换详细营养信息的显示和隐藏。点击按钮时,通过设置详细营养信息表格(tableLayoutDetails)的可见性来实现显示或隐藏,并更改按钮的图标。


Fragment_Settings.java
package com.falyrion.gymtonicapp.fragments;

import android.database.Cursor;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;

import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.falyrion.gymtonicapp.Activity_Main;
import com.falyrion.gymtonicapp.R;


public class Fragment_Settings extends Fragment implements AdapterView.OnItemSelectedListener {

    private double[] dataGoals;
    private String[] languages;
    private String currentLanguage;
    private boolean savePossible = false;
    private boolean firstSelect = true;

    private Button saveButton;

    private class textWatcher implements TextWatcher {
        private int id;
        private textWatcher(int id) {
            this.id = id;
        }

        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            // pass
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            // pass
        }

        @Override
        public void afterTextChanged(Editable editable) {
            // Update value
            dataGoals[id] = Double.parseDouble(editable.toString());

            // Update background resource of save button
            enableSaveButton();
        }
    }

    private String convertDataToText(double value) {
        // Convert given double to string.
        // Check if double value has ".0" decimals. If yes cut it out.
        if (value % 1 == 0) {
            return String.valueOf((int) value);
        } else {
            return String.valueOf(value);
        }
    }

    private void enableSaveButton() {
        saveButton.setBackgroundResource(R.drawable.shape_box_round_pop);
        saveButton.setTextColor(getContext().getColor(R.color.text_high));
        saveButton.setVisibility(View.VISIBLE);
        savePossible = true;
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Load data from database
        Cursor cursorGoals = ((Activity_Main) requireContext()).databaseHelper.getSettingsGoals();
        if (cursorGoals.getCount() > 0) {
            cursorGoals.moveToFirst();
            dataGoals = new double[] {
                    cursorGoals.getDouble(0),
                    cursorGoals.getDouble(1),
                    cursorGoals.getDouble(2),
                    cursorGoals.getDouble(3)
            };
        } else {
            dataGoals = new double[] {0, 0, 0, 0};
        }
        cursorGoals.close();

        // Languages
        languages = new String[] {
                getResources().getString(R.string.lang_de),
                getResources().getString(R.string.lang_en)
        };
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_settings, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        // Nutrition goal settings
        EditText editTextCalories = getView().findViewById(R.id.editTextSettingsGoalsCal);
        editTextCalories.setText(convertDataToText(dataGoals[0]));
        editTextCalories.addTextChangedListener(new textWatcher(0));

        EditText editTextFat = getView().findViewById(R.id.editTextSettingsGoalsFat);
        editTextFat.setText(convertDataToText(dataGoals[1]));
        editTextFat.addTextChangedListener(new textWatcher(1));

        EditText editTextCarbs = getView().findViewById(R.id.editTextSettingsGoalsCarbs);
        editTextCarbs.setText(convertDataToText(dataGoals[2]));
        editTextCarbs.addTextChangedListener(new textWatcher(2));

        EditText editTextProtein = getView().findViewById(R.id.editTextSettingsGoalsProtein);
        editTextProtein.setText(convertDataToText(dataGoals[3]));
        editTextProtein.addTextChangedListener(new textWatcher(3));


        // Language settings spinner
        Spinner spinner = getView().findViewById(R.id.spinnerLanguages);
        spinner.setOnItemSelectedListener(this);
        ArrayAdapter adapterCategories = new ArrayAdapter(getContext(), R.layout.spinner_item_purple_middle, languages);
        adapterCategories.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapterCategories);

        // Button
        saveButton = getView().findViewById(R.id.buttonSaveSettings);
        saveButton.setVisibility(View.INVISIBLE);
        saveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (savePossible) {
                    savePossible = false;
                    saveButton.setBackgroundResource(R.drawable.shape_box_round_middle);
                    saveButton.setTextColor(getContext().getColor(R.color.text_middle));
                    saveButton.setVisibility(View.INVISIBLE);

                    ((Activity_Main) requireContext()).databaseHelper.setSettingsGoals(dataGoals[0], dataGoals[1], dataGoals[2], dataGoals[3]);
                    ((Activity_Main) requireContext()).databaseHelper.setSettingsLanguage(currentLanguage);

                }
            }
        });
    }

    // Methods from imported spinner interface -----------------------------------------------------
    @Override
    public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
        // Guard clause against the automatic item select on creation
        if (firstSelect) {
            firstSelect = false;
            return;
        }

        // Set value
        switch (position) {
            case 0: currentLanguage = "de"; break;
            case 1: currentLanguage = "en"; break;
        }

        // Update button
        enableSaveButton();
    }

    @Override
    public void onNothingSelected(AdapterView<?> adapterView) {
        // Pass
    }
}
  1. 导入相关的Android库:
import android.database.Cursor;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;

import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.falyrion.gymtonicapp.Activity_Main;
import com.falyrion.gymtonicapp.R;
  1. 创建一个名为Fragment_Settings的类,继承自Fragment,并实现了AdapterView.OnItemSelectedListener接口。
public class Fragment_Settings extends Fragment implements AdapterView.OnItemSelectedListener {
    // 类的成员变量和方法在下面
}
  1. 定义了一些成员变量:
private double[] dataGoals;
private String[] languages;
private String currentLanguage;
private boolean savePossible = false;
private boolean firstSelect = true;

private Button saveButton;
  1. 创建一个内部类textWatcher,它实现了TextWatcher接口,用于监听输入框文本的变化。
private class textWatcher implements TextWatcher {
    private int id;

    private textWatcher(int id) {
        this.id = id;
    }

    // 在文本改变前不做处理
    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        // pass
    }

    // 在文本改变时不做处理
    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        // pass
    }

    // 在文本改变后,更新对应目标值和保存按钮状态
    @Override
    public void afterTextChanged(Editable editable) {
        dataGoals[id] = Double.parseDouble(editable.toString());
        enableSaveButton();
    }
}
  1. 定义了一些私有方法:
private String convertDataToText(double value) {
    // 将给定的double转换为字符串,并检查是否有".0"的小数部分,有则删除
    if (value % 1 == 0) {
        return String.valueOf((int) value);
    } else {
        return String.valueOf(value);
    }
}

private void enableSaveButton() {
    // 更新保存按钮的背景和可见性,用于表示用户可以保存设置
    saveButton.setBackgroundResource(R.drawable.shape_box_round_pop);
    saveButton.setTextColor(getContext().getColor(R.color.text_high));
    saveButton.setVisibility(View.VISIBLE);
    savePossible = true;
}
  1. onCreate()方法:
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // 从数据库中加载数据
    Cursor cursorGoals = ((Activity_Main) requireContext()).databaseHelper.getSettingsGoals();
    if (cursorGoals.getCount() > 0) {
        cursorGoals.moveToFirst();
        dataGoals = new double[] {
                cursorGoals.getDouble(0),
                cursorGoals.getDouble(1),
                cursorGoals.getDouble(2),
                cursorGoals.getDouble(3)
        };
    } else {
        dataGoals = new double[] {0, 0, 0, 0};
    }
    cursorGoals.close();

    // 设置语言选项
    languages = new String[] {
            getResources().getString(R.string.lang_de),
            getResources().getString(R.string.lang_en)
    };
}
  1. onCreateView()方法:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // 加载并返回fragment_settings布局
    return inflater.inflate(R.layout.fragment_settings, container, false);
}
  1. onViewCreated()方法:
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    // 获取布局中的输入框,并显示对应的目标值
    EditText editTextCalories = getView().findViewById(R.id.editTextSettingsGoalsCal);
    editTextCalories.setText(convertDataToText(dataGoals[0]));
    editTextCalories.addTextChangedListener(new textWatcher(0));

    EditText editTextFat = getView().findViewById(R.id.editTextSettingsGoalsFat);
    editTextFat.setText(convertDataToText(dataGoals[1]));
    editTextFat.addTextChangedListener(new textWatcher(1));

    EditText editTextCarbs = getView().findViewById(R.id.editTextSettingsGoalsCarbs);
    editTextCarbs.setText(convertDataToText(dataGoals[2]));
    editTextCarbs.addTextChangedListener(new textWatcher(2));

    EditText editTextProtein = getView().findViewById(R.id.editTextSettingsGoalsProtein);
    editTextProtein.setText(convertDataToText(dataGoals[3]));
    editTextProtein.addTextChangedListener(new textWatcher(3));


    // 设置语言选项的Spinner
    Spinner spinner = getView().findViewById(R.id.spinnerLanguages);
    spinner.setOnItemSelectedListener(this);
    ArrayAdapter adapterCategories = new ArrayAdapter(getContext(), R.layout.spinner_item_purple_middle, languages);
    adapterCategories.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapterCategories);

    // 设置保存按钮
    saveButton = getView().findViewById(R.id.buttonSaveSettings);
    saveButton.setVisibility(View.INVISIBLE);
    saveButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // 如果保存按钮可用,则保存数据到数据库,并隐藏保存按钮
            if (savePossible) {
                savePossible = false;
                saveButton.setBackgroundResource(R.drawable.shape_box_round_middle);
                saveButton.setTextColor(getContext().getColor(R.color.text_middle));
                saveButton.setVisibility(View.INVISIBLE);

                ((Activity_Main) requireContext()).databaseHelper.setSettingsGoals(dataGoals[0], dataGoals[1], dataGoals[2], dataGoals[3]);
                ((Activity_Main) requireContext()).databaseHelper.setSettingsLanguage(currentLanguage);
            }
        }
    });
}
  1. 方法从导入的AdapterView.OnItemSelectedListener接口中继承:
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
    // 防止在创建时自动选择项
    if (firstSelect) {
        firstSelect = false;
        return;
    }

    // 设置语言选项,并更新保存按钮状态
    switch (position) {
        case 0: currentLanguage = "de"; break;
        case 1: currentLanguage = "en"; break;
    }
    enableSaveButton();
}

@Override
public void onNothingSelected(AdapterView<?> adapterView) {
    // 无操作
}

总体来说,这段代码是一个用于设置健身目标和语言选项的Fragment,它在用户修改了目标值或语言选项时,会显示一个保存按钮,允许用户保存设置到数据库。注意其中涉及了数据库操作和布局文件的相关处理。


package com.falyrion.gymtonicapp.fragments;

import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.falyrion.gymtonicapp.Activity_Main;
import com.falyrion.gymtonicapp.R;
import com.falyrion.gymtonicapp.activities.Activity_Workout_CreateEditExercise;
import com.falyrion.gymtonicapp.activities.Activity_Workout_EditPlans;
import com.falyrion.gymtonicapp.activities.Activity_Workout_EditRoutines;
import com.falyrion.gymtonicapp.recyclerview.Adapter_Workout_Exercise;
import com.falyrion.gymtonicapp.recyclerview.Adapter_Workout_Routine;
import com.falyrion.gymtonicapp.recyclerview.Item_Workout_Exercise;
import com.falyrion.gymtonicapp.recyclerview.Item_Workout_Routine;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;

import java.util.ArrayList;


public class Fragment_Workout extends Fragment implements Adapter_Workout_Routine.Interface_Workout_Routine, Adapter_Workout_Exercise.Interface_Workout_Exercises, AdapterView.OnItemSelectedListener {

    private String[] workoutPlans;
    private ArrayList<Item_Workout_Routine> workoutRoutines;
    private ArrayList<Item_Workout_Exercise> workoutExercises;
    private int selectedPlanIdx = -1;
    private int selectedRoutineIdx = -1;
    private RecyclerView recyclerViewRoutines;
    private RecyclerView recyclerViewExercises;
    private Adapter_Workout_Routine adapterRoutines;
    private Adapter_Workout_Exercise adapterExercises;

    private boolean fabOpen = false;
    private FloatingActionButton fabMain;
    private LinearLayout linearLayoutFABSub01;
    private LinearLayout linearLayoutFABSub02;
    private LinearLayout linearLayoutFABSub03;
    private View backgroundBlur;

    TextView sectionTitleRoutines;
    TextView sectionTitleExercises;


    private String[] loadPlansFromDatabase() {
        Cursor cursor = ((Activity_Main) requireContext()).databaseHelper.getWorkoutPlans();
        String[] loadedPlans = new String[0];

        if (cursor.getCount() > 0) {
            // Initiate array with length of cursor data
            loadedPlans = new String[cursor.getCount()];
            // Add plan-names to array
            int j = 0;
            while (cursor.moveToNext()) {
                loadedPlans[j] = cursor.getString(0);
                j++;
            }
        }
        cursor.close();

        return loadedPlans;
    }

    private ArrayList<Item_Workout_Routine> loadRoutinesFromDatabase(String workoutPlan) {
        Cursor cursor = ((Activity_Main) requireContext()).databaseHelper.getWorkoutRoutines(workoutPlan);
        ArrayList<Item_Workout_Routine> loadedRoutines = new ArrayList<Item_Workout_Routine>();

        if (cursor.getCount() > 0) {
            cursor.moveToFirst();
            loadedRoutines.add(cursor.getPosition(), new Item_Workout_Routine(cursor.getString(0), true));

            while (cursor.moveToNext()) {
                loadedRoutines.add(cursor.getPosition(), new Item_Workout_Routine(cursor.getString(0), false));
            }
        }

        return loadedRoutines;
    }

    private ArrayList<Item_Workout_Exercise> loadExercisesFromDatabase(String workoutPlan, String workoutRoutine) {
        Cursor cursor = ((Activity_Main) requireContext()).databaseHelper.getWorkoutExercises(workoutPlan, workoutRoutine);
        ArrayList<Item_Workout_Exercise> loadedExercises = new ArrayList<Item_Workout_Exercise>();

        if (cursor.getCount() > 0) {
            while (cursor.moveToNext()) {
                loadedExercises.add(
                        cursor.getPosition(),
                        new Item_Workout_Exercise(
                                cursor.getString(0),  // Title
                                cursor.getInt(1),  // Sets
                                cursor.getInt(2),  // Reps
                                cursor.getDouble(3)  // Weight
                        )
                );
            }
        }

        return loadedExercises;
    }

    private void toggleFABMenu() {
        if (fabOpen) {
            // Close FAB-menu
            fabOpen = false;
            fabMain.setImageResource(R.drawable.ic_baseline_add_circle_24);
            linearLayoutFABSub01.setTranslationY(0);
            linearLayoutFABSub02.setTranslationY(0);
            linearLayoutFABSub03.setTranslationY(0);
            linearLayoutFABSub01.setVisibility(View.INVISIBLE);
            linearLayoutFABSub02.setVisibility(View.INVISIBLE);
            linearLayoutFABSub03.setVisibility(View.INVISIBLE);
            backgroundBlur.setVisibility(View.GONE);
        } else {
            // Oben FAB-menu
            fabOpen = true;
            backgroundBlur.setVisibility(View.VISIBLE);
            fabMain.setImageResource(R.drawable.ic_baseline_remove_circle_24);
            linearLayoutFABSub01.setVisibility(View.VISIBLE);
            linearLayoutFABSub02.setVisibility(View.VISIBLE);
            linearLayoutFABSub03.setVisibility(View.VISIBLE);
            linearLayoutFABSub01.animate().translationY(-170);
            linearLayoutFABSub02.animate().translationY(-340);
            linearLayoutFABSub03.animate().translationY(-510);
        }
    }


    // Override class default methods --------------------------------------------------------------

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Load data from database and fill lists and create adapters

        workoutPlans = loadPlansFromDatabase();
        selectedPlanIdx = 0;

        workoutRoutines = loadRoutinesFromDatabase(workoutPlans[0]);

        if (!workoutRoutines.isEmpty()) {
            workoutExercises = loadExercisesFromDatabase(workoutPlans[0], workoutRoutines.get(0).getTitle());
            Log.d("uwu", "routines size: " + workoutRoutines.size());
            Log.d("uwu", "exerzises size: " + workoutExercises.size());
        }

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_workout, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        // Set up recycler-views

        sectionTitleRoutines = view.findViewById(R.id.sectionTitleRoutines);
        sectionTitleExercises = view.findViewById(R.id.sectionTitleExercises);

        Spinner spinnerPlans = view.findViewById(R.id.spinnerWorkoutPlans);
        spinnerPlans.setOnItemSelectedListener(this);
        ArrayAdapter adapterPlans = new ArrayAdapter(getContext(), R.layout.spinner_item_purple_middle, workoutPlans);
        adapterPlans.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinnerPlans.setAdapter(adapterPlans);

        recyclerViewRoutines = view.findViewById(R.id.recyclerViewRoutines);
        if (!workoutRoutines.isEmpty()) {
            adapterRoutines = new Adapter_Workout_Routine(workoutRoutines, this);
            recyclerViewRoutines.setAdapter(adapterRoutines);
            recyclerViewRoutines.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
            selectedRoutineIdx = 0;
        } else {
            sectionTitleRoutines.setVisibility(View.INVISIBLE);
        }

        recyclerViewExercises = view.findViewById(R.id.recyclerViewExercises);
        if (!workoutExercises.isEmpty()) {
            adapterExercises = new Adapter_Workout_Exercise(workoutExercises, this);
            recyclerViewExercises.setAdapter(adapterExercises);
            recyclerViewExercises.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
        } else {
            sectionTitleExercises.setVisibility(View.INVISIBLE);
        }

        // FAB-Views -------------------------------------------------------------------------------

        linearLayoutFABSub01 = view.findViewById(R.id.linearLayoutFAB01);
        linearLayoutFABSub02 = view.findViewById(R.id.linearLayoutFAB02);
        linearLayoutFABSub03 = view.findViewById(R.id.linearLayoutFAB03);
        backgroundBlur = view.findViewById(R.id.fragmentExercisesBlur);
        fabMain = view.findViewById(R.id.fabExercisesMain);
        FloatingActionButton fabSub01 = view.findViewById(R.id.fabExercises01);
        FloatingActionButton fabSub02 = view.findViewById(R.id.fabExercises02);
        FloatingActionButton fabSub03 = view.findViewById(R.id.fabExercises03);

        // Main Button
        fabMain.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                toggleFABMenu();
            }
        });

        // Background blur
        backgroundBlur.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                toggleFABMenu();
            }
        });

        // Button "Add Exercise"
        fabSub01.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (workoutRoutines.isEmpty()) {
                    Snackbar.make(view, "Please create at least one workout routine first!", Snackbar.LENGTH_SHORT).show();
                    return;
                }

                Intent intent = new Intent(view.getContext(), Activity_Workout_CreateEditExercise.class);
                intent.putExtra("date", ((Activity_Main) requireContext()).date);
                startActivity(intent);
            }
        });

        // Button "Add Routine"
        fabSub02.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Check if at least 1 plan exists, else do not open new activity
                if (workoutPlans.length <= 0) {
                    Toast.makeText(getContext(), "You must create at least 1 workout plan first!", Toast.LENGTH_SHORT).show();
                    return;
                }

                // Start activity
                Intent intent = new Intent(view.getContext(), Activity_Workout_EditRoutines.class);
                startActivity(intent);
            }
        });

        // Button "Add Plan"
        fabSub03.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(view.getContext(), Activity_Workout_EditPlans.class);
                startActivity(intent);
            }
        });

    }


    // Interface methods ---------------------------------------------------------------------------

    // Spinner Plan Methods
    @Override
    public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
        if (position == selectedPlanIdx) {
            return;
        }

        selectedPlanIdx = position;

        // Update routines
        workoutRoutines.clear();
        if (adapterRoutines != null) {
            adapterRoutines.notifyDataSetChanged();
        }

        workoutExercises.clear();
        if (adapterExercises != null) {
            adapterExercises.notifyDataSetChanged();
        }

        workoutRoutines = loadRoutinesFromDatabase(workoutPlans[selectedPlanIdx]);

        if (workoutRoutines.isEmpty()) {
            sectionTitleRoutines.setVisibility(View.INVISIBLE);
            sectionTitleExercises.setVisibility(View.INVISIBLE);
            return;
        }

        adapterRoutines = new Adapter_Workout_Routine(workoutRoutines, this);
        recyclerViewRoutines.setAdapter(adapterRoutines);
        recyclerViewRoutines.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
        selectedRoutineIdx = 0;
        sectionTitleRoutines.setVisibility(View.VISIBLE);

        // Updates exercises
        workoutExercises = loadExercisesFromDatabase(workoutPlans[selectedPlanIdx], workoutRoutines.get(selectedRoutineIdx).getTitle());

        if (!workoutExercises.isEmpty()) {
            adapterExercises = new Adapter_Workout_Exercise(workoutExercises, this);
            recyclerViewExercises.setAdapter(adapterExercises);
            recyclerViewExercises.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
            sectionTitleExercises.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> adapterView) {
        // Pass
    }

    // Routine adapter methods
    @Override
    public void onRoutineItemClick(int itemPosition) {
        if (selectedRoutineIdx == -1) {
            return;
        }

        if (itemPosition == selectedRoutineIdx) {
            return;
        }

        // Update routine-items visually
        workoutRoutines.get(itemPosition).setIsSelected(true);
        workoutRoutines.get(selectedRoutineIdx).setIsSelected(false);
        adapterRoutines.notifyItemChanged(itemPosition);
        adapterRoutines.notifyItemChanged(selectedRoutineIdx);

        selectedRoutineIdx = itemPosition;

        // Update exercises
        workoutExercises.clear();
        if (adapterExercises != null) {
            adapterExercises.notifyDataSetChanged();
        }


        workoutExercises = loadExercisesFromDatabase(workoutPlans[selectedPlanIdx], workoutRoutines.get(selectedRoutineIdx).getTitle());

        if (!workoutExercises.isEmpty()) {
            adapterExercises = new Adapter_Workout_Exercise(workoutExercises, this);
            recyclerViewExercises.setAdapter(adapterExercises);
            recyclerViewExercises.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
        }


        // adapterExercises.notifyDataSetChanged();
    }

    // Exercise adapter methods
    @Override
    public void onExerciseItemClick(int itemPosition) {
        Intent intent = new Intent(getContext(), Activity_Workout_CreateEditExercise.class);
        intent.putExtra("date", ((Activity_Main) requireContext()).date);
        intent.putExtra("mode", "edit");
        intent.putExtra("planName", workoutPlans[selectedPlanIdx]);
        intent.putExtra("routineName", workoutRoutines.get(selectedRoutineIdx).getTitle());
        intent.putExtra("exerciseName", workoutExercises.get(itemPosition).getTitle());
        intent.putExtra("exerciseSets", workoutExercises.get(itemPosition).getSets());
        intent.putExtra("exerciseReps", workoutExercises.get(itemPosition).getRepetitions());
        intent.putExtra("exerciseWeight", workoutExercises.get(itemPosition).getWeight());
        startActivity(intent);
    }

}
  1. 导入所需的Android类和自定义类:
    代码中首先导入了一些必要的Android类和自定义的类,这些类包括数据库操作、RecyclerView适配器和其他视图组件。

  2. 定义Fragment类:
    Fragment_Workout类是一个继承自Fragment的Java类,它实现了Adapter_Workout_Routine.Interface_Workout_Routine、Adapter_Workout_Exercise.Interface_Workout_Exercises和AdapterView.OnItemSelectedListener接口。

  3. 声明和初始化一些变量:
    代码中声明了一些成员变量,用于存储用户的训练计划、训练例程和训练细节等信息。这些变量包括:

    • workoutPlans:存储训练计划的字符串数组。
    • workoutRoutines:存储训练例程的自定义类Item_Workout_Routine的ArrayList。
    • workoutExercises:存储训练细节的自定义类Item_Workout_Exercise的ArrayList。
    • selectedPlanIdx:当前选中的训练计划在workoutPlans数组中的索引。
    • selectedRoutineIdx:当前选中的训练例程在workoutRoutines数组中的索引。
  4. 从数据库加载数据:

    • loadPlansFromDatabase()方法:从数据库中获取所有的训练计划,并返回一个存储训练计划名称的字符串数组。
    • loadRoutinesFromDatabase(String workoutPlan)方法:根据传入的训练计划名称从数据库中获取对应的训练例程,并返回一个存储训练例程的Item_Workout_Routine的ArrayList。
    • loadExercisesFromDatabase(String workoutPlan, String workoutRoutine)方法:根据传入的训练计划名称和训练例程名称从数据库中获取对应的训练细节,并返回一个存储训练细节的Item_Workout_Exercise的ArrayList。
  5. toggleFABMenu()方法:
    这是一个用于控制浮动操作按钮(FloatingActionButton)动画和显示的方法。根据fabOpen变量的值,切换浮动操作按钮的显示状态,从而呈现打开或关闭的动画效果。

  6. 重写Fragment的默认方法:

    • onCreate()方法:在Fragment创建时调用,用于加载数据和初始化变量。
    • onCreateView()方法:在Fragment创建视图时调用,用于加载布局文件。
    • onViewCreated()方法:在视图创建后调用,用于设置RecyclerView、Spinner和浮动操作按钮等的事件监听和适配器。
  7. 实现接口方法:

    • onItemSelected(AdapterView<?> adapterView, View view, int position, long l)方法:当Spinner中的选项被选中时调用,根据选择的训练计划,更新展示的训练例程和训练细节列表。
    • onNothingSelected(AdapterView<?> adapterView)方法:当Spinner中没有选项被选中时调用,这里没有实现任何操作。
    • onRoutineItemClick(int itemPosition)方法:当点击训练例程列表中的某一项时调用,用于更新选中的训练例程,并刷新训练细节列表。
    • onExerciseItemClick(int itemPosition)方法:当点击训练细节列表中的某一项时调用,用于编辑选中的训练细节,打开一个新的Activity页面。

这段代码的主要功能是实现一个展示用户训练计划和训练细节的页面,并且支持添加新的训练计划、训练例程和训练细节。用户可以通过界面上的Spinner选择不同的训练计划,然后展示该计划下的训练例程和训练细节列表。用户还可以通过浮动操作按钮执行添加训练例程、训练细节和训练计划的操作。

三.项目源码

链接:https://pan.baidu.com/s/1F3fEFvEiiGqL1kNZLN_EHA?pwd=jynl
提取码:jynl

创作不易,项目已加密,有偿(仅一杯奶茶钱,可做实验报告,代码讲解等)

请私信作者或

(v)15135757306

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

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

相关文章

【IDEA + Spark 3.4.1 + sbt 1.9.3 + Spark MLlib 构建鸢尾花决策树分类预测模型】

决策树进行鸢尾花分类的案例 背景说明&#xff1a; 通过IDEA Spark 3.4.1 sbt 1.9.3 Spark MLlib 构建鸢尾花决策树分类预测模型&#xff0c;这是一个分类模型案例&#xff0c;通过该案例&#xff0c;可以快速了解Spark MLlib分类预测模型的使用方法。 依赖 ThisBuild /…

算法通关村第四关——如何基于数组实现栈

1.栈的基础知识 1.1 栈的特征 栈&#xff08;Stack&#xff09;&#xff1a;具有一定操作约束的线性表&#xff0c;只在一端&#xff08;栈顶&#xff0c;Top&#xff09;做插入&#xff08;Push&#xff09;、删除(Pop)&#xff0c;不可操作的一端称为栈底&#xff08;Botto…

C高级--day4(wc指令、case...in、while循环、for循环、select..in、break、continue、shell中的函数)

#!/bin/bash function fun() {uidid -u $namegidid -g $nameecho $uid $gid } read name retfun $name echo $ret

【docker】设置 docker 国内镜像报错问题,解决方案

一、报错&#xff1a; [rootlocalhost ~]# systemctl restart docker Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.二、原因&#xf…

UE5 半透明覆层材质

文章目录 前言介绍示例1示例2示例3 前言 本文采用虚幻5.2.1版本演示&#xff0c;介绍半透明覆层材质&#xff08;覆层材质&#xff09;。 介绍 半透明覆层材质是 UE5.1 版本 更新的功能&#xff0c;使用半透明覆层材质&#xff0c;可以轻松的给物体表面附着一层材质。 在UE5…

【Maven】常用命令、插件管理、私服nexus

【Maven】常用命令、插件管理、私服nexus 常用命令 插件管理 私服nexus Nexus3 配置私服 项目pom中的配置 发布时区分正式版、快照版 常用命令 Maven提供了一系列常用命令&#xff0c;用于构建、测试和管理项目。以下是一些常用的Maven命令示例&#xff1a; mvn clean:…

安装zabbix5.0监控

官网安装手册&#xff1a; https://www.zabbix.com/cn/download 一、 安装zabbix a. 安装yum源 rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/x86_64/zabbix-release-5.0-1.el7.noarch.rpmyum clean allb. 安装Zabbix server&#xff0c;web前端&#xff0c;agent y…

面试热题(翻转k个链表)

给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部的值&a…

《论文阅读13》Efficient Urban-scale Point Clouds Segmentationwith BEV Projection

一、论文 研究领域&#xff1a; 城市级3D语义分割论文&#xff1a;Efficient Urban-scale Point Clouds Segmentationwith BEV Projection论文链接 注&#xff1a; BEV&#xff1a; Birds Eye View BEV投影是指鸟瞰视角(Birds Eye View,简称BEV)的一种从上方观看对象或场景的…

【JavaEE】Spring Boot - 配置文件

【JavaEE】Spring Boot 开发要点总结&#xff08;2&#xff09; 文章目录 【JavaEE】Spring Boot 开发要点总结&#xff08;2&#xff09;1. 配置文件的两种格式2. .properties 文件2.1 基本语法2.2 注释2.3 配置项2.4 主动读取配置文件的键值2.5 数据库的连接时的需要的信息配…

面试热题(字符串相加)

给定两个字符串形式的非负整数 num1 和num2 &#xff0c;计算它们的和并同样以字符串形式返回。 你不能使用任何內建的用于处理大整数的库&#xff08;比如 BigInteger&#xff09;&#xff0c; 也不能直接将输入的字符串转换为整数形式。 输入&#xff1a;num1 "11"…

Mermaid系列之FlowChart流程图

一.欢迎来到我的酒馆 介绍mermaid下&#xff0c;Flowchat流程图语法。 目录 一.欢迎来到我的酒馆二.什么是mermiad工具三.在vs code中使用mermaid四.基本语法 二.什么是mermiad工具 2.1 mermaid可以让你使用代码来创建图表和可视化效果。mermaid是一款基于javascript语言的图表…

排序进行曲-v4.0

文章目录 小程一言快速排序步骤详细解释具体步骤 举例总结 复杂度分析时间复杂度分析&#xff1a;空间复杂度分析&#xff1a;注意 应用场景总结 实际举例结果总结 代码实现结果解释 小程一言 这篇文章是在排序进行曲3.0之后的续讲&#xff0c; 这篇文章主要是对快速排序进行细…

二、框架篇

框架篇 Spring 1. 基础核心技术 第1章-Spring的模块与应用场景 第2章-Spring基于XML配置的容器 第3章-Spring基于注解配置的容器 第4章-Spring基于Java配置的容器 第5章-Spring三种配置方式的混合和迁移 第6章-Spring同类型多个Bean的注入 第7章-Spring的Bean生命周期…

Mybatis案例-商品的增删改查

文章目录 1. aim2.环境准备3.查询3.1 查所有3.2 查看详情3.3 条件查询3.3.1 Mybatics如何接收参数&#xff1f;3.3.2 多条件查询3.3.3 动态条件查询3.3.4 单条件查询 4.添加主键返回 5.修改5.1 修改全部字段5.2 修改动态字段 6.删除6.1 删除1个6.2 批量删除 JDBC完成&#xff1…

【0804作业】顺序执行2个线程 (完成逆置打印、拷贝文件) (实现类似cat打印到终端)

作业1&#xff1a; 要求定义一个全局变量 char buf[] "1234567"&#xff0c;创建两个线程&#xff0c;不考虑退出条件 要求定义一个全局变量 char buf[] "1234567"&#xff0c;创建两个线程&#xff0c;不考虑退出条件&#xff0c;另&#xff1a; A线程循…

前端食堂技术周刊第 93 期:7 月登陆 Web 平台的新功能、Node.js 工具箱、Nuxt3 开发技巧、MF 重构方案

美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;橙橙冰萃美式 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 大家好&#xff0c;我是童欧巴。欢迎来到前端食堂技术周刊&#xff0c;我们先来…

第二天 什么是JWT ?

✅作者简介&#xff1a;大家好&#xff0c;我是Cisyam&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Cisyam-Shark的博客 &#x1f49e;当前专栏&#xff1a; 每天一个知识点 ✨特色专…

RocketMQ 主备自动切换模式部署

目录 主备自动切换模式部署 Controller 部署​ Controller 嵌入 NameServer 部署​ Controller 独立部署​ Broker 部署​ 兼容性​ 升级注意事项​ 主备自动切换模式部署 该文档主要介绍如何部署支持自动主从切换的 RocketMQ 集群&#xff0c;其架构如上图所示&#xff…

c++实现Qt信号和槽机制

文章目录 简介信号槽信号与槽的连接 特点观察者模式定义观察者模式结构图 实现简单的信号和槽 简介 信号槽机制与Windows下消息机制类似&#xff0c;消息机制是基于回调函数&#xff0c;Qt中用信号与槽来代替函数指针&#xff0c;使程序更安全简洁。  信号和槽机制是 Qt 的核心…