Los móviles Android son muy útiles y proporcionan la información de forma instantánea. Solo suponga que está continuamente volando o atendiendo pacientes o participando en reuniones, etc., con mucha frecuencia. Durante esos momentos, hay posibilidades de estresarse y, por lo tanto, la meditación es muy esencial en esta vida acelerada. Aquí proporcionamos el código fuente para la aplicación de ejercicios de respiración y seguramente eso será útil para tener más energía y entusiasmo. A continuación se proporciona un GIF de muestra para tener una idea de lo que vamos a hacer en este artículo. Tenga en cuenta que vamos a implementar este proyecto utilizando el lenguaje Java .
Implementación paso a paso
Paso 1: Crear un nuevo proyecto
Para crear un nuevo proyecto en Android Studio, consulte Cómo crear/iniciar un nuevo proyecto en Android Studio . Tenga en cuenta que seleccione Java como lenguaje de programación.
Paso 2: antes de ir a la sección de codificación, primero debe hacer una tarea previa
Vaya a la aplicación > res > valores > archivo colors.xml y configure los colores para su aplicación.
XML
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimaryLight">#5db839</color> <color name="colorPrimary">#0F9D58</color> <color name="colorPrimaryDark">#0F9D58</color> <color name="colorAccent">#FF4081</color> </resources>
Vaya al archivo Gradle Scripts > build.gradle (Módulo: aplicación) e importe las siguientes dependencias y haga clic en » Sincronizar ahora » en la ventana emergente anterior.
compile fileTree (dir: ‘libs’, incluya: [‘*.jar’])
androidTestCompile(‘com.android.support.test.espresso:espresso-core:2.2.2’, {
excluir grupo: ‘com.android.support’, módulo: ‘apoyo-anotaciones’
})
A continuación se muestra el código completo para el archivo build.gradle (Módulo: aplicación) :
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' }
Paso 3: diseñar la parte de la interfaz de usuario
Trabajando con el archivo activity_main.xml:
Vaya al archivo activity_main.xml y consulte el siguiente código. A continuación se muestra el código para el archivo activity_main.xml .
XML
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:orientation="vertical"> <include layout="@layout/content_main" /> </LinearLayout>
Aquí se incluyó content_main.xml . A continuación se muestra el código para ello:
XML
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/lt_content" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.example.breath.view.MainActivity"> <View android:id="@+id/view_circle_outer" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginLeft="@dimen/activity_horizontal_margin" android:layout_marginRight="@dimen/activity_horizontal_margin" android:background="@drawable/bg_circle_outer" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintDimensionRatio="1:1" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <View android:id="@+id/view_circle_inner" android:layout_width="150dp" android:layout_height="150dp" android:background="@drawable/bg_circle_inner" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.501" /> <TextView android:id="@+id/txt_status" android:layout_width="50dp" android:layout_height="wrap_content" android:gravity="center" android:text="HOLD" android:textColor="#4dd1b2" android:textSize="@dimen/hold_text_size" app:layout_constraintBottom_toBottomOf="@+id/view_circle_inner" app:layout_constraintLeft_toLeftOf="@+id/view_circle_inner" app:layout_constraintRight_toRightOf="@+id/view_circle_inner" app:layout_constraintTop_toTopOf="@+id/view_circle_inner" /> </android.support.constraint.ConstraintLayout>
Puede ver en el código anterior como «bg_circle_inner » y » bg_circle_outer «. Que necesitamos crear (Ir al dibujable > clic derecho > Nuevo > Archivo de recursos dibujable ) en la carpeta dibujable.
A continuación se muestra el código para el archivo bg_circle_inner.xml :
XML
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="@android:color/white" /> </shape>
A continuación se muestra el código para el archivo bg_circle_outer.xml :
XML
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <gradient android:angle="90" android:endColor="@color/colorPrimaryDark" android:startColor="@color/colorPrimaryLight" /> </shape>
Básicamente, bg_circle_outer.xml y bg_circle_inner.xml son los archivos XML que crean una forma ovalada y se usan en content_main.xml . Querían mostrar el propósito de » inhalar » y » exhalar «.
Paso 4: trabajar con el archivo Java
Trabajando con el archivo MainActivity.java:
Vaya al archivo MainActivity.java y consulte el siguiente código. A continuación se muestra el código del archivo 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; } }
Cree una nueva clase Java y nombre el archivo como SettingsUtils. A continuación se muestra el código para el archivo de clase 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; } }
Cree una nueva clase Java y nombre el archivo como BreathePreferences. A continuación se muestra el código para el archivo de clase 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(); } }
Cree una nueva clase Java y nombre el archivo como Constantes. A continuación se muestra el código para el archivo de clase 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; }
Cree una nueva enumeración de Java y nombre el archivo como Preset. A continuación se muestra el código para el archivo de clase 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; } }
Cree una nueva clase Java y nombre el archivo como SettingsDialog. A continuación se muestra el código para el archivo de clase 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); } }
En la ejecución del código, podemos obtener el resultado como se muestra en el video adjunto.
Producción:
Enlace Github: https://github.com/raj123raj/meditation
Publicación traducida automáticamente
Artículo escrito por priyarajtt y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA