This commit is contained in:
ADITYA
2023-07-07 21:07:04 +05:30
parent 0242aa3b73
commit 9171f96e8e
264 changed files with 10366 additions and 1465 deletions

123
.idea/codeStyles/Project.xml generated Normal file
View File

@@ -0,0 +1,123 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<runningDeviceTargetSelectedWithDropDown>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="5203ae2be8ec4353" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-06-29T11:46:37.575091600Z" />
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -45,16 +45,22 @@ dependencies {
// circle indicator for viewpager
implementation 'me.relex:circleindicator:2.1.6'
// picasso
implementation 'com.squareup.picasso:picasso:2.8'
// Glide
implementation 'com.github.bumptech.glide:glide:4.15.1'
// lottie animations
// lottie
def lottieVersion = "3.4.0"
implementation "com.airbnb.android:lottie:$lottieVersion"
// dynamic text size
implementation 'com.intuit.ssp:ssp-android:1.1.0'
// spinners
implementation "com.github.skydoves:powerspinner:1.2.7"
// cicle image view
implementation 'de.hdodenhof:circleimageview:3.1.0'
implementation 'androidx.appcompat:appcompat:1.6.0'
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,17 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group android:scaleX="1.0149242"
android:scaleY="1.0149242"
android:translateX="28.26"
android:translateY="31.110922">
<path
android:pathData="M24.849,0.438c-0.259,0.252 -0.881,0.846 -1.365,1.318s-1.577,1.516 -2.423,2.321 -1.9,1.823 -2.355,2.253 -1.181,1.14 -1.632,1.57 -1.174,1.126 -1.611,1.55 -0.983,0.942 -1.229,1.167l-0.444,0.41 -0.02,-2.792 -0.014,-2.792h-6.485v11.851l-0.56,0.546c-0.314,0.293 -1.256,1.2 -2.1,2.007 -1.536,1.468 -2.642,2.533 -3.925,3.775l-0.683,0.662h3.857L3.86,45.11h43.009v-9.981l-0.594,0.532c-0.335,0.3 -0.614,0.553 -0.635,0.58 -0.109,0.123 -1.666,1.365 -2.389,1.9a90.439,90.439 0,0 1,-9.148 5.721c-0.171,0.089 -0.41,0.232 -0.539,0.307l-0.232,0.143 0.048,-0.273a3.611,3.611 0,0 0,-0.792 -3.379,13.934 13.934,0 0,0 -1.488,-1.1 31.878,31.878 0,0 1,-2.833 -2.041,20.765 20.765,0 0,1 -4.089,-3.885 7.26,7.26 0,0 1,-1.2 -3.577,7.1 7.1,0 0,1 2.048,-5.7 6.831,6.831 0,0 1,4.867 -2.171,6.5 6.5,0 0,1 2.471,0.3 7.392,7.392 0,0 1,3.516 2.444l0.287,0.369 0.239,-0.321a7.641,7.641 0,0 1,2.355 -2,7.075 7.075,0 0,1 3.7,-0.792 6.951,6.951 0,0 1,4.383 1.727l0.43,0.369h3.454l-0.751,-0.737c-0.416,-0.4 -1.106,-1.065 -1.536,-1.481s-1.2,-1.147 -1.707,-1.638 -1.645,-1.577 -2.526,-2.423l-3.311,-3.174c-0.075,-0.075 -0.457,-0.444 -0.853,-0.819s-1.051,-1 -1.468,-1.4 -1.12,-1.072 -1.57,-1.5c-0.853,-0.812 -1.9,-1.816 -3.413,-3.27 -0.485,-0.471 -1.208,-1.161 -1.6,-1.536s-1.133,-1.085 -1.638,-1.577c-1.754,-1.693 -4.929,-4.71 -4.97,-4.724A2.558,2.558 0,0 0,24.849 0.438Z"
android:fillColor="#fff"/>
<path
android:pathData="M29.846,25.076a6.243,6.243 0,0 0,-3.516 2.007A6,6 0,0 0,24.883 31.029a6.008,6.008 0,0 0,1.126 3.666,26.87 26.87,0 0,0 5.673,4.792 5.047,5.047 0,0 1,1.659 1.55,4.491 4.491,0 0,1 0.485,1.754 0.7,0.7 0,0 0,0.068 0.369,60.61 60.61,0 0,0 7.346,-4.431 25.025,25.025 0,0 0,4.574 -4.041,6.6 6.6,0 0,0 0.949,-2.089 7.027,7.027 0,0 0,0.089 -1.741,4.139 4.139,0 0,0 -0.239,-1.816 6.027,6.027 0,0 0,-3.045 -3.427,6.019 6.019,0 0,0 -4.533,-0.335 6.119,6.119 0,0 0,-2.737 1.877l-0.389,0.478 -0.171,-0.225a8.693,8.693 0,0 0,-1.372 -1.331A6.018,6.018 0,0 0,29.846 25.076ZM31.109,31.589a1.833,1.833 0,0 1,1.024 0.881,1.837 1.837,0 0,1 -0.43,2.212A1.784,1.784 0,0 1,28.783 33.197,1.8 1.8,0 0,1 31.109,31.589ZM36.352,31.623a1.806,1.806 0,0 1,0.6 3.011,1.573 1.573,0 0,1 -1.188,0.457 1.75,1.75 0,0 1,-1.782 -1.932A1.779,1.779 0,0 1,36.352 31.623ZM41.552,31.623a1.752,1.752 0,0 1,1.167 1.686,1.771 1.771,0 0,1 -3.011,1.277A1.787,1.787 0,0 1,41.547 31.623Z"
android:fillColor="#fff"/>
</group>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#1B6DC1</color>
</resources>

View File

@@ -14,8 +14,11 @@
android:supportsRtl="true"
android:theme="@style/Theme.SimpliTend"
tools:targetApi="31">
<activity
android:name=".welcome.activities.WelcomeActivity"
android:configChanges="orientation"
android:screenOrientation="portrait"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@@ -2,9 +2,20 @@ package com.ssb.simplitend.apputils;
import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import androidx.annotation.RawRes;
import com.bumptech.glide.Glide;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.ssb.simplitend.R;
import com.ssb.simplitend.databinding.DecisionBottomsheetBinding;
import com.ssb.simplitend.databinding.DoneBottomsheetBinding;
public abstract class AppUtil {
// closes keyboard
@@ -18,4 +29,63 @@ public abstract class AppUtil {
}
}
// show decision dialog
public static void showSOSDecision(@NonNull Context context,
@NonNull String decisionText,
@NonNull String positiveText, @NonNull String negativeText,
View.OnClickListener positiveClickListener,
View.OnClickListener negativeClickListener) {
DecisionBottomsheetBinding binding = DecisionBottomsheetBinding.inflate(LayoutInflater.from(context));
BottomSheetDialog bsd = new BottomSheetDialog(context, R.style.BottomSheetDialog);
bsd.setContentView(binding.getRoot());
bsd.setCancelable(false);
binding.text.setText(decisionText);
binding.positiveBtn.setText(positiveText);
binding.negativeBtn.setText(negativeText);
binding.negativeBtn.setOnClickListener(v -> {
bsd.dismiss();
negativeClickListener.onClick(v);
});
binding.positiveBtn.setOnClickListener(v -> {
bsd.dismiss();
positiveClickListener.onClick(v);
});
bsd.show();
}
public static void showAnimateDBS(@NonNull Context context,
@NonNull String title,
@RawRes int rawRes, long doneInterval,
@NonNull View.OnClickListener doneListener){
DoneBottomsheetBinding binding = DoneBottomsheetBinding.inflate(LayoutInflater.from(context));
BottomSheetDialog bsd = new BottomSheetDialog(context, R.style.BottomSheetDialog);
bsd.setContentView(binding.getRoot());
bsd.setCancelable(false);
binding.text.setText(title);
Glide.with(context)
.asGif()
.load(rawRes)
.into(binding.doneAnim);
bsd.show();
new Handler().postDelayed(() -> {
bsd.dismiss();
doneListener.onClick(null);
}, doneInterval);
}
}

View File

@@ -0,0 +1,12 @@
package com.ssb.simplitend.apputils;
/*
This a static data of user's profile progress
THIS FILE WILL BE DELETED AFTERWARDS
*/
public class ProfileProgress {
public static final boolean[] PROFILE_PROGRESS = {false, false, false, false};
}

View File

@@ -0,0 +1,30 @@
package com.ssb.simplitend.medicalinfo;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.ssb.simplitend.databinding.AddMedicalInfoBinding;
public class AddMedicalInfoFragment extends Fragment {
// view binding
protected AddMedicalInfoBinding binding;
public AddMedicalInfoFragment(){
// required empty const.
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = AddMedicalInfoBinding.inflate(inflater, container, false);
return binding.getRoot();
}
}

View File

@@ -0,0 +1,44 @@
package com.ssb.simplitend.medicalinfo;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import com.ssb.simplitend.R;
import com.ssb.simplitend.databinding.MedicalIntoFragmentBinding;
public class MedicalInfoFragment extends Fragment {
// view binding
protected MedicalIntoFragmentBinding binding;
public MedicalInfoFragment(){
// required empty const.
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = MedicalIntoFragmentBinding.inflate(inflater, container, false);
clickEvents();
return binding.getRoot();
}
private void clickEvents() {
binding.addMedInfo.setOnClickListener(v ->
{
Navigation.findNavController(v).navigate(R.id.action_medicalInfoFragment_to_addMedicalInfoFragment);
}
);
}
}

View File

