.
123
.idea/codeStyles/Project.xml
generated
Normal 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
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
17
.idea/deploymentTargetDropDown.xml
generated
@@ -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
@@ -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>
|
||||
@@ -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'
|
||||
|
||||
BIN
app/src/debug/ic_launcher-playstore.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
17
app/src/debug/res/drawable/ic_launcher_foreground.xml
Normal 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>
|
||||
BIN
app/src/debug/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/debug/res/mipmap-hdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/debug/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/debug/res/mipmap-mdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/debug/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
app/src/debug/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
4
app/src/debug/res/values/ic_launcher_background.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#1B6DC1</color>
|
||||
</resources>
|
||||
@@ -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" />
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ssb.simplitend.medreminder;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public interface OnActivityTouchListener {
|
||||
void getTouchCoordinates(MotionEvent ev);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ssb.simplitend.welcome.activities;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
|
||||
@@ -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 ->
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
@@ -27,24 +36,66 @@ public class AddContactFragment extends Fragment {
|
||||
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();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,8 +23,20 @@ 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(){
|
||||
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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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(){}
|
||||
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
@@ -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 ->
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -1,20 +1,41 @@
|
||||
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() {
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 23 KiB |
BIN
app/src/main/res/drawable-hdpi/contact_img_static.png
Normal file
|
After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 13 KiB |
BIN
app/src/main/res/drawable-hdpi/forgot_pin_email_img.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
app/src/main/res/drawable-hdpi/ic_delete_2.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/drawable-hdpi/ic_edit_2.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
app/src/main/res/drawable-hdpi/img_allergies.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
app/src/main/res/drawable-hdpi/img_diagnosis.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
app/src/main/res/drawable-hdpi/img_diet_restriction.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
app/src/main/res/drawable-hdpi/img_doc_contact.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
app/src/main/res/drawable-hdpi/img_doctor.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
app/src/main/res/drawable-hdpi/img_hospital.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
app/src/main/res/drawable-hdpi/img_med_type_1.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
app/src/main/res/drawable-hdpi/img_med_type_2.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 10 KiB |
BIN
app/src/main/res/drawable-ldpi/contact_img_static.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
BIN
app/src/main/res/drawable-ldpi/forgot_pin_email_img.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
10
app/src/main/res/drawable-ldpi/ic_calender_2.xml
Normal 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>
|
||||
BIN
app/src/main/res/drawable-ldpi/ic_delete_2.png
Normal file
|
After Width: | Height: | Size: 824 B |
BIN
app/src/main/res/drawable-ldpi/ic_edit_2.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
10
app/src/main/res/drawable-ldpi/ic_freq.xml
Normal 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>
|
||||
10
app/src/main/res/drawable-ldpi/ic_instruction.xml
Normal 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>
|
||||
10
app/src/main/res/drawable-ldpi/ic_quantity.xml
Normal 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>
|
||||
BIN
app/src/main/res/drawable-ldpi/img_allergies.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
app/src/main/res/drawable-ldpi/img_diagnosis.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
app/src/main/res/drawable-ldpi/img_diet_restriction.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
app/src/main/res/drawable-ldpi/img_doc_contact.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
app/src/main/res/drawable-ldpi/img_doctor.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
app/src/main/res/drawable-ldpi/img_hospital.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/main/res/drawable-ldpi/img_med_type_1.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
app/src/main/res/drawable-ldpi/img_med_type_2.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 13 KiB |
BIN
app/src/main/res/drawable-mdpi/contact_img_static.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 7.4 KiB |
BIN
app/src/main/res/drawable-mdpi/forgot_pin_email_img.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
app/src/main/res/drawable-mdpi/ic_delete_2.png
Normal file
|
After Width: | Height: | Size: 1007 B |
BIN
app/src/main/res/drawable-mdpi/ic_edit_2.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/drawable-mdpi/img_allergies.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
app/src/main/res/drawable-mdpi/img_diagnosis.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
app/src/main/res/drawable-mdpi/img_diet_restriction.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
app/src/main/res/drawable-mdpi/img_doc_contact.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
app/src/main/res/drawable-mdpi/img_doctor.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
app/src/main/res/drawable-mdpi/img_hospital.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/main/res/drawable-mdpi/img_med_type_1.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
app/src/main/res/drawable-mdpi/img_med_type_2.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 12 KiB |
BIN
app/src/main/res/drawable-tvdpi/caregiver_img.png
Normal file
|
After Width: | Height: | Size: 20 KiB |