Android手机非常方便,并且可以即时提供信息。只是假设您经常在连续飞行或参加患者或参加会议等。在那段时间里,可能会有压力,因此冥想在这种快速的生活中非常重要。这里提供了呼吸运动应用程序的源代码,并且肯定会有助于变得更有活力和热情。下面给出了一个示例GIF,以使我们对本文中要做的事情有一个了解。注意,我们将使用Java语言实现该项目。
分步实施
步骤1:创建一个新项目
要在Android Studio中创建新项目,请参阅如何在Android Studio中创建/启动新项目。请注意,选择Java作为编程语言。
第2步:首先进入编码部分,您必须做一些准备工作
转到应用程序> res>值> colors.xml文件,然后为您的应用程序设置颜色。
XML
#5db839
#0F9D58
#0F9D58
#FF4081
Java
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion "27.0.3"
defaultConfig {
applicationId "com.example.breath"
minSdkVersion 21
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:27.1.0'
compile 'com.android.support:design:27.1.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
}
XML
XML
XML
XML
Java
import android.os.Bundle;
import android.os.Handler;
import android.support.constraint.ConstraintLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
import com.example.breath.R;
import com.example.breath.utils.Constants;
import com.example.breath.utils.SettingsUtils;
public class MainActivity extends AppCompatActivity implements SettingsDialog.SettingsChangeListener {
private static final String TAG = MainActivity.class.getSimpleName();
private ConstraintLayout contentLayout;
private TextView statusText;
private View outerCircleView, innerCircleView;
private FloatingActionButton fab;
private Animation animationInhaleText, animationExhaleText, animationInhaleInnerCircle, animationExhaleInnerCircle;
private Handler handler = new Handler();
private int holdDuration = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contentLayout = findViewById(R.id.lt_content);
statusText = findViewById(R.id.txt_status);
statusText.setText(Constants.INHALE);
outerCircleView = findViewById(R.id.view_circle_outer);
innerCircleView = findViewById(R.id.view_circle_inner);
setupBackgroundColor();
prepareAnimations();
statusText.startAnimation(animationInhaleText);
innerCircleView.startAnimation(animationInhaleInnerCircle);
}
private void setupBackgroundColor() {
int backgroundResId = SettingsUtils.getBackgroundByPresetPosition(SettingsUtils.getSelectedPreset());
setOuterCircleBackground(R.color.colorPrimaryDark);
}
private void setOuterCircleBackground(int backgroundResId) {
outerCircleView.setBackgroundResource(backgroundResId);
}
private void setInhaleDuration(int duration) {
animationInhaleText.setDuration(duration);
animationInhaleInnerCircle.setDuration(duration);
}
private void setExhaleDuration(int duration) {
animationExhaleText.setDuration(duration);
animationExhaleInnerCircle.setDuration(duration);
}
private void prepareAnimations() {
int inhaleDuration = SettingsUtils.getSelectedInhaleDuration();
int exhaleDuration = SettingsUtils.getSelectedExhaleDuration();
holdDuration = SettingsUtils.getSelectedHoldDuration();
// Inhale - make large
animationInhaleText = AnimationUtils.loadAnimation(this, R.anim.anim_text_inhale);
animationInhaleText.setFillAfter(true);
animationInhaleText.setAnimationListener(inhaleAnimationListener);
animationInhaleInnerCircle = AnimationUtils.loadAnimation(this, R.anim.anim_inner_circle_inhale);
animationInhaleInnerCircle.setFillAfter(true);
animationInhaleInnerCircle.setAnimationListener(inhaleAnimationListener);
setInhaleDuration(inhaleDuration);
// Exhale - make small
animationExhaleText = AnimationUtils.loadAnimation(this, R.anim.anim_text_exhale);
animationExhaleText.setFillAfter(true);
animationExhaleText.setAnimationListener(exhaleAnimationListener);
animationExhaleInnerCircle = AnimationUtils.loadAnimation(this, R.anim.anim_inner_circle_exhale);
animationExhaleInnerCircle.setFillAfter(true);
animationExhaleInnerCircle.setAnimationListener(exhaleAnimationListener);
setExhaleDuration(exhaleDuration);
}
private Animation.AnimationListener inhaleAnimationListener = new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
Log.d(TAG, "inhale animation end");
statusText.setText(Constants.HOLD);
handler.postDelayed(new Runnable() {
@Override
public void run() {
statusText.setText(Constants.EXHALE);
statusText.startAnimation(animationExhaleText);
innerCircleView.startAnimation(animationExhaleInnerCircle);
}
}, holdDuration);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
};
private Animation.AnimationListener exhaleAnimationListener = new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
Log.d(TAG, "exhale animation end");
statusText.setText(Constants.HOLD);
handler.postDelayed(new Runnable() {
@Override
public void run() {
statusText.setText(Constants.INHALE);
statusText.startAnimation(animationInhaleText);
innerCircleView.startAnimation(animationInhaleInnerCircle);
}
}, holdDuration);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
};
@Override
public void onPresetChanged(int backgroundResId) {
setOuterCircleBackground(backgroundResId);
}
@Override
public void onInhaleValueChanged(int duration) {
setInhaleDuration(duration);
}
@Override
public void onExhaleValueChanged(int duration) {
setExhaleDuration(duration);
}
@Override
public void onHoldValueChanged(int duration) {
holdDuration = duration;
}
}
Java
public class SettingsUtils {
public static int getBackgroundByPresetPosition(int position) {
Preset preset = Preset.values()[position];
return preset.getResId();
}
public static void saveSelectedPreset(int presetIndex) {
BreathePreferences.getInstance().putInt(BreathePreferences.SELECTED_PRESET_KEY, presetIndex);
}
public static int getSelectedPreset() {
int preset = BreathePreferences.getInstance().getInt(BreathePreferences.SELECTED_PRESET_KEY);
return preset != -1 ? preset : Constants.DEFAULT_PRESET_INDEX;
}
public static void saveSelectedInhaleDuration(int duration) {
BreathePreferences.getInstance().putInt(BreathePreferences.SELECTED_INHALE_DURATION_KEY, duration);
}
public static int getSelectedInhaleDuration() {
int duration = BreathePreferences.getInstance().getInt(BreathePreferences.SELECTED_INHALE_DURATION_KEY);
return duration != -1 ? duration : Constants.DEFAULT_DURATION;
}
public static void saveSelectedExhaleDuration(int duration) {
BreathePreferences.getInstance().putInt(BreathePreferences.SELECTED_EXHALE_DURATION_KEY, duration);
}
public static int getSelectedExhaleDuration() {
int duration = BreathePreferences.getInstance().getInt(BreathePreferences.SELECTED_EXHALE_DURATION_KEY);
return duration != -1 ? duration : Constants.DEFAULT_DURATION;
}
public static void saveSelectedHoldDuration(int duration) {
BreathePreferences.getInstance().putInt(BreathePreferences.SELECTED_HOLD_DURATION_KEY, duration);
}
public static int getSelectedHoldDuration() {
int duration = BreathePreferences.getInstance().getInt(BreathePreferences.SELECTED_HOLD_DURATION_KEY);
return duration != -1 ? duration : Constants.DEFAULT_DURATION;
}
}
Java
import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
public class BreathePreferences {
static final String SELECTED_PRESET_KEY = "selectedPreset";
static final String SELECTED_INHALE_DURATION_KEY = "selectedInhaleDuration";
static final String SELECTED_EXHALE_DURATION_KEY = "selectedExhaleDuration";
static final String SELECTED_HOLD_DURATION_KEY = "selectedHoldDuration";
private static final String BREATHE_PREFS = "BreathePreferences";
private static BreathePreferences instance;
private SharedPreferences prefs;
private BreathePreferences(@NonNull Context context) {
prefs = context.getSharedPreferences(BREATHE_PREFS, Context.MODE_PRIVATE);
}
public static void init(@NonNull Context context) {
if (instance == null) {
instance = new BreathePreferences(context);
}
}
public static BreathePreferences getInstance() {
if (instance == null) {
Log.e(BreathePreferences.class.getSimpleName(), "Call init() first");
}
return instance;
}
public void putString(@NonNull String key, @NonNull String value) {
prefs.edit().putString(key, value).apply();
}
public void putLong(@NonNull String key, long value) {
prefs.edit().putLong(key, value).apply();
}
public void putInt(@NonNull String key, int value) {
prefs.edit().putInt(key, value).apply();
}
public void putFloat(@NonNull String key, float value) {
prefs.edit().putFloat(key, value).apply();
}
@Nullable
public String getString(@NonNull String key) {
return prefs.getString(key, null);
}
public long getLong(@NonNull String key) {
return prefs.getLong(key, -1);
}
public int getInt(@NonNull String key) {
return prefs.getInt(key, -1);
}
public float getFloat(@NonNull String key) {
return prefs.getFloat(key, -1);
}
public void clearAll() {
prefs.edit().clear().apply();
}
}
Java
public class Constants {
// Texts to show inside the breathing circle
public static final String INHALE = "INHALE";
public static final String EXHALE = "EXHALE";
public static final String HOLD = "HOLD";
// FAB button visibility delay
public static int CONTENT_SHOW_DELAY_MS = 2000;
// Defaults for @{@link SettingsUtils}
public static final int DEFAULT_PRESET_INDEX = 0;
public static final int DEFAULT_DURATION = 6000;
// Value used to convert between animation
// duration and seekbar unit
public static final int MILLISECOND = 2000;
}
Java
import com.example.breath.R;
public enum Preset {
WARM_FLAME(0, R.drawable.bg_circle_preset_warm_flame),
NIGHT_FADE(1, R.drawable.bg_circle_preset_night_fade),
WINTER_NEVA(2, R.drawable.bg_circle_preset_winter_neva),
MORNING_SALAD(3, R.drawable.bg_circle_outer),
SOFT_GRASS(4, R.drawable.bg_circle_preset_soft_grass);
private final int settingsPosition;
private final int resId;
Preset(int settingsPosition, int resId) {
this.settingsPosition = settingsPosition;
this.resId = resId;
}
public int getResId() {
return resId;
}
}
Java
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import com.example.breath.R;
import com.example.breath.utils.Constants;
import com.example.breath.utils.Preset;
import com.example.breath.utils.SettingsUtils;
public class SettingsDialog extends Dialog {
private SettingsChangeListener listener;
private RadioGroup radioGroup;
public SettingsDialog(@NonNull Context context, @NonNull SettingsChangeListener listener) {
super(context, R.style.Theme_SettingsDialog);
this.listener = listener;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.v_overlay);
getWindow().getAttributes().windowAnimations = R.style.Theme_SettingsDialog;
radioGroup = findViewById(R.id.rg_gradients);
SeekBar inhaleSeekBar = findViewById(R.id.seekBar_inhale);
SeekBar exhaleSeekBar = findViewById(R.id.seekBar_exhale);
SeekBar holdSeekBar = findViewById(R.id.seekBar_hold);
Button closeButton = findViewById(R.id.btn_close);
radioGroup.setOnCheckedChangeListener(checkedChangeListener);
inhaleSeekBar.setOnSeekBarChangeListener(inhaleSeekBarChangeListener);
exhaleSeekBar.setOnSeekBarChangeListener(exhaleSeekBarChangeListener);
holdSeekBar.setOnSeekBarChangeListener(holdSeekBarChangeListener);
closeButton.setOnClickListener(closeBtnClickListener);
((RadioButton) radioGroup.getChildAt(SettingsUtils.getSelectedPreset())).setChecked(true);
inhaleSeekBar.setProgress(SettingsUtils.getSelectedInhaleDuration() / Constants.MILLISECOND);
exhaleSeekBar.setProgress(SettingsUtils.getSelectedExhaleDuration() / Constants.MILLISECOND);
holdSeekBar.setProgress(SettingsUtils.getSelectedHoldDuration() / Constants.MILLISECOND);
}
private RadioGroup.OnCheckedChangeListener checkedChangeListener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
Preset selectedPreset;
switch (checkedId) {
case R.id.rb_1:
selectedPreset = Preset.WARM_FLAME;
break;
case R.id.rb_2:
selectedPreset = Preset.NIGHT_FADE;
break;
case R.id.rb_3:
selectedPreset = Preset.WINTER_NEVA;
break;
case R.id.rb_4:
selectedPreset = Preset.MORNING_SALAD;
break;
case R.id.rb_5:
selectedPreset = Preset.SOFT_GRASS;
break;
default:
selectedPreset = Preset.WARM_FLAME;
break;
}
SettingsUtils.saveSelectedPreset(selectedPreset.ordinal());
listener.onPresetChanged(selectedPreset.getResId());
}
};
private SeekBar.OnSeekBarChangeListener inhaleSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
listener.onInhaleValueChanged(progress != 0 ? progress * Constants.MILLISECOND : Constants.MILLISECOND);
SettingsUtils.saveSelectedInhaleDuration(progress != 0 ? progress * Constants.MILLISECOND :
Constants.MILLISECOND);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
private SeekBar.OnSeekBarChangeListener exhaleSeekBarChangeListener = new SeekBar
.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
listener.onExhaleValueChanged(progress != 0 ? progress * Constants.MILLISECOND : Constants.MILLISECOND);
SettingsUtils.saveSelectedExhaleDuration(progress != 0 ? progress * Constants.MILLISECOND :
Constants.MILLISECOND);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
private SeekBar.OnSeekBarChangeListener holdSeekBarChangeListener = new SeekBar
.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
listener.onHoldValueChanged(progress * Constants.MILLISECOND);
SettingsUtils.saveSelectedHoldDuration(progress * Constants.MILLISECOND);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
private View.OnClickListener closeBtnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
};
public interface SettingsChangeListener {
void onPresetChanged(int backgroundResId);
void onInhaleValueChanged(int duration);
void onExhaleValueChanged(int duration);
void onHoldValueChanged(int duration);
}
}
转到Gradle脚本> build.gradle(模块:应用程序)文件并导入以下依赖项,然后在上面的弹出窗口中单击“立即同步”。
compile fileTree(dir: ‘libs’, include: [‘*.jar’])
androidTestCompile(‘com.android.support.test.espresso:espresso-core:2.2.2’, {
exclude group: ‘com.android.support’, module: ‘support-annotations’
})
以下是build.gradle(模块:app)文件的完整代码:
Java
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion "27.0.3"
defaultConfig {
applicationId "com.example.breath"
minSdkVersion 21
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:27.1.0'
compile 'com.android.support:design:27.1.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
}
步骤3:设计UI部件
使用activity_main.xml文件:
转到activity_main.xml文件,并参考以下代码。以下是activity_main.xml文件的代码。
XML格式
这里,包含了content_main.xml 。下面是它的代码:
XML格式
您可以在上面的代码中看到“ bg_circle_inner ”和“ bg_circle_outer ”。我们需要在drawable文件夹中创建(转到drawable>右键单击> New> Drawable Resource File )。
以下是bg_circle_inner.xml文件的代码:
XML格式
以下是bg_circle_outer.xml文件的代码:
XML格式
基本上, bg_circle_outer.xml和bg_circle_inner.xml是创建椭圆形的XML文件,它们在content_main.xml中使用。它们的目的是显示“吸气”和“呼气”的目的。
步骤4:使用Java文件
使用MainActivity。 Java文件:
转到MainActivity。 Java文件并参考以下代码。下面是MainActivity的代码。 Java文件。
Java
import android.os.Bundle;
import android.os.Handler;
import android.support.constraint.ConstraintLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
import com.example.breath.R;
import com.example.breath.utils.Constants;
import com.example.breath.utils.SettingsUtils;
public class MainActivity extends AppCompatActivity implements SettingsDialog.SettingsChangeListener {
private static final String TAG = MainActivity.class.getSimpleName();
private ConstraintLayout contentLayout;
private TextView statusText;
private View outerCircleView, innerCircleView;
private FloatingActionButton fab;
private Animation animationInhaleText, animationExhaleText, animationInhaleInnerCircle, animationExhaleInnerCircle;
private Handler handler = new Handler();
private int holdDuration = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contentLayout = findViewById(R.id.lt_content);
statusText = findViewById(R.id.txt_status);
statusText.setText(Constants.INHALE);
outerCircleView = findViewById(R.id.view_circle_outer);
innerCircleView = findViewById(R.id.view_circle_inner);
setupBackgroundColor();
prepareAnimations();
statusText.startAnimation(animationInhaleText);
innerCircleView.startAnimation(animationInhaleInnerCircle);
}
private void setupBackgroundColor() {
int backgroundResId = SettingsUtils.getBackgroundByPresetPosition(SettingsUtils.getSelectedPreset());
setOuterCircleBackground(R.color.colorPrimaryDark);
}
private void setOuterCircleBackground(int backgroundResId) {
outerCircleView.setBackgroundResource(backgroundResId);
}
private void setInhaleDuration(int duration) {
animationInhaleText.setDuration(duration);
animationInhaleInnerCircle.setDuration(duration);
}
private void setExhaleDuration(int duration) {
animationExhaleText.setDuration(duration);
animationExhaleInnerCircle.setDuration(duration);
}
private void prepareAnimations() {
int inhaleDuration = SettingsUtils.getSelectedInhaleDuration();
int exhaleDuration = SettingsUtils.getSelectedExhaleDuration();
holdDuration = SettingsUtils.getSelectedHoldDuration();
// Inhale - make large
animationInhaleText = AnimationUtils.loadAnimation(this, R.anim.anim_text_inhale);
animationInhaleText.setFillAfter(true);
animationInhaleText.setAnimationListener(inhaleAnimationListener);
animationInhaleInnerCircle = AnimationUtils.loadAnimation(this, R.anim.anim_inner_circle_inhale);
animationInhaleInnerCircle.setFillAfter(true);
animationInhaleInnerCircle.setAnimationListener(inhaleAnimationListener);
setInhaleDuration(inhaleDuration);
// Exhale - make small
animationExhaleText = AnimationUtils.loadAnimation(this, R.anim.anim_text_exhale);
animationExhaleText.setFillAfter(true);
animationExhaleText.setAnimationListener(exhaleAnimationListener);
animationExhaleInnerCircle = AnimationUtils.loadAnimation(this, R.anim.anim_inner_circle_exhale);
animationExhaleInnerCircle.setFillAfter(true);
animationExhaleInnerCircle.setAnimationListener(exhaleAnimationListener);
setExhaleDuration(exhaleDuration);
}
private Animation.AnimationListener inhaleAnimationListener = new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
Log.d(TAG, "inhale animation end");
statusText.setText(Constants.HOLD);
handler.postDelayed(new Runnable() {
@Override
public void run() {
statusText.setText(Constants.EXHALE);
statusText.startAnimation(animationExhaleText);
innerCircleView.startAnimation(animationExhaleInnerCircle);
}
}, holdDuration);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
};
private Animation.AnimationListener exhaleAnimationListener = new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
Log.d(TAG, "exhale animation end");
statusText.setText(Constants.HOLD);
handler.postDelayed(new Runnable() {
@Override
public void run() {
statusText.setText(Constants.INHALE);
statusText.startAnimation(animationInhaleText);
innerCircleView.startAnimation(animationInhaleInnerCircle);
}
}, holdDuration);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
};
@Override
public void onPresetChanged(int backgroundResId) {
setOuterCircleBackground(backgroundResId);
}
@Override
public void onInhaleValueChanged(int duration) {
setInhaleDuration(duration);
}
@Override
public void onExhaleValueChanged(int duration) {
setExhaleDuration(duration);
}
@Override
public void onHoldValueChanged(int duration) {
holdDuration = duration;
}
}
创建一个新的Java类,并将文件命名为SettingsUtils。以下是SettingsUtils的代码。 Java类文件。
Java
public class SettingsUtils {
public static int getBackgroundByPresetPosition(int position) {
Preset preset = Preset.values()[position];
return preset.getResId();
}
public static void saveSelectedPreset(int presetIndex) {
BreathePreferences.getInstance().putInt(BreathePreferences.SELECTED_PRESET_KEY, presetIndex);
}
public static int getSelectedPreset() {
int preset = BreathePreferences.getInstance().getInt(BreathePreferences.SELECTED_PRESET_KEY);
return preset != -1 ? preset : Constants.DEFAULT_PRESET_INDEX;
}
public static void saveSelectedInhaleDuration(int duration) {
BreathePreferences.getInstance().putInt(BreathePreferences.SELECTED_INHALE_DURATION_KEY, duration);
}
public static int getSelectedInhaleDuration() {
int duration = BreathePreferences.getInstance().getInt(BreathePreferences.SELECTED_INHALE_DURATION_KEY);
return duration != -1 ? duration : Constants.DEFAULT_DURATION;
}
public static void saveSelectedExhaleDuration(int duration) {
BreathePreferences.getInstance().putInt(BreathePreferences.SELECTED_EXHALE_DURATION_KEY, duration);
}
public static int getSelectedExhaleDuration() {
int duration = BreathePreferences.getInstance().getInt(BreathePreferences.SELECTED_EXHALE_DURATION_KEY);
return duration != -1 ? duration : Constants.DEFAULT_DURATION;
}
public static void saveSelectedHoldDuration(int duration) {
BreathePreferences.getInstance().putInt(BreathePreferences.SELECTED_HOLD_DURATION_KEY, duration);
}
public static int getSelectedHoldDuration() {
int duration = BreathePreferences.getInstance().getInt(BreathePreferences.SELECTED_HOLD_DURATION_KEY);
return duration != -1 ? duration : Constants.DEFAULT_DURATION;
}
}
创建一个新的Java类,并将文件命名为BreathePreferences。下面是BreathePreferences的代码。 Java类文件。
Java
import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
public class BreathePreferences {
static final String SELECTED_PRESET_KEY = "selectedPreset";
static final String SELECTED_INHALE_DURATION_KEY = "selectedInhaleDuration";
static final String SELECTED_EXHALE_DURATION_KEY = "selectedExhaleDuration";
static final String SELECTED_HOLD_DURATION_KEY = "selectedHoldDuration";
private static final String BREATHE_PREFS = "BreathePreferences";
private static BreathePreferences instance;
private SharedPreferences prefs;
private BreathePreferences(@NonNull Context context) {
prefs = context.getSharedPreferences(BREATHE_PREFS, Context.MODE_PRIVATE);
}
public static void init(@NonNull Context context) {
if (instance == null) {
instance = new BreathePreferences(context);
}
}
public static BreathePreferences getInstance() {
if (instance == null) {
Log.e(BreathePreferences.class.getSimpleName(), "Call init() first");
}
return instance;
}
public void putString(@NonNull String key, @NonNull String value) {
prefs.edit().putString(key, value).apply();
}
public void putLong(@NonNull String key, long value) {
prefs.edit().putLong(key, value).apply();
}
public void putInt(@NonNull String key, int value) {
prefs.edit().putInt(key, value).apply();
}
public void putFloat(@NonNull String key, float value) {
prefs.edit().putFloat(key, value).apply();
}
@Nullable
public String getString(@NonNull String key) {
return prefs.getString(key, null);
}
public long getLong(@NonNull String key) {
return prefs.getLong(key, -1);
}
public int getInt(@NonNull String key) {
return prefs.getInt(key, -1);
}
public float getFloat(@NonNull String key) {
return prefs.getFloat(key, -1);
}
public void clearAll() {
prefs.edit().clear().apply();
}
}
创建一个新的Java类,并将文件命名为Constants。下面是常量的代码。 Java类文件。
Java
public class Constants {
// Texts to show inside the breathing circle
public static final String INHALE = "INHALE";
public static final String EXHALE = "EXHALE";
public static final String HOLD = "HOLD";
// FAB button visibility delay
public static int CONTENT_SHOW_DELAY_MS = 2000;
// Defaults for @{@link SettingsUtils}
public static final int DEFAULT_PRESET_INDEX = 0;
public static final int DEFAULT_DURATION = 6000;
// Value used to convert between animation
// duration and seekbar unit
public static final int MILLISECOND = 2000;
}
创建一个新的Java Enum并将文件命名为Preset。以下是预设的代码。 Java类文件。
Java
import com.example.breath.R;
public enum Preset {
WARM_FLAME(0, R.drawable.bg_circle_preset_warm_flame),
NIGHT_FADE(1, R.drawable.bg_circle_preset_night_fade),
WINTER_NEVA(2, R.drawable.bg_circle_preset_winter_neva),
MORNING_SALAD(3, R.drawable.bg_circle_outer),
SOFT_GRASS(4, R.drawable.bg_circle_preset_soft_grass);
private final int settingsPosition;
private final int resId;
Preset(int settingsPosition, int resId) {
this.settingsPosition = settingsPosition;
this.resId = resId;
}
public int getResId() {
return resId;
}
}
创建一个新的Java类,并将文件命名为SettingsDialog。下面是SettingsDialog的代码。 Java类文件。
Java
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import com.example.breath.R;
import com.example.breath.utils.Constants;
import com.example.breath.utils.Preset;
import com.example.breath.utils.SettingsUtils;
public class SettingsDialog extends Dialog {
private SettingsChangeListener listener;
private RadioGroup radioGroup;
public SettingsDialog(@NonNull Context context, @NonNull SettingsChangeListener listener) {
super(context, R.style.Theme_SettingsDialog);
this.listener = listener;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.v_overlay);
getWindow().getAttributes().windowAnimations = R.style.Theme_SettingsDialog;
radioGroup = findViewById(R.id.rg_gradients);
SeekBar inhaleSeekBar = findViewById(R.id.seekBar_inhale);
SeekBar exhaleSeekBar = findViewById(R.id.seekBar_exhale);
SeekBar holdSeekBar = findViewById(R.id.seekBar_hold);
Button closeButton = findViewById(R.id.btn_close);
radioGroup.setOnCheckedChangeListener(checkedChangeListener);
inhaleSeekBar.setOnSeekBarChangeListener(inhaleSeekBarChangeListener);
exhaleSeekBar.setOnSeekBarChangeListener(exhaleSeekBarChangeListener);
holdSeekBar.setOnSeekBarChangeListener(holdSeekBarChangeListener);
closeButton.setOnClickListener(closeBtnClickListener);
((RadioButton) radioGroup.getChildAt(SettingsUtils.getSelectedPreset())).setChecked(true);
inhaleSeekBar.setProgress(SettingsUtils.getSelectedInhaleDuration() / Constants.MILLISECOND);
exhaleSeekBar.setProgress(SettingsUtils.getSelectedExhaleDuration() / Constants.MILLISECOND);
holdSeekBar.setProgress(SettingsUtils.getSelectedHoldDuration() / Constants.MILLISECOND);
}
private RadioGroup.OnCheckedChangeListener checkedChangeListener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
Preset selectedPreset;
switch (checkedId) {
case R.id.rb_1:
selectedPreset = Preset.WARM_FLAME;
break;
case R.id.rb_2:
selectedPreset = Preset.NIGHT_FADE;
break;
case R.id.rb_3:
selectedPreset = Preset.WINTER_NEVA;
break;
case R.id.rb_4:
selectedPreset = Preset.MORNING_SALAD;
break;
case R.id.rb_5:
selectedPreset = Preset.SOFT_GRASS;
break;
default:
selectedPreset = Preset.WARM_FLAME;
break;
}
SettingsUtils.saveSelectedPreset(selectedPreset.ordinal());
listener.onPresetChanged(selectedPreset.getResId());
}
};
private SeekBar.OnSeekBarChangeListener inhaleSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
listener.onInhaleValueChanged(progress != 0 ? progress * Constants.MILLISECOND : Constants.MILLISECOND);
SettingsUtils.saveSelectedInhaleDuration(progress != 0 ? progress * Constants.MILLISECOND :
Constants.MILLISECOND);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
private SeekBar.OnSeekBarChangeListener exhaleSeekBarChangeListener = new SeekBar
.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
listener.onExhaleValueChanged(progress != 0 ? progress * Constants.MILLISECOND : Constants.MILLISECOND);
SettingsUtils.saveSelectedExhaleDuration(progress != 0 ? progress * Constants.MILLISECOND :
Constants.MILLISECOND);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
private SeekBar.OnSeekBarChangeListener holdSeekBarChangeListener = new SeekBar
.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
listener.onHoldValueChanged(progress * Constants.MILLISECOND);
SettingsUtils.saveSelectedHoldDuration(progress * Constants.MILLISECOND);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
private View.OnClickListener closeBtnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
};
public interface SettingsChangeListener {
void onPresetChanged(int backgroundResId);
void onInhaleValueChanged(int duration);
void onExhaleValueChanged(int duration);
void onHoldValueChanged(int duration);
}
}
执行代码后,我们可以获取输出,如随附的视频所示。
输出:
Github链接: https : //github.com/raj123raj/meditation