@@ -0,0 +1,346 @@
package com.ssb.simplitend.medreminder;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import com.ssb.simplitend.R;
import com.ssb.simplitend.apputils.AppUtil;
import com.ssb.simplitend.databinding.AddReminderFragmentBinding;
import com.ssb.simplitend.medreminder.mvvm.Reminder;
import com.ssb.simplitend.welcome.fragments.contacts.mvvm.Contact;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;
public class AddReminderFragment extends Fragment implements CompoundButton.OnCheckedChangeListener {
// view binding
protected AddReminderFragmentBinding binding;
/*
week day selection states
true -> selected
false -> un-selected
*/
boolean[] week_state;
// arguments keys
public static final String REMINDER_KEY = "reminder_key";
// model
private Reminder reminder;
public AddReminderFragment() {
// required empty const.
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = AddReminderFragmentBinding.inflate(inflater, container, false);
initViews();
clickEvents();
return binding.getRoot();
}
private void clickEvents() {
binding.getTime.setOnClickListener(v -> {
AppUtil.closeKeyboard(requireActivity());
getTime();
});
binding.getDate.setOnClickListener(v -> {
AppUtil.closeKeyboard(requireActivity());
getDate();
});
binding.addReminder.setOnClickListener(v -> {
if (reminder == null){
Navigation.findNavController(v).popBackStack(R.id.reminderFragment, false, true);
}else{
AppUtil.showSOSDecision(requireContext(), getString(R.string.make_changes),
getString(R.string.yes), getString(R.string.no),
v1 -> {
// yes click
AppUtil.showAnimateDBS(requireContext(),
getString(R.string.changes_successful), R.raw.done_anim_primary,
3000, v3 -> {
// here v3 is null
Navigation.findNavController(v).popBackStack(R.id.reminderFragment, false, true);
});
}, v2 -> {
// no click
});
}
});
}
@SuppressLint("ClickableViewAccessibility")
private void initViews() {
// checking if intent to EDIT or ADD reminder
Bundle bundle = getArguments();
if (bundle != null) setLayoutDetails(reminder = (Reminder) bundle.getSerializable(REMINDER_KEY));
// scrolling instruction edit text
binding.instructions.setOnTouchListener((v, event) -> {
if (binding.instructions.hasFocus()) {
v.getParent().requestDisallowInterceptTouchEvent(true);
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_SCROLL) {
v.getParent().requestDisallowInterceptTouchEvent(false);
return true;
}
}
return false;
});
// load into spinner
loadMedType();
loadFrequency();
setUpWeekSelection();
binding.everydayCheck.setOnCheckedChangeListener(this);
}
private void setLayoutDetails(Reminder reminder){
if (reminder != null){
// intent is to edit the reminder
binding.title.setText(getString(R.string.edit_reminder));
binding.medicName.setText(reminder.dosage_name);
binding.quantity.setText(reminder.quantity);
binding.getTime.setText(reminder.time);
}
}
// every-dau toggle listener
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
for (int i = 0; i < 7; i++) {
setSelectionState(i, week_state[i] = isChecked);
}
}
// set selection and un-selection of week day
private void setUpWeekSelection() {
week_state = new boolean[7];
// week day selections
binding.sun.setOnClickListener(v -> setSelectionState(0, week_state[0] = !week_state[0]));
binding.mon.setOnClickListener(v -> setSelectionState(1, week_state[1] = !week_state[1]));
binding.tue.setOnClickListener(v -> setSelectionState(2, week_state[2] = !week_state[2]));
binding.wed.setOnClickListener(v -> setSelectionState(3, week_state[3] = !week_state[3]));
binding.thu.setOnClickListener(v -> setSelectionState(4, week_state[4] = !week_state[4]));
binding.fri.setOnClickListener(v -> setSelectionState(5, week_state[5] = !week_state[5]));
binding.sat.setOnClickListener(v -> setSelectionState(6, week_state[6] = !week_state[6]));
}
private void setSelectionState(int position, boolean selection) {
if (selection) {
// selection has to be made
switch (position) {
case 0:
// sun
binding.sun.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
binding.sun.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
break;
case 1:
// mon
binding.mon.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
binding.mon.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
break;
case 2:
// tue
binding.tue.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
binding.tue.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
break;
case 3:
// wed
binding.wed.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
binding.wed.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
break;
case 4:
// thu
binding.thu.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
binding.thu.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
break;
case 5:
// fri
binding.fri.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
binding.fri.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
break;
case 6:
// sat
binding.sat.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
binding.sat.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
break;
}
} else {
// un-selection has to be made
switch (position) {
case 0:
// sun
binding.sun.setBackgroundTintList(null);
binding.sun.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
break;
case 1:
// mon
binding.mon.setBackgroundTintList(null);
binding.mon.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
break;
case 2:
// tue
binding.tue.setBackgroundTintList(null);
binding.tue.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
break;
case 3:
// wed
binding.wed.setBackgroundTintList(null);
binding.wed.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
break;
case 4:
// thu
binding.thu.setBackgroundTintList(null);
binding.thu.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
break;
case 5:
// fri
binding.fri.setBackgroundTintList(null);
binding.fri.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
break;
case 6:
// sat
binding.sat.setBackgroundTintList(null);
binding.sat.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
break;
}
}
// checking if all days are selected or not
// thus, updating the Everyday switch accordingly
boolean isEveryDay = true;
for (int i = 0; i < 7; i++) {
if (!week_state[i]) {
// some day is not selected thus not everyday selection
isEveryDay = false;
break;
}
}
binding.everydayCheck.setOnCheckedChangeListener(null);
binding.everydayCheck.setChecked(isEveryDay);
binding.everydayCheck.setOnCheckedChangeListener(this);
}
// shows date picker to pick date and set to tv
private void getDate() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
DatePickerDialog dpd = new DatePickerDialog(requireContext());
dpd.setOnDateSetListener((view, year, month, dayOfMonth) -> {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);
SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy", Locale.getDefault());
String selected_time = sdf.format(cal.getTime());
binding.getDate.setText(selected_time);
});
dpd.show();
}
// TODO: 05-07-2023 for lower version
}
// shows time picker to pick time and set to textview
private void getTime() {
Calendar calendar = Calendar.getInstance(Locale.getDefault());
TimePickerDialog tpd = new TimePickerDialog(requireContext(),
(TimePickerDialog.OnTimeSetListener) (view, hourOfDay, minute) -> {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
cal.set(Calendar.MINUTE, minute);
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm a", Locale.getDefault());
String selected_time = sdf.format(cal.getTime());
binding.getTime.setText(selected_time);
}, calendar.getTime().getHours(), calendar.getTime().getMinutes(), false);
tpd.show();
}
// loading freq. into its resp. spinner
private void loadFrequency() {
// static data
ArrayList<String> medTypeList = new ArrayList<>();
medTypeList.add("1 time, Daily");
medTypeList.add("2 time, Daily");
medTypeList.add("3 time, Daily");
binding.frequencySpinner.setLifecycleOwner(this);
binding.frequencySpinner.setItems(medTypeList);
binding.frequencySpinner.setDismissWhenNotifiedItemSelected(true);
binding.frequencySpinner.setIsFocusable(true);
}
// loads med types into its resp. apinner
private void loadMedType() {
// static data
ArrayList<String> medTypeList = new ArrayList<>();
medTypeList.add("Lorem ipsum");
medTypeList.add("Lorem ipsum");
medTypeList.add("Lorem ipsum");
binding.medicationsSpinner.setLifecycleOwner(this);
binding.medicationsSpinner.setItems(medTypeList);
binding.medicationsSpinner.setDismissWhenNotifiedItemSelected(true);
binding.medicationsSpinner.setIsFocusable(true);
}
}

View File

@@ -0,0 +1,7 @@
package com.ssb.simplitend.medreminder;
import android.view.MotionEvent;
public interface OnActivityTouchListener {
void getTouchCoordinates(MotionEvent ev);
}

View File

@@ -0,0 +1,915 @@
package com.ssb.simplitend.medreminder;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.graphics.Rect;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.DecelerateInterpolator;
import android.widget.ListView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener, OnActivityTouchListener {
private static final String TAG = "RecyclerTouchListener";
final Handler handler = new Handler();
Activity act;
List<Integer> unSwipeableRows;
/*
* independentViews are views on the foreground layer which when clicked, act "independent" from the foreground
* ie, they are treated separately from the "row click" action
*/
List<Integer> independentViews;
List<Integer> unClickableRows;
List<Integer> optionViews;
Set<Integer> ignoredViewTypes;
// Cached ViewConfiguration and system-wide constant values
private int touchSlop;
private int minFlingVel;
private int maxFlingVel;
private long ANIMATION_STANDARD = 300;
private long ANIMATION_CLOSE = 150;
// Fixed properties
private RecyclerView rView;
// private SwipeListener mSwipeListener;
private int bgWidth = 1, bgWidthLeft = 1; // 1 and not 0 to prevent dividing by zero
// Transient properties
// private List<PendingDismissData> mPendingDismisses = new ArrayList<>();
private int mDismissAnimationRefCount = 0;
private float touchedX;
private float touchedY;
private boolean isFgSwiping;
private int mSwipingSlop;
private VelocityTracker mVelocityTracker;
private int touchedPosition;
private View touchedView;
private boolean mPaused;
private boolean bgVisible, fgPartialViewClicked;
private int bgVisiblePosition;
private View bgVisibleView;
private boolean isRViewScrolling;
private int heightOutsideRView, screenHeight;
private boolean mLongClickPerformed;
// Foreground view (to be swiped), Background view (to show)
private View fgView;
private View bgView;
//view ID
private int fgViewID;
private int bgViewID, bgViewIDLeft;
private ArrayList<Integer> fadeViews;
private OnRowClickListener mRowClickListener;
private OnRowLongClickListener mRowLongClickListener;
private OnSwipeOptionsClickListener mBgClickListener, mBgClickListenerLeft;
// user choices
private boolean clickable = false;
private boolean longClickable = false;
private boolean swipeable = false, swipeableLeftOptions = false;
private int LONG_CLICK_DELAY = 800;
private boolean longClickVibrate;
Runnable mLongPressed = new Runnable() {
public void run() {
if (!longClickable)
return;
mLongClickPerformed = true;
if (!bgVisible && touchedPosition >= 0 && !unClickableRows.contains(touchedPosition) && !isRViewScrolling) {
if (longClickVibrate) {
// Vibrator vibe = (Vibrator) act.getSystemService(Context.VIBRATOR_SERVICE);
// vibe.vibrate(100); // do we really need to add vibrate service
}
mRowLongClickListener.onRowLongClicked(touchedPosition);
}
}
};
public RecyclerTouchListener(Activity a, RecyclerView recyclerView) {
this.act = a;
ViewConfiguration vc = ViewConfiguration.get(recyclerView.getContext());
touchSlop = vc.getScaledTouchSlop();
minFlingVel = vc.getScaledMinimumFlingVelocity() * 16;
maxFlingVel = vc.getScaledMaximumFlingVelocity();
rView = recyclerView;
bgVisible = false;
bgVisiblePosition = -1;
bgVisibleView = null;
fgPartialViewClicked = false;
unSwipeableRows = new ArrayList<>();
unClickableRows = new ArrayList<>();
ignoredViewTypes = new HashSet<>();
independentViews = new ArrayList<>();
optionViews = new ArrayList<>();
fadeViews = new ArrayList<>();
isRViewScrolling = false;
// mSwipeListener = listener;
rView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
/**
* This will ensure that this RecyclerTouchListener is paused during recycler view scrolling.
* If a scroll listener is already assigned, the caller should still pass scroll changes through
* to this listener.
*/
setEnabled(newState != RecyclerView.SCROLL_STATE_DRAGGING);
/**
* This is used so that clicking a row cannot be done while scrolling
*/
isRViewScrolling = newState != RecyclerView.SCROLL_STATE_IDLE;
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
}
});
}
/**
* Enables or disables (pauses or resumes) watching for swipe-to-dismiss gestures.
*
* @param enabled Whether or not to watch for gestures.
*/
public void setEnabled(boolean enabled) {
mPaused = !enabled;
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent motionEvent) {
return handleTouchEvent(motionEvent);
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent motionEvent) {
handleTouchEvent(motionEvent);
}
/*////////////// Clickable ////////////////////*/
public RecyclerTouchListener setClickable(OnRowClickListener listener) {
this.clickable = true;
this.mRowClickListener = listener;
return this;
}
public RecyclerTouchListener setClickable(boolean clickable) {
this.clickable = clickable;
return this;
}
public RecyclerTouchListener setLongClickable(boolean vibrate, OnRowLongClickListener listener) {
this.longClickable = true;
this.mRowLongClickListener = listener;
this.longClickVibrate = vibrate;
return this;
}
public RecyclerTouchListener setLongClickable(boolean longClickable) {
this.longClickable = longClickable;
return this;
}
public RecyclerTouchListener setIndependentViews(Integer... viewIds) {
this.independentViews = new ArrayList<>(Arrays.asList(viewIds));
return this;
}
public RecyclerTouchListener setUnClickableRows(Integer... rows) {
this.unClickableRows = new ArrayList<>(Arrays.asList(rows));
return this;
}
public RecyclerTouchListener setIgnoredViewTypes(Integer... viewTypes) {
ignoredViewTypes.clear();
ignoredViewTypes.addAll(Arrays.asList(viewTypes));
return this;
}
//////////////// Swipeable ////////////////////
public RecyclerTouchListener setSwipeable(int foregroundID, int backgroundID, OnSwipeOptionsClickListener listener) {
this.swipeable = true;
if (fgViewID != 0 && foregroundID != fgViewID)
throw new IllegalArgumentException("foregroundID does not match previously set ID");
fgViewID = foregroundID;
bgViewID = backgroundID;
this.mBgClickListener = listener;
if (act instanceof RecyclerTouchListenerHelper)
((RecyclerTouchListenerHelper) act).setOnActivityTouchListener(this);
DisplayMetrics displaymetrics = new DisplayMetrics();
act.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
screenHeight = displaymetrics.heightPixels;
return this;
}
public RecyclerTouchListener setSwipeable(boolean value) {
this.swipeable = value;
if (!value)
invalidateSwipeOptions();
return this;
}
public RecyclerTouchListener setSwipeOptionViews(Integer... viewIds) {
this.optionViews = new ArrayList<>(Arrays.asList(viewIds));
return this;
}
public RecyclerTouchListener setUnSwipeableRows(Integer... rows) {
this.unSwipeableRows = new ArrayList<>(Arrays.asList(rows));
return this;
}
//////////////// Fade Views ////////////////////
// Set views which are faded out as fg is opened
public RecyclerTouchListener setViewsToFade(Integer... viewIds) {
this.fadeViews = new ArrayList<>(Arrays.asList(viewIds));
return this;
}
// the entire foreground is faded out as it is opened
public RecyclerTouchListener setFgFade() {
if (!fadeViews.contains(fgViewID))
this.fadeViews.add(fgViewID);
return this;
}
//-------------- Checkers for preventing ---------------//
private boolean isIndependentViewClicked(MotionEvent motionEvent) {
for (int i = 0; i < independentViews.size(); i++) {
if (touchedView != null) {
Rect rect = new Rect();
int x = (int) motionEvent.getRawX();
int y = (int) motionEvent.getRawY();
touchedView.findViewById(independentViews.get(i)).getGlobalVisibleRect(rect);
if (rect.contains(x, y)) {
return false;
}
}
}
return true;
}
private int getOptionViewID(MotionEvent motionEvent) {
for (int i = 0; i < optionViews.size(); i++) {
if (touchedView != null) {
Rect rect = new Rect();
int x = (int) motionEvent.getRawX();
int y = (int) motionEvent.getRawY();
touchedView.findViewById(optionViews.get(i)).getGlobalVisibleRect(rect);
if (rect.contains(x, y)) {
return optionViews.get(i);
}
}
}
return -1;
}
private int getIndependentViewID(MotionEvent motionEvent) {
for (int i = 0; i < independentViews.size(); i++) {
if (touchedView != null) {
Rect rect = new Rect();
int x = (int) motionEvent.getRawX();
int y = (int) motionEvent.getRawY();
touchedView.findViewById(independentViews.get(i)).getGlobalVisibleRect(rect);
if (rect.contains(x, y)) {
return independentViews.get(i);
}
}
}
return -1;
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
public void invalidateSwipeOptions() {
bgWidth = 1;
}
public void openSwipeOptions(int position) {
if (!swipeable || rView.getChildAt(position) == null
|| unSwipeableRows.contains(position) || shouldIgnoreAction(position))
return;
if (bgWidth < 2) {
if (act.findViewById(bgViewID) != null)
bgWidth = act.findViewById(bgViewID).getWidth();
heightOutsideRView = screenHeight - rView.getHeight();
}
touchedPosition = position;
touchedView = rView.getChildAt(position);
fgView = touchedView.findViewById(fgViewID);
bgView = touchedView.findViewById(bgViewID);
bgView.setMinimumHeight(fgView.getHeight());
closeVisibleBG(null);
animateFG(touchedView, Animation.OPEN, ANIMATION_STANDARD);
bgVisible = true;
bgVisibleView = fgView;
bgVisiblePosition = touchedPosition;
}
@Deprecated
public void closeVisibleBG() {
if (bgVisibleView == null) {
Log.e(TAG, "No rows found for which background options are visible");
return;
}
bgVisibleView.animate()
.translationX(0)
.setDuration(ANIMATION_CLOSE)
.setListener(null);
animateFadeViews(bgVisibleView, 1f, ANIMATION_CLOSE);
bgVisible = false;
bgVisibleView = null;
bgVisiblePosition = -1;
}
public void closeVisibleBG(final OnSwipeListener mSwipeCloseListener) {
if (bgVisibleView == null) {
Log.e(TAG, "No rows found for which background options are visible");
return;
}
final ObjectAnimator translateAnimator = ObjectAnimator.ofFloat(bgVisibleView,
View.TRANSLATION_X, 0f);
translateAnimator.setDuration(ANIMATION_CLOSE);
translateAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if (mSwipeCloseListener != null)
mSwipeCloseListener.onSwipeOptionsClosed();
translateAnimator.removeAllListeners();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
translateAnimator.start();
animateFadeViews(bgVisibleView, 1f, ANIMATION_CLOSE);
bgVisible = false;
bgVisibleView = null;
bgVisiblePosition = -1;
}
private void animateFadeViews(View downView, float alpha, long duration) {
if (fadeViews != null) {
for (final int viewID : fadeViews) {
downView.findViewById(viewID).animate()
.alpha(alpha)
.setDuration(duration);
}
}
}
private void animateFG(View downView, Animation animateType, long duration) {
if (animateType == Animation.OPEN) {
ObjectAnimator translateAnimator = ObjectAnimator.ofFloat(
fgView, View.TRANSLATION_X, -bgWidth);
translateAnimator.setDuration(duration);
translateAnimator.setInterpolator(new DecelerateInterpolator(1.5f));
translateAnimator.start();
animateFadeViews(downView, 0f, duration);
} else if (animateType == Animation.CLOSE) {
ObjectAnimator translateAnimator = ObjectAnimator.ofFloat(
fgView, View.TRANSLATION_X, 0f);
translateAnimator.setDuration(duration);
translateAnimator.setInterpolator(new DecelerateInterpolator(1.5f));
translateAnimator.start();
animateFadeViews(downView, 1f, duration);
}
}
private void animateFG(View downView, final Animation animateType, long duration,
final OnSwipeListener mSwipeCloseListener) {
final ObjectAnimator translateAnimator;
if (animateType == Animation.OPEN) {
translateAnimator = ObjectAnimator.ofFloat(fgView, View.TRANSLATION_X, -bgWidth);
translateAnimator.setDuration(duration);
translateAnimator.setInterpolator(new DecelerateInterpolator(1.5f));
translateAnimator.start();
animateFadeViews(downView, 0f, duration);
} else /*if (animateType == Animation.CLOSE)*/ {
translateAnimator = ObjectAnimator.ofFloat(fgView, View.TRANSLATION_X, 0f);
translateAnimator.setDuration(duration);
translateAnimator.setInterpolator(new DecelerateInterpolator(1.5f));
translateAnimator.start();
animateFadeViews(downView, 1f, duration);
}
translateAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if (mSwipeCloseListener != null) {
if (animateType == Animation.OPEN)
mSwipeCloseListener.onSwipeOptionsOpened();
else if (animateType == Animation.CLOSE)
mSwipeCloseListener.onSwipeOptionsClosed();
}
translateAnimator.removeAllListeners();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
private boolean handleTouchEvent(MotionEvent motionEvent) {
if (swipeable && bgWidth < 2) {
// bgWidth = rView.getWidth();
if (act.findViewById(bgViewID) != null)
bgWidth = act.findViewById(bgViewID).getWidth();
heightOutsideRView = screenHeight - rView.getHeight();
}
switch (motionEvent.getActionMasked()) {
// When finger touches screen
case MotionEvent.ACTION_DOWN: {
if (mPaused) {
break;
}
// Find the child view that was touched (perform a hit test)
Rect rect = new Rect();
int childCount = rView.getChildCount();
int[] listViewCoords = new int[2];
rView.getLocationOnScreen(listViewCoords);
// x and y values respective to the recycler view
int x = (int) motionEvent.getRawX() - listViewCoords[0];
int y = (int) motionEvent.getRawY() - listViewCoords[1];
View child;
/*
* check for every child (row) in the recycler view whether the touched co-ordinates belong to that
* respective child and if it does, register that child as the touched view (touchedView)
*/
for (int i = 0; i < childCount; i++) {
child = rView.getChildAt(i);
child.getHitRect(rect);
if (rect.contains(x, y)) {
touchedView = child;
break;
}
}
if (touchedView != null) {
touchedX = motionEvent.getRawX();
touchedY = motionEvent.getRawY();
touchedPosition = rView.getChildAdapterPosition(touchedView);
if (shouldIgnoreAction(touchedPosition)) {
touchedPosition = ListView.INVALID_POSITION;
return false; // <-- guard here allows for ignoring events, allowing more than one view type and preventing NPE
}
if (longClickable) {
mLongClickPerformed = false;
handler.postDelayed(mLongPressed, LONG_CLICK_DELAY);
}
if (swipeable) {
mVelocityTracker = VelocityTracker.obtain();
mVelocityTracker.addMovement(motionEvent);
fgView = touchedView.findViewById(fgViewID);
bgView = touchedView.findViewById(bgViewID);
// bgView.getLayoutParams().height = fgView.getHeight();
bgView.setMinimumHeight(fgView.getHeight());
/*
* bgVisible is true when the options menu is opened
* This block is to register fgPartialViewClicked status - Partial view is the view that is still
* shown on the screen if the options width is < device width
*/
if (bgVisible && fgView != null) {
handler.removeCallbacks(mLongPressed);
x = (int) motionEvent.getRawX();
y = (int) motionEvent.getRawY();
fgView.getGlobalVisibleRect(rect);
fgPartialViewClicked = rect.contains(x, y);
} else {
fgPartialViewClicked = false;
}
}
}
/*
* If options menu is shown and the touched position is not the same as the row for which the
* options is displayed - close the options menu for the row which is displaying it
* (bgVisibleView and bgVisiblePosition is used for this purpose which registers which view and
* which position has it's options menu opened)
*/
x = (int) motionEvent.getRawX();
y = (int) motionEvent.getRawY();
rView.getHitRect(rect);
if (swipeable && bgVisible && touchedPosition != bgVisiblePosition) {
handler.removeCallbacks(mLongPressed);
closeVisibleBG(null);
}
break;
}
case MotionEvent.ACTION_CANCEL: {
handler.removeCallbacks(mLongPressed);
if (mLongClickPerformed)
break;
if (mVelocityTracker == null) {
break;
}
if (swipeable) {
if (touchedView != null && isFgSwiping) {
// cancel
animateFG(touchedView, Animation.CLOSE, ANIMATION_STANDARD);
}
mVelocityTracker.recycle();
mVelocityTracker = null;
isFgSwiping = false;
bgView = null;
}
touchedX = 0;
touchedY = 0;
touchedView = null;
touchedPosition = ListView.INVALID_POSITION;
break;
}
// When finger is lifted off the screen (after clicking, flinging, swiping, etc..)
case MotionEvent.ACTION_UP: {
handler.removeCallbacks(mLongPressed);
if (mLongClickPerformed)
break;
if (mVelocityTracker == null && swipeable) {
break;
}
if (touchedPosition < 0)
break;
// swipedLeft and swipedRight are true if the user swipes in the respective direction (no conditions)
boolean swipedLeft = false;
boolean swipedRight = false;
/*
* swipedLeftProper and swipedRightProper are true if user swipes in the respective direction
* and if certain conditions are satisfied (given some few lines below)
*/
boolean swipedLeftProper = false;
boolean swipedRightProper = false;
float mFinalDelta = motionEvent.getRawX() - touchedX;
// if swiped in a direction, make that respective variable true
if (isFgSwiping) {
swipedLeft = mFinalDelta < 0;
swipedRight = mFinalDelta > 0;
}
/*
* If the user has swiped more than half of the width of the options menu, or if the
* velocity of swiping is between min and max fling values
* "proper" variable are set true
*/
if (Math.abs(mFinalDelta) > bgWidth / 2 && isFgSwiping) {
swipedLeftProper = mFinalDelta < 0;
swipedRightProper = mFinalDelta > 0;
} else if (swipeable) {
mVelocityTracker.addMovement(motionEvent);
mVelocityTracker.computeCurrentVelocity(1000);
float velocityX = mVelocityTracker.getXVelocity();
float absVelocityX = Math.abs(velocityX);
float absVelocityY = Math.abs(mVelocityTracker.getYVelocity());
if (minFlingVel <= absVelocityX && absVelocityX <= maxFlingVel
&& absVelocityY < absVelocityX && isFgSwiping) {
// dismiss only if flinging in the same direction as dragging
swipedLeftProper = (velocityX < 0) == (mFinalDelta < 0);
swipedRightProper = (velocityX > 0) == (mFinalDelta > 0);
}
}
///////// Manipulation of view based on the 4 variables mentioned above ///////////
// if swiped left properly and options menu isn't already visible, animate the foreground to the left
if (swipeable && !swipedRight && swipedLeftProper && touchedPosition != RecyclerView.NO_POSITION
&& !unSwipeableRows.contains(touchedPosition) && !bgVisible) {
final View downView = touchedView; // touchedView gets null'd before animation ends
final int downPosition = touchedPosition;
++mDismissAnimationRefCount;
//TODO - speed
animateFG(touchedView, Animation.OPEN, ANIMATION_STANDARD);
bgVisible = true;
bgVisibleView = fgView;
bgVisiblePosition = downPosition;
}
// else if swiped right properly when options menu is visible, close the menu and bring the foreground
// to it's original position
else if (swipeable && !swipedLeft && swipedRightProper && touchedPosition != RecyclerView.NO_POSITION
&& !unSwipeableRows.contains(touchedPosition) && bgVisible) {
// dismiss
final View downView = touchedView; // touchedView gets null'd before animation ends
final int downPosition = touchedPosition;
++mDismissAnimationRefCount;
//TODO - speed
animateFG(touchedView, Animation.CLOSE, ANIMATION_STANDARD);
bgVisible = false;
bgVisibleView = null;
bgVisiblePosition = -1;
}
// else if swiped left incorrectly (not satisfying the above conditions), animate the foreground back to
// it's original position (spring effect)
else if (swipeable && swipedLeft && !bgVisible) {
// cancel
final View tempBgView = bgView;
animateFG(touchedView, Animation.CLOSE, ANIMATION_STANDARD, new OnSwipeListener() {
@Override
public void onSwipeOptionsClosed() {
if (tempBgView != null)
tempBgView.setVisibility(View.VISIBLE);
}
@Override
public void onSwipeOptionsOpened() {
}
});
bgVisible = false;
bgVisibleView = null;
bgVisiblePosition = -1;
}
// else if swiped right incorrectly (not satisfying the above conditions), animate the foreground to
// it's open position (spring effect)
else if (swipeable && swipedRight && bgVisible) {
// cancel
animateFG(touchedView, Animation.OPEN, ANIMATION_STANDARD);
bgVisible = true;
bgVisibleView = fgView;
bgVisiblePosition = touchedPosition;
}
// This case deals with an error where the user can swipe left, then right
// really fast and the fg is stuck open - so in that case we close the fg
else if (swipeable && swipedRight && !bgVisible) {
// cancel
animateFG(touchedView, Animation.CLOSE, ANIMATION_STANDARD);
bgVisible = false;
bgVisibleView = null;
bgVisiblePosition = -1;
}
// This case deals with an error where the user can swipe right, then left
// really fast and the fg is stuck open - so in that case we open the fg
else if (swipeable && swipedLeft && bgVisible) {
// cancel
animateFG(touchedView, Animation.OPEN, ANIMATION_STANDARD);
bgVisible = true;
bgVisibleView = fgView;
bgVisiblePosition = touchedPosition;
}
// if clicked
else if (!swipedRight && !swipedLeft) {
// if partial foreground view is clicked (see ACTION_DOWN) bring foreground back to original position
// bgVisible is true automatically since it's already checked in ACTION_DOWN block
if (swipeable && fgPartialViewClicked) {
animateFG(touchedView, Animation.CLOSE, ANIMATION_STANDARD);
bgVisible = false;
bgVisibleView = null;
bgVisiblePosition = -1;
}
// On Click listener for rows
else if (clickable && !bgVisible && touchedPosition >= 0 && !unClickableRows.contains(touchedPosition)
&& isIndependentViewClicked(motionEvent) && !isRViewScrolling) {
mRowClickListener.onRowClicked(touchedPosition);
}
// On Click listener for independent views inside the rows
else if (clickable && !bgVisible && touchedPosition >= 0 && !unClickableRows.contains(touchedPosition)
&& !isIndependentViewClicked(motionEvent) && !isRViewScrolling) {
final int independentViewID = getIndependentViewID(motionEvent);
if (independentViewID >= 0)
mRowClickListener.onIndependentViewClicked(independentViewID, touchedPosition);
}
// On Click listener for background options
else if (swipeable && bgVisible && !fgPartialViewClicked) {
final int optionID = getOptionViewID(motionEvent);
if (optionID >= 0 && touchedPosition >= 0) {
final int downPosition = touchedPosition;
closeVisibleBG(new OnSwipeListener() {
@Override
public void onSwipeOptionsClosed() {
mBgClickListener.onSwipeOptionClicked(optionID, downPosition);
}
@Override
public void onSwipeOptionsOpened() {
}
});
}
}
}
}
// if clicked and not swiped
if (swipeable) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
touchedX = 0;
touchedY = 0;
touchedView = null;
touchedPosition = ListView.INVALID_POSITION;
isFgSwiping = false;
bgView = null;
break;
// when finger is moving across the screen (and not yet lifted)
case MotionEvent.ACTION_MOVE: {
if (mLongClickPerformed)
break;
if (mVelocityTracker == null || mPaused || !swipeable) {
break;
}
mVelocityTracker.addMovement(motionEvent);
float deltaX = motionEvent.getRawX() - touchedX;
float deltaY = motionEvent.getRawY() - touchedY;
/*
* isFgSwiping variable which is set to true here is used to alter the swipedLeft, swipedRightProper
* variables in "ACTION_UP" block by checking if user is actually swiping at present or not
*/
if (!isFgSwiping && Math.abs(deltaX) > touchSlop && Math.abs(deltaY) < Math.abs(deltaX) / 2) {
handler.removeCallbacks(mLongPressed);
isFgSwiping = true;
mSwipingSlop = (deltaX > 0 ? touchSlop : -touchSlop);
}
// This block moves the foreground along with the finger when swiping
if (swipeable && isFgSwiping && !unSwipeableRows.contains(touchedPosition)) {
if (bgView == null) {
bgView = touchedView.findViewById(bgViewID);
bgView.setVisibility(View.VISIBLE);
}
// if fg is being swiped left
if (deltaX < touchSlop && !bgVisible) {
float translateAmount = deltaX - mSwipingSlop;
// if ((Math.abs(translateAmount) > bgWidth ? -bgWidth : translateAmount) <= 0) {
// swipe fg till width of bg. If swiped further, nothing happens (stalls at width of bg)
fgView.setTranslationX(Math.abs(translateAmount) > bgWidth ? -bgWidth : translateAmount);
if (fgView.getTranslationX() > 0) fgView.setTranslationX(0);
// }
// fades all the fadeViews gradually to 0 alpha as dragged
if (fadeViews != null) {
for (int viewID : fadeViews) {
touchedView.findViewById(viewID).setAlpha(1 - (Math.abs(translateAmount) / bgWidth));
}
}
}
// if fg is being swiped right
else if (deltaX > 0 && bgVisible) {
// for closing rightOptions
if (bgVisible) {
float translateAmount = (deltaX - mSwipingSlop) - bgWidth;
// swipe fg till it reaches original position. If swiped further, nothing happens (stalls at 0)
fgView.setTranslationX(translateAmount > 0 ? 0 : translateAmount);
// fades all the fadeViews gradually to 0 alpha as dragged
if (fadeViews != null) {
for (int viewID : fadeViews) {
touchedView.findViewById(viewID).setAlpha(1 - (Math.abs(translateAmount) / bgWidth));
}
}
}
// for opening leftOptions
else {
float translateAmount = (deltaX - mSwipingSlop) - bgWidth;
// swipe fg till it reaches original position. If swiped further, nothing happens (stalls at 0)
fgView.setTranslationX(translateAmount > 0 ? 0 : translateAmount);
// fades all the fadeViews gradually to 0 alpha as dragged
if (fadeViews != null) {
for (int viewID : fadeViews) {
touchedView.findViewById(viewID).setAlpha(1 - (Math.abs(translateAmount) / bgWidth));
}
}
}
}
return true;
}
// moves the fg slightly to give the illusion of an "unswipeable" row
else if (swipeable && isFgSwiping && unSwipeableRows.contains(touchedPosition)) {
if (deltaX < touchSlop && !bgVisible) {
float translateAmount = deltaX - mSwipingSlop;
if (bgView == null)
bgView = touchedView.findViewById(bgViewID);
if (bgView != null)
bgView.setVisibility(View.GONE);
// swipe fg till width of bg. If swiped further, nothing happens (stalls at width of bg)
fgView.setTranslationX(translateAmount / 5);
if (fgView.getTranslationX() > 0) fgView.setTranslationX(0);
// fades all the fadeViews gradually to 0 alpha as dragged
// if (fadeViews != null) {
// for (int viewID : fadeViews) {
// touchedView.findViewById(viewID).setAlpha(1 - (Math.abs(translateAmount) / bgWidth));
// }
// }
}
return true;
}
break;
}
}
return false;
}
/**
* Gets coordinates from Activity and closes any
* swiped rows if touch happens outside the recycler view
*/
@Override
public void getTouchCoordinates(MotionEvent ev) {
int y = (int) ev.getRawY();
if (swipeable && bgVisible && ev.getActionMasked() == MotionEvent.ACTION_DOWN
&& y < heightOutsideRView) closeVisibleBG(null);
}
private boolean shouldIgnoreAction(int touchedPosition) {
return rView == null || ignoredViewTypes.contains(rView.getAdapter().getItemViewType(touchedPosition));
}
private enum Animation {
OPEN, CLOSE
}
///////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// Interfaces /////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
public interface OnRowClickListener {
void onRowClicked(int position);
void onIndependentViewClicked(int independentViewID, int position);
}
public interface OnRowLongClickListener {
void onRowLongClicked(int position);
}
public interface OnSwipeOptionsClickListener {
void onSwipeOptionClicked(int viewID, int position);
}
public interface RecyclerTouchListenerHelper {
void setOnActivityTouchListener(OnActivityTouchListener listener);
}
public interface OnSwipeListener {
void onSwipeOptionsClosed();
void onSwipeOptionsOpened();
}
}

View File

@@ -0,0 +1,277 @@
package com.ssb.simplitend.medreminder;
import static com.ssb.simplitend.medreminder.AddReminderFragment.REMINDER_KEY;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.ssb.simplitend.R;
import com.ssb.simplitend.apputils.AppUtil;
import com.ssb.simplitend.apputils.ProfileProgress;
import com.ssb.simplitend.databinding.RemindersFragmentBinding;
import com.ssb.simplitend.medreminder.mvvm.Reminder;
import com.ssb.simplitend.medreminder.mvvm.ReminderViewModel;
public class ReminderFragment extends Fragment implements RecyclerTouchListener.OnSwipeOptionsClickListener {
// view binding
protected RemindersFragmentBinding binding;
// reminders viewmodel
protected ReminderViewModel reminderViewModel;
// recycler touch listener for swipe menu
protected RecyclerTouchListener recyclerTouchListener;
// selection state for week days
/*
true -> date selected
false -> date unselected
*/
private boolean[] selection_state;
private static final String SELECTION_STATE_KEY = "selection_state";
public ReminderFragment(){
// required empty const.
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = RemindersFragmentBinding.inflate(inflater, container, false);
initViews(savedInstanceState);
clickEvents();
return binding.getRoot();
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBooleanArray(SELECTION_STATE_KEY, selection_state);
}
private void clickEvents() {
// date selections
binding.sun.setOnClickListener(v -> {
setSelectionState(0, selection_state[0] = !selection_state[0]);
loadReminderList();
});
binding.mon.setOnClickListener(v -> {
setSelectionState(1, selection_state[1] = !selection_state[1]);
loadReminderList();
});
binding.tue.setOnClickListener(v -> {
setSelectionState(2, selection_state[2] = !selection_state[2]);
loadReminderList();
});
binding.wed.setOnClickListener(v -> {
setSelectionState(3, selection_state[3] = !selection_state[3]);
loadReminderList();
});
binding.thu.setOnClickListener(v -> {
setSelectionState(4, selection_state[4] = !selection_state[4]);
loadReminderList();
});
binding.fri.setOnClickListener(v -> {
setSelectionState(5, selection_state[5] = !selection_state[5]);
loadReminderList();
});
binding.sat.setOnClickListener(v -> {
setSelectionState(6, selection_state[6] = !selection_state[6]);
loadReminderList();
});
// add button
binding.addReminder.setOnClickListener(v ->
Navigation.findNavController(v).navigate(R.id.action_reminderFragment_to_addReminderFragment)
);
binding.done.setOnClickListener(v -> {
Navigation.findNavController(v).popBackStack();
ProfileProgress.PROFILE_PROGRESS[0] = true;
});
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());
binding.editBtn.setOnClickListener(v -> {
Bundle bundle = new Bundle();
Reminder reminder = new Reminder("Vitamin D3", "05:00 PM", "5 Capsules");
bundle.putSerializable(REMINDER_KEY, reminder);
Navigation.findNavController(binding.getRoot())
.navigate(R.id.action_reminderFragment_to_addReminderFragment, bundle);
});
}
private void loadReminderList(){
binding.noData.setVisibility(View.GONE);
binding.remindersRv.setVisibility(View.VISIBLE);
reminderViewModel.getReminderAdapter().submitList(reminderViewModel.getRemindersList());
// static
binding.done.setVisibility(View.VISIBLE);
}
private void initViews(Bundle savedInstanceState) {
if (savedInstanceState != null){
selection_state = savedInstanceState.getBooleanArray(SELECTION_STATE_KEY);
for (int i = 0; i < selection_state.length; i++) {
setSelectionState(i, selection_state[i]);
}
}else{
selection_state = new boolean[7];
}
reminderViewModel = new ViewModelProvider(this).get(ReminderViewModel.class);
binding.remindersRv.setLayoutManager(new LinearLayoutManager(requireContext()));
binding.remindersRv.setAdapter(reminderViewModel.getReminderAdapter());
recyclerTouchListener = new RecyclerTouchListener(requireActivity(), binding.remindersRv);
recyclerTouchListener.setSwipeOptionViews(R.id.reminder_edit, R.id.reminder_delete)
.setSwipeable(R.id.rowFG, R.id.rowBG, this);
binding.remindersRv.addOnItemTouchListener(recyclerTouchListener);
}
private void setSelectionState(int position, boolean selection){
if (selection){
switch (position){
case 0:
// sun
binding.sun.setBackgroundResource(R.drawable.seleted_item_primary);
binding.sunT1.setTextColor(getResources().getColor(R.color.white_bg));
binding.sunT2.setTextColor(getResources().getColor(R.color.white_bg));
break;
case 1:
// mon
binding.mon.setBackgroundResource(R.drawable.seleted_item_primary);
binding.monT1.setTextColor(getResources().getColor(R.color.white_bg));
binding.monT2.setTextColor(getResources().getColor(R.color.white_bg));
break;
case 2:
// tue
binding.tue.setBackgroundResource(R.drawable.seleted_item_primary);
binding.tue1.setTextColor(getResources().getColor(R.color.white_bg));
binding.tue2.setTextColor(getResources().getColor(R.color.white_bg));
break;
case 3:
// wed
binding.wed.setBackgroundResource(R.drawable.seleted_item_primary);
binding.wed1.setTextColor(getResources().getColor(R.color.white_bg));
binding.wed2.setTextColor(getResources().getColor(R.color.white_bg));
break;
case 4:
// thu
binding.thu.setBackgroundResource(R.drawable.seleted_item_primary);
binding.thu1.setTextColor(getResources().getColor(R.color.white_bg));
binding.thu2.setTextColor(getResources().getColor(R.color.white_bg));
break;
case 5:
// fri
binding.fri.setBackgroundResource(R.drawable.seleted_item_primary);
binding.fri1.setTextColor(getResources().getColor(R.color.white_bg));
binding.fri2.setTextColor(getResources().getColor(R.color.white_bg));
break;
case 6:
// sat
binding.sat.setBackgroundResource(R.drawable.seleted_item_primary);
binding.sat1.setTextColor(getResources().getColor(R.color.white_bg));
binding.sat2.setTextColor(getResources().getColor(R.color.white_bg));
break;
}
}else{
switch (position){
case 0:
// sun
binding.sun.setBackgroundColor(getResources().getColor(R.color.white_bg));
binding.sunT1.setTextColor(getResources().getColor(R.color.black));
binding.sunT2.setTextColor(getResources().getColor(R.color.black));
break;
case 1:
// mon
binding.mon.setBackgroundColor(getResources().getColor(R.color.white_bg));
binding.monT1.setTextColor(getResources().getColor(R.color.black));
binding.monT2.setTextColor(getResources().getColor(R.color.black));
break;
case 2:
// tue
binding.tue.setBackgroundColor(getResources().getColor(R.color.white_bg));
binding.tue1.setTextColor(getResources().getColor(R.color.black));
binding.tue2.setTextColor(getResources().getColor(R.color.black));
break;
case 3:
// wed
binding.wed.setBackgroundColor(getResources().getColor(R.color.white_bg));
binding.wed1.setTextColor(getResources().getColor(R.color.black));
binding.wed2.setTextColor(getResources().getColor(R.color.black));
break;
case 4:
// thu
binding.thu.setBackgroundColor(getResources().getColor(R.color.white_bg));
binding.thu1.setTextColor(getResources().getColor(R.color.black));
binding.thu2.setTextColor(getResources().getColor(R.color.black));
break;
case 5:
// fri
binding.fri.setBackgroundColor(getResources().getColor(R.color.white_bg));
binding.fri1.setTextColor(getResources().getColor(R.color.black));
binding.fri2.setTextColor(getResources().getColor(R.color.black));
break;
case 6:
// sat
binding.sat.setBackgroundColor(getResources().getColor(R.color.white_bg));
binding.sat1.setTextColor(getResources().getColor(R.color.black));
binding.sat2.setTextColor(getResources().getColor(R.color.black));
break;
}
}
}
// swipe option menu click listener for reminder list
@Override
public void onSwipeOptionClicked(int viewID, int position) {
if (viewID == R.id.reminder_delete){
AppUtil.showSOSDecision(requireContext(),
getString(R.string.delete_med_reminder),
getString(R.string.yes), getString(R.string.no),
v -> {
// yes button clicked
Toast.makeText(requireContext(), "Delete " + position, Toast.LENGTH_SHORT).show();
}, v -> {
// no button clicked
});
}else if (viewID == R.id.reminder_edit){
Bundle bundle = new Bundle();
Reminder reminder = reminderViewModel.getRemindersList().get(position);
bundle.putSerializable(REMINDER_KEY, reminder);
Navigation.findNavController(binding.getRoot())
.navigate(R.id.action_reminderFragment_to_addReminderFragment, bundle);
}
}
}

View File

@@ -0,0 +1,30 @@
package com.ssb.simplitend.medreminder.mvvm;
import java.io.Serializable;
import java.util.Objects;
public class Reminder implements Serializable {
public String dosage_name, time, quantity;
public Reminder(){}
public Reminder(String dosage_name, String time, String quantity) {
this.dosage_name = dosage_name;
this.time = time;
this.quantity = quantity;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Reminder reminder = (Reminder) o;
return Objects.equals(dosage_name, reminder.dosage_name) && Objects.equals(time, reminder.time) && Objects.equals(quantity, reminder.quantity);
}
@Override
public int hashCode() {
return Objects.hash(dosage_name, time, quantity);
}
}

View File

@@ -0,0 +1,91 @@
package com.ssb.simplitend.medreminder.mvvm;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;
import com.ssb.simplitend.R;
import com.ssb.simplitend.databinding.ReminderViewholderBinding;
public class ReminderAdapter extends ListAdapter<Reminder, ReminderAdapter.ReminderViewHolder> {
private static final DiffUtil.ItemCallback<Reminder> DIFF_CALLBACK = new DiffUtil.ItemCallback<Reminder>() {
@Override
public boolean areItemsTheSame(@NonNull Reminder oldItem, @NonNull Reminder newItem) {
return oldItem.equals(newItem);
}
@Override
public boolean areContentsTheSame(@NonNull Reminder oldItem, @NonNull Reminder newItem) {
return oldItem.equals(newItem);
}
};
// static thing for selection status
public final boolean[] selection_state;
public ReminderAdapter(){
super(DIFF_CALLBACK);
this.selection_state = new boolean[2];
}
@NonNull
@Override
public ReminderViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ReminderViewholderBinding binding = ReminderViewholderBinding.inflate(LayoutInflater.from(parent.getContext()));
return new ReminderViewHolder(binding, selection_state);
}
@Override
public void onBindViewHolder(@NonNull ReminderViewHolder holder, int position) {
holder.setReminder(getItem(position), position);
}
public static class ReminderViewHolder extends RecyclerView.ViewHolder{
public ReminderViewholderBinding binding;
private final boolean[] selection_state;
public ReminderViewHolder(ReminderViewholderBinding binding, boolean[] selection_state){
super(binding.getRoot());
this.binding = binding;
this.selection_state = selection_state;
}
public void setReminder(Reminder reminder, int position){
binding.medName.setText(reminder.dosage_name);
binding.time.setText(reminder.time);
binding.quantity.setText(reminder.quantity);
// static image
if (position == 0){
binding.medImg.setImageResource(R.drawable.img_med_type_1);
}else{
binding.medImg.setImageResource(R.drawable.img_med_type_2);
}
binding.done.setOnClickListener(v -> {
if (selection_state[position]){
// item selected. un-selecting now
binding.sideBar.setBackgroundTintList(null);
binding.card.setCardBackgroundColor(AppCompatResources.getColorStateList(itemView.getContext(), R.color.white_bg));
binding.done.setImageResource(R.drawable.ic_done_accent);
}else{
// item un-selected. selecting now
binding.sideBar.setBackgroundTintList(AppCompatResources.getColorStateList(itemView.getContext(), R.color.color_primary));
binding.card.setCardBackgroundColor(AppCompatResources.getColorStateList(itemView.getContext(), R.color.color_accent));
binding.done.setImageResource(R.drawable.ic_done_accent_2);
}
selection_state[position] = !selection_state[position];
});
}
}
}

View File

@@ -0,0 +1,34 @@
package com.ssb.simplitend.medreminder.mvvm;
import androidx.lifecycle.ViewModel;
import java.util.ArrayList;
public class ReminderViewModel extends ViewModel {
private final ArrayList<Reminder> remindersList;
// reminder list adapter
private final ReminderAdapter reminderAdapter;
public ReminderViewModel(){
// fetch reminder list
reminderAdapter = new ReminderAdapter();
// static for now
// TODO: 06-07-2023
remindersList = new ArrayList<>();
remindersList.add(new Reminder("Vitamin D3", "02:00 pm", "2 capsules"));
remindersList.add(new Reminder("Sinupret", "09:00 pm", "1 capsules"));
}
public ArrayList<Reminder> getRemindersList() {
return remindersList;
}
public ReminderAdapter getReminderAdapter() {
return reminderAdapter;
}
}

View File

@@ -8,7 +8,9 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import com.ssb.simplitend.R;
import com.ssb.simplitend.databinding.ProfileProgressFragmentBinding;
public class ProfileProgressFragment extends Fragment {
@@ -25,6 +27,25 @@ public class ProfileProgressFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = ProfileProgressFragmentBinding.inflate(inflater, container, false);
initProgress();
clickEvents();
return binding.getRoot();
}
private void initProgress() {
}
private void clickEvents() {
binding.medicReminder.setOnClickListener(v ->
Navigation.findNavController(v).navigate(R.id.action_profileProgressFragment_to_reminderFragment)
);
binding.medicInfo.setOnClickListener(v ->
Navigation.findNavController(v).navigate(R.id.action_profileProgressFragment_to_medicalInfoFragment)
);
}
}

View File

@@ -1,6 +1,7 @@
package com.ssb.simplitend.welcome.activities;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import android.os.Bundle;

View File

@@ -1,6 +1,7 @@
package com.ssb.simplitend.welcome.fragments;
import android.os.Bundle;
import android.text.InputType;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -27,11 +28,16 @@ public class SignInFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = SignInFragmentBinding.inflate(inflater, container, false);
initViews();
clickEvents();
return binding.getRoot();
}
private void initViews() {
}
private void clickEvents() {
binding.forgotPin.setOnClickListener(v ->

View File

@@ -4,6 +4,7 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

View File

@@ -9,15 +9,24 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.GridLayoutManager;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.ssb.simplitend.R;
import com.ssb.simplitend.databinding.AddContactFragmentBinding;
import com.ssb.simplitend.databinding.DoneBottomsheetBinding;
import com.ssb.simplitend.welcome.fragments.contacts.mvvm.AddContactAdapter;
import com.ssb.simplitend.welcome.fragments.contacts.mvvm.Contact;
import java.util.ArrayList;
public class AddContactFragment extends Fragment {
// view binding
protected AddContactFragmentBinding binding;
protected AddContactAdapter contactAdapter;
public AddContactFragment(){
// required empty const.
}
@@ -26,25 +35,67 @@ public class AddContactFragment extends Fragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = AddContactFragmentBinding.inflate(inflater, container, false);
initViews();
clickEvents();
return binding.getRoot();
}
private void initViews() {
binding.contactRv.setLayoutManager(new GridLayoutManager(requireContext(), 2));
contactAdapter = new AddContactAdapter();
binding.contactRv.setAdapter(contactAdapter);
loadContacts();
}
private void loadContacts() {
// static data
ArrayList<Contact> contacts = new ArrayList<>();
// adding 10 contacts
contacts.add(new Contact("Akansha Surve", "phone number"));
contacts.add(new Contact("Akansha Surve", "phone number"));
contacts.add(new Contact("Akansha Surve", "phone number"));
contacts.add(new Contact("Akansha Surve", "phone number"));
contacts.add(new Contact("Akansha Surve", "phone number"));
contacts.add(new Contact("Akansha Surve", "phone number"));
contacts.add(new Contact("Akansha Surve", "phone number"));
contacts.add(new Contact("Akansha Surve", "phone number"));
contacts.add(new Contact("Akansha Surve", "phone number"));
contacts.add(new Contact("Akansha Surve", "phone number"));
contactAdapter.submitList(contacts);
}
private void clickEvents() {
binding.static1.setOnClickListener(v ->
Navigation.findNavController(v).navigate(R.id.action_addContactFragment_to_contactInfoFragment)
);
binding.static2.setOnClickListener(v ->
Navigation.findNavController(v).navigate(R.id.action_addContactFragment_to_contactListFragment)
);
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());
binding.nextBtn.setOnClickListener(v ->
Navigation.findNavController(v).navigate(R.id.action_addContactFragment_to_profileProgressFragment)
);
Navigation.findNavController(v).navigate(R.id.action_addContactFragment_to_profileProgressFragment));
}
private void showEmailSentAnim() {
DoneBottomsheetBinding binding = DoneBottomsheetBinding.inflate(getLayoutInflater());
BottomSheetDialog bsd = new BottomSheetDialog(requireContext(), R.style.BottomSheetDialog);
bsd.setContentView(binding.getRoot());
// TODO: 05-07-2023 animation part
binding.text.setText(getString(R.string.email_sent_to_caregiver));
binding.subText.setVisibility(View.VISIBLE);
binding.subText.setText(getString(R.string.continue_and_complete_profile));
bsd.show();
}
}

View File

@@ -8,6 +8,7 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import com.ssb.simplitend.databinding.ContactInfoFragmentBinding;
@@ -25,6 +26,14 @@ public class ContactInfoFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = ContactInfoFragmentBinding.inflate(inflater, container, false);
clickEvents();
return binding.getRoot();
}
private void clickEvents() {
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());
}
}

View File

@@ -4,8 +4,12 @@ import static com.ssb.simplitend.welcome.fragments.contacts.CreateContactFragmen
import static com.ssb.simplitend.welcome.fragments.contacts.CreateContactFragment.TO_EDIT_KEY;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -41,10 +45,18 @@ public class ContactListFragment extends Fragment {
protected ActivityResultLauncher<String> permissionLauncher;
private ArrayList<Contact> contactList;
public ContactListFragment() {
// required empty const.
}
@Override
public void onStart() {
super.onStart();
loadContacts();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@@ -63,9 +75,10 @@ public class ContactListFragment extends Fragment {
binding.createContact.setOnClickListener(v ->
{
Bundle arguments = new Bundle();
arguments.putBoolean(TO_EDIT_KEY, false);
Navigation.findNavController(v).navigate(R.id.action_contactListFragment_to_createContactFragment, arguments);
// insert contact intent
Intent intent = new Intent(Intent.ACTION_INSERT);
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
startActivity(intent);
}
);
@@ -78,6 +91,55 @@ public class ContactListFragment extends Fragment {
}
);
binding.search.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
filterContactList(s.toString().trim().toLowerCase());
}
});
}
// filters contact list w.r.t searchInput
private void filterContactList(String searchInput) {
if(searchInput.isEmpty()) {
contactListAdapter.submitList(contactList);
return;
}
ArrayList<Contact> filteredList = new ArrayList<>();
for (Contact contact: contactList){
if (contact.name != null && contact.name.trim().toLowerCase().contains(searchInput)){
filteredList.add(contact);
}else if (contact.phoneNumber != null && contact.phoneNumber.trim().contains(searchInput)){
filteredList.add(contact);
}else if (contact.email != null && contact.email.trim().toLowerCase().contains(searchInput)){
filteredList.add(contact);
}else if (contact.relationship != null && contact.relationship.trim().toLowerCase().contains(searchInput)){
filteredList.add(contact);
}
}
if (filteredList.isEmpty()) {
Toast.makeText(requireContext(), "No match found", Toast.LENGTH_SHORT).show();
}
contactListAdapter.submitList(filteredList);
binding.contactRv.smoothScrollToPosition(0);
}
private void initializeViews() {
@@ -98,8 +160,6 @@ public class ContactListFragment extends Fragment {
}
);
loadContacts();
}
/*
@@ -114,6 +174,14 @@ public class ContactListFragment extends Fragment {
contactViewModel = new ViewModelProvider(this).get(ContactViewModel.class);
Log.d(TAG, "initializeViews: viewmodel " + contactViewModel);
contactListAdapter.submitList(contactViewModel.getContactList());
contactList = null;
contactList = contactViewModel.getContactList(requireContext());
if (binding.search.getText().toString().trim().isEmpty())
contactListAdapter.submitList(contactList);
else
filterContactList(binding.search.getText().toString().trim().toLowerCase());
binding.contactRv.smoothScrollToPosition(0);
}
}

View File

@@ -1,27 +1,21 @@
package com.ssb.simplitend.welcome.fragments.contacts;
import android.animation.Animator;
import android.graphics.drawable.Drawable;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import androidx.vectordrawable.graphics.drawable.Animatable2Compat;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.ssb.simplitend.R;
import com.ssb.simplitend.databinding.CreateEditContactFragmentBinding;
@@ -29,7 +23,19 @@ import com.ssb.simplitend.databinding.DecisionBottomsheetBinding;
import com.ssb.simplitend.databinding.DoneBottomsheetBinding;
import com.ssb.simplitend.welcome.fragments.contacts.mvvm.Contact;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class CreateContactFragment extends Fragment {
// log tag
private static final String TAG = "CreateContactFragment";
// view binding
protected CreateEditContactFragmentBinding binding;
@@ -41,6 +47,9 @@ public class CreateContactFragment extends Fragment {
// flag if current instance is to edit or create contact
boolean to_edit;
// image selector launcher
private ActivityResultLauncher<String> imageSelector;
public CreateContactFragment() {
// required empty const.
}
@@ -59,6 +68,8 @@ public class CreateContactFragment extends Fragment {
private void clickEvents() {
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());
binding.nextBtn.setOnClickListener(v -> {
if (to_edit){
@@ -66,11 +77,13 @@ public class CreateContactFragment extends Fragment {
showSaveEditDecision();
}else {
// saving new contact
gotoAddContactFragment();
Navigation.findNavController(v).popBackStack();
}
});
binding.image.setOnClickListener(v -> imageSelector.launch("image/*"));
}
private void showSaveEditDecision() {
@@ -105,35 +118,25 @@ public class CreateContactFragment extends Fragment {
binding.text.setText(getString(R.string.changes_successful));
binding.anim.addAnimatorListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(@NonNull Animator animation) {
}
@Override
public void onAnimationEnd(@NonNull Animator animation) {
bsd.dismiss();
gotoAddContactFragment();
}
@Override
public void onAnimationCancel(@NonNull Animator animation) {
}
@Override
public void onAnimationRepeat(@NonNull Animator animation) {
}
});
Glide.with(requireContext())
.asGif()
.load(R.raw.done_anim_primary)
.into(binding.doneAnim);
bsd.show();
gotoAddContactFragment(3000, bsd);
}
private void gotoAddContactFragment(){
Navigation.findNavController(binding.getRoot())
.navigate(R.id.action_createContactFragment_to_addContactFragment);
private void gotoAddContactFragment(long inMsm, BottomSheetDialog bsd){
new Handler().postDelayed(() -> {
if (bsd != null) bsd.dismiss();
Navigation.findNavController(binding.getRoot())
.navigate(R.id.action_createContactFragment_to_addContactFragment);
}, inMsm);
}
private void showSOSDecision() {
@@ -142,6 +145,7 @@ public class CreateContactFragment extends Fragment {
BottomSheetDialog bsd = new BottomSheetDialog(requireContext(), R.style.BottomSheetDialog);
bsd.setContentView(binding.getRoot());
bsd.setCancelable(false);
binding.text.setText(getString(R.string.make_sos));
@@ -186,6 +190,81 @@ public class CreateContactFragment extends Fragment {
}
});
loadCountryCodeDropDown();
// image selector launcher
imageSelector = registerForActivityResult(new ActivityResultContracts.GetContent(),
uri -> {
if (uri != null){
binding.image.setImageURI(null);
binding.image.setImageURI(uri);
}
});
}
private void loadCountryCodeDropDown() {
ArrayList<String> countryCodeList = new ArrayList<>();
try {
String countryCodeStr = readCountryCodes(requireContext());
JSONArray jsonArray = new JSONArray(countryCodeStr);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject code = jsonArray.getJSONObject(i);
countryCodeList.add(code.getString("dial_code"));
}
} catch (Exception e) {
// if cannot load all country codes showing only india's dial code
countryCodeList.add("+91");
Log.e(TAG, "loadCountryCodeDropDown: ", e);
}
binding.countryCodes.setLifecycleOwner(this);
binding.countryCodes.setItems(countryCodeList);
binding.countryCodes.selectItemByIndex(countryCodeList.indexOf("+91"));
binding.countryCodes.setDismissWhenNotifiedItemSelected(true);
binding.countryCodes.setIsFocusable(true);
}
public String readCountryCodes(Context context) throws IOException {
StringBuilder returnString = new StringBuilder();
InputStream fIn = context.getResources().openRawResource(R.raw.country_code);
InputStreamReader isr = new InputStreamReader(fIn);
BufferedReader input = new BufferedReader(isr);
String line = "";
while ((line = input.readLine()) != null) {
returnString.append(line);
}
try {
isr.close();
if (fIn != null) fIn.close();
input.close();
} catch (Exception e) {
Log.e(TAG, "readCountryCodes: ", e);
}
return returnString.toString();
}
private void setDetails(Contact contact) {

View File

@@ -0,0 +1,103 @@
package com.ssb.simplitend.welcome.fragments.contacts.mvvm;
import static com.ssb.simplitend.welcome.fragments.contacts.CreateContactFragment.CONTACT_KEY;
import static com.ssb.simplitend.welcome.fragments.contacts.CreateContactFragment.TO_EDIT_KEY;
import android.app.AlertDialog;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;
import com.ssb.simplitend.R;
import com.ssb.simplitend.databinding.AddContactViewholderBinding;
public class AddContactAdapter extends ListAdapter<Contact, AddContactAdapter.ContactViewHolder> {
private static final DiffUtil.ItemCallback<Contact> DIFF_UTIL = new DiffUtil.ItemCallback<Contact>() {
@Override
public boolean areItemsTheSame(@NonNull Contact oldItem, @NonNull Contact newItem) {
return oldItem.name.equals(newItem.name);
}
@Override
public boolean areContentsTheSame(@NonNull Contact oldItem, @NonNull Contact newItem) {
return oldItem.equals(newItem);
}
};
public AddContactAdapter() {
super(DIFF_UTIL);
}
@NonNull
@Override
public ContactViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
AddContactViewholderBinding binding = AddContactViewholderBinding.inflate(LayoutInflater.from(parent.getContext()));
return new ContactViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull ContactViewHolder holder, int position) {
holder.setData(getItem(position), position);
}
public static class ContactViewHolder extends RecyclerView.ViewHolder {
public AddContactViewholderBinding binding;
private AlertDialog contactDialog;
public ContactViewHolder(AddContactViewholderBinding binding) {
super(binding.getRoot());
this.binding = binding;
this.contactDialog = new AlertDialog.Builder(itemView.getContext())
.setTitle("Add contact")
.setMessage("Select an option to add contact")
.setPositiveButton("Add manually", ((dialog1, which) -> {
// navigating to add contact fragment
Bundle bundle = new Bundle();
bundle.putBoolean(TO_EDIT_KEY, false);
Navigation.findNavController(binding.getRoot()).navigate(R.id.action_addContactFragment_to_createContactFragment, bundle);
}))
.setNegativeButton("Select contact", ((dialog1, which) -> {
Navigation.findNavController(binding.getRoot()).navigate(R.id.action_addContactFragment_to_contactListFragment);
}))
.create();
}
public void setData(Contact contact, int position) {
if (position == 0) {
binding.sos.setVisibility(View.VISIBLE);
binding.card.setCardBackgroundColor(Color.WHITE);
binding.name.setText("Akansha Surve");
binding.imag.setImageResource(R.drawable.contact_img_static);
binding.card.setOnClickListener(v -> {
Navigation.findNavController(v).navigate(R.id.action_addContactFragment_to_contactInfoFragment);
});
} else {
binding.name.setText("Add contact");
binding.card.setOnClickListener(v -> {
contactDialog.show();
});
}
}
}
}

View File

@@ -4,23 +4,20 @@ import android.app.Application;
import android.content.Context;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.ViewModel;
import java.util.ArrayList;
public class ContactViewModel extends AndroidViewModel {
private final ArrayList<Contact> contactList;
private final UserContactRepository contactRepository;
public ContactViewModel(Application application){
super(application);
this.contactRepository = new UserContactRepository();
this.contactList = this.contactRepository.getContactList(application.getApplicationContext());
}
public ArrayList<Contact> getContactList() {
return contactList;
public ArrayList<Contact> getContactList(Context context) {
return this.contactRepository.getContactList(context.getApplicationContext());
}
public UserContactRepository getContactRepository() {

View File

@@ -2,13 +2,19 @@ package com.ssb.simplitend.welcome.fragments.contacts.mvvm;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.ssb.simplitend.welcome.fragments.contacts.mvvm.Contact;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
public class UserContactRepository {
@@ -16,7 +22,8 @@ public class UserContactRepository {
private static final String[] PROJECTION = new String[]{
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.PHOTO_URI
};
public UserContactRepository(){}

View File

@@ -12,6 +12,7 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import com.bumptech.glide.Glide;
import com.ssb.simplitend.R;
import com.ssb.simplitend.apputils.AppUtil;
import com.ssb.simplitend.databinding.CheckMailFragmentBinding;
@@ -39,6 +40,13 @@ public class CheckMailFragment extends Fragment {
private void initViews() {
// showing gif
Glide.with(binding.image)
.asGif()
.load(R.raw.email_sending_anim)
.placeholder(R.drawable.forgot_pin_email_img)
.into(binding.image);
initOTPBoxes();
}

View File

@@ -10,6 +10,7 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import com.bumptech.glide.Glide;
import com.ssb.simplitend.R;
import com.ssb.simplitend.databinding.ForgotPinFragmentBinding;
@@ -26,11 +27,22 @@ public class ForgotPinFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = ForgotPinFragmentBinding.inflate(inflater, container, false);
initViews();
clickEvents();
return binding.getRoot();
}
private void initViews() {
// showing gif
Glide.with(binding.image)
.asGif()
.load(R.raw.email_sending_anim)
.placeholder(R.drawable.forgot_pin_email_img)
.into(binding.image);
}
private void clickEvents() {
binding.backBtn.setOnClickListener(v ->

View File

@@ -1,6 +1,8 @@
package com.ssb.simplitend.welcome.fragments.register;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -10,14 +12,34 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import com.skydoves.powerspinner.OnSpinnerItemSelectedListener;
import com.ssb.simplitend.R;
import com.ssb.simplitend.databinding.LocationFragmentBinding;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
public class LocationFragment extends Fragment {
private static final String TAG = "LocationFragment";
// view binding
protected LocationFragmentBinding binding;
// country list
ArrayList<String> countryList;
// Map for country and their states
HashMap<String, ArrayList<String>> country_N_states_map;
public LocationFragment(){
// required empty const.
}
@@ -27,11 +49,113 @@ public class LocationFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = LocationFragmentBinding.inflate(inflater, container, false);
initViews();
clickEvents();
return binding.getRoot();
}
private void initViews() {
loadCountriesAndStates();
}
// loads all countries and their states into the spinners
private void loadCountriesAndStates() {
countryList = new ArrayList<>();
country_N_states_map = new HashMap<>();
try {
String country_n_states_str = readCountryNStates(requireContext());
JSONArray country_n_states = new JSONObject(country_n_states_str).getJSONArray("countries");
Log.d(TAG, "loadCountriesAndStates: " + country_n_states);
for (int i = 0; i < country_n_states.length(); i++) {
String country = country_n_states.getJSONObject(i).getString("country");
countryList.add(country);
JSONArray states = country_n_states.getJSONObject(i).getJSONArray("states");
ArrayList<String> stateList = new ArrayList<>();
for (int j = 0; j < states.length(); j++) {
stateList.add(states.getString(j));
}
country_N_states_map.put(country, stateList);
}
} catch (Exception e) {
Log.e(TAG, "load country and states: ", e);
}
Log.d(TAG, "loadCountriesAndStates: " + countryList);
binding.stateSpinner.setLifecycleOwner(this);
binding.countrySpinner.setLifecycleOwner(this);
binding.countrySpinner.setItems(countryList);
binding.stateSpinner.setDismissWhenNotifiedItemSelected(true);
binding.countrySpinner.setDismissWhenNotifiedItemSelected(true);
binding.stateSpinner.setIsFocusable(true);
binding.countrySpinner.setIsFocusable(true);
binding.countrySpinner.setOnSpinnerItemSelectedListener((OnSpinnerItemSelectedListener<String>) (i, s, i1, t1) -> {
ArrayList<String> stateList;
if (country_N_states_map.containsKey(t1) && country_N_states_map.get(t1) != null){
stateList = country_N_states_map.get(t1);
}else{
stateList = new ArrayList<>();
}
if (stateList != null) {
binding.stateSpinner.setItems(stateList);
binding.stateSpinner.clearSelectedItem();
}
});
}
public String readCountryNStates(Context context) throws IOException {
StringBuilder returnString = new StringBuilder();
InputStream fIn = context.getResources().openRawResource(R.raw.country_n_states);
InputStreamReader isr = new InputStreamReader(fIn);
BufferedReader input = new BufferedReader(isr);
String line = "";
while ((line = input.readLine()) != null) {
returnString.append(line);
}
try {
isr.close();
if (fIn != null) fIn.close();
input.close();
} catch (Exception e) {
Log.e(TAG, "readCountryNStates: ", e);
}
return returnString.toString();
}
private void clickEvents() {
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());

View File

@@ -1,23 +1,44 @@
package com.ssb.simplitend.welcome.fragments.register;
import android.app.DatePickerDialog;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import com.skydoves.powerspinner.OnSpinnerDismissListener;
import com.ssb.simplitend.R;
import com.ssb.simplitend.apputils.AppUtil;
import com.ssb.simplitend.databinding.RegisterFragmentBinding;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;
public class RegisterFragment extends Fragment {
private static final String TAG = "RegisterFragment";
protected RegisterFragmentBinding binding;
public RegisterFragment(){
public RegisterFragment() {
// required empty const.
}
@@ -26,11 +47,19 @@ public class RegisterFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = RegisterFragmentBinding.inflate(inflater, container, false);
initViews();
clickEvents();
return binding.getRoot();
}
private void initViews() {
loadCountryCodeDropDown();
}
private void clickEvents() {
binding.backBtn.setOnClickListener(v -> Navigation.findNavController(v).popBackStack());
@@ -38,5 +67,102 @@ public class RegisterFragment extends Fragment {
binding.nextBtn.setOnClickListener(v ->
Navigation.findNavController(v).navigate(R.id.action_registerFragment_to_locationFragment));
binding.dob.setOnClickListener(v -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
AppUtil.closeKeyboard(requireActivity());
pickDate();
}
});
}
private void loadCountryCodeDropDown() {
ArrayList<String> countryCodeList = new ArrayList<>();
try {
String countryCodeStr = readCountryCodes(requireContext());
JSONArray jsonArray = new JSONArray(countryCodeStr);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject code = jsonArray.getJSONObject(i);
countryCodeList.add(code.getString("dial_code"));
}
} catch (Exception e) {
// if cannot load all country codes showing only india's dial code
countryCodeList.add("+91");
Log.e(TAG, "loadCountryCodeDropDown: ", e);
}
binding.countryCodes.setLifecycleOwner(this);
binding.countryCodes.setItems(countryCodeList);
binding.countryCodes.selectItemByIndex(countryCodeList.indexOf("+91"));
binding.countryCodes.setDismissWhenNotifiedItemSelected(true);
binding.countryCodes.setIsFocusable(true);
}
public String readCountryCodes(Context context) throws IOException {
StringBuilder returnString = new StringBuilder();
InputStream fIn = context.getResources().openRawResource(R.raw.country_code);
InputStreamReader isr = new InputStreamReader(fIn);
BufferedReader input = new BufferedReader(isr);
String line = "";
while ((line = input.readLine()) != null) {
returnString.append(line);
}
try {
isr.close();
if (fIn != null) fIn.close();
input.close();
} catch (Exception e) {
Log.e(TAG, "readCountryCodes: ", e);
}
return returnString.toString();
}
@RequiresApi(api = Build.VERSION_CODES.N)
private void pickDate() {
DatePickerDialog datePickerDialog = new DatePickerDialog(requireContext());
datePickerDialog.setOnDateSetListener((view, year, month, dayOfMonth) -> {
setDOB(year, month, dayOfMonth);
});
datePickerDialog.show();
}
private void setDOB(int year, int month, int dayOfMonth) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);
SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy", Locale.getDefault());
String selected_time = sdf.format(cal.getTime());
binding.dob.setText(selected_time);
}
}

View File

@@ -0,0 +1,35 @@
package com.ssb.simplitend.welcome.fragments.register;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import com.ssb.simplitend.R;
import com.ssb.simplitend.databinding.SplashFragmentBinding;
public class SplashFragment extends Fragment {
// view binding
protected SplashFragmentBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = SplashFragmentBinding.inflate(inflater, container, false);
new Handler().postDelayed(() -> {
Navigation.findNavController(binding.mainIcon).navigate(R.id.action_splashFragment_to_welcomeFragment);
}, 1000);
return binding.getRoot();
}
}

View File

@@ -11,10 +11,7 @@ import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.squareup.picasso.Picasso;
import com.ssb.simplitend.R;
import com.ssb.simplitend.databinding.LocationFragmentBinding;
import com.ssb.simplitend.databinding.ThankYouFragmentBinding;
public class ThankYouFragment extends Fragment {
@@ -39,6 +36,11 @@ public class ThankYouFragment extends Fragment {
}
private void initializeViews(Bundle savedInstanceState) {
// showing anim
Glide.with(requireContext())
.asGif()
.load(R.raw.done_anim)
.into(binding.animIv);
}
private void clickEvents() {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_user_outline_bg"/>
<item android:drawable="@drawable/ic_calender_2_outline"
android:gravity="center"
/>
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_user_outline_bg"/>
<item android:drawable="@drawable/ic_freq_outline"
android:gravity="center"
/>
</layer-list>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_user_outline_bg"/>
<item android:drawable="@drawable/ic_instruction_outline"
android:gravity="center"
/>
</layer-list>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_user_outline_bg"/>
<item android:drawable="@drawable/ic_quantity_outline"
android:gravity="center"
/>
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1007 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Some files were not shown because too many files have changed in this diff Show More