liufuhua007

2 version add patient view

Showing 28 changed files with 994 additions and 21 deletions
package com.sw.laryngoscope.FHIR.adapter;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.sw.laryngoscope.FHIR.model.PatientModel;
import java.util.ArrayList;
import java.util.HashMap;
public abstract class BaseAdapter<H extends BaseViewHolder> extends RecyclerView.Adapter<BaseViewHolder> {
private HashMap<String, PatientModel> patientsHashMap;
private ArrayList<PatientModel> uniquePatients = new ArrayList<>();
/**
* Constructor.
*/
BaseAdapter(HashMap<String, PatientModel> patientsHashMap) {
this.patientsHashMap = patientsHashMap;
}
/**
* Getter for PatientHashMap
* @return the patientHashMap
*/
HashMap<String, PatientModel> getPatientsHashMap() {
return patientsHashMap;
}
/**
* Setter for PatientHashMap
* @param patientsHashMap new PatientHashMap
*/
void setPatientsHashMap(HashMap<String, PatientModel> patientsHashMap) {
this.patientsHashMap = patientsHashMap;
}
/**
* Getter for uniquePatients
* @return uniquePatients
*/
ArrayList<PatientModel> getUniquePatients() {
return uniquePatients;
}
/**
* Setter for uniquePatients
* @param uniquePatients new uniquePatients list
*/
void setUniquePatients(ArrayList<PatientModel> uniquePatients) {
this.uniquePatients = uniquePatients;
}
/**
* onCreateViewHolder overrides it superclass's ( RecyclerView ) method
* subclass of this class must implement this method.
*/
@NonNull
@Override
public abstract BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType);
/**
* onBindViewHolder overrides it superclass's ( RecyclerView ) method
* subclass of this class must implement this method.
*/
@Override
public abstract void onBindViewHolder(@NonNull BaseViewHolder holder, int position);
/**
* onGetItemCount overrides it superclass's ( RecyclerView ) method
* subclass of this class must implement this method.
*/
@Override
public abstract int getItemCount();
}
package com.sw.laryngoscope.FHIR.adapter;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public abstract class BaseViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
/**
* Constructor.
* @param itemView
*/
BaseViewHolder(@NonNull View itemView) {
super(itemView);
}
/**
* On click method from View.OnClickListener interface
* Subclass that inherits from this class must implement this method.
*/
@Override
public abstract void onClick(View v);
}
package com.sw.laryngoscope.FHIR.adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.google.android.material.chip.Chip;
import com.sw.laryngoscope.R;
import com.sw.laryngoscope.FHIR.model.PatientModel;
import com.sw.laryngoscope.FHIR.model.observation.ObservationType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;
public class SelectPatientsAdapter extends BaseAdapter<SelectPatientsAdapter.SelectPatientViewHolder>{
// select patients adapter on pcl
private OnPatientClickListener onPatientClickListener;
private ArrayList<PatientModel> selectedPatients;
// A list to remember a patient's state
// ( true when patient is selected , otherwise false)
private ArrayList<Boolean> patientState = new ArrayList<>();
/**
* The SelectPatient Adapter constructor, this initialises the adapter that
* will be used to update the SelectPatient fragment UI.
*
* @param patientsHashMap list of patients that is under HealthPractitioner
* @param onPatientClickListener the listener that is listening to each patient's card clicks
* @param selectedPatients a list of selected patients
*/
public SelectPatientsAdapter(HashMap<String, PatientModel> patientsHashMap, OnPatientClickListener onPatientClickListener, ArrayList<PatientModel> selectedPatients) {
super(patientsHashMap);
this.selectedPatients = selectedPatients;
this.onPatientClickListener = onPatientClickListener;
ArrayList<PatientModel> uniquePatients = new ArrayList<>();
// loop through the patient hash map to get a list of unique patients
patientsHashMap.forEach((patientID, patientModel) -> {
if (patientModel != null) {
PatientModel selectedPatient = isSelectedPatient(patientModel);
if (selectedPatient != null) {
uniquePatients.add(selectedPatient);
patientState.add(true);
}
else {
uniquePatients.add(patientModel);
patientState.add(false);
}
}
});
setUniquePatients(uniquePatients);
}
/**
* This method checks if patient is already in the selected patient list.
* @param patient - the patient model object
* @return true - if patient is already in the selected patient list
* false - if patient is not in the selected patient list
*/
private PatientModel isSelectedPatient(PatientModel patient) {
for (PatientModel p: selectedPatients) {
if(p.getPatientID().equals(patient.getPatientID())) {
return p;
}
}
return null;
}
/**
* This method overrides its superclass's onCreateViewHolder method
* It is responsible for creating new card view holders that will be used to hold
* and display patient'name
* @return a ViewHolder Object
*/
@NonNull
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.select_patients_cardview, parent, false);
return new SelectPatientsAdapter.SelectPatientViewHolder(v, onPatientClickListener);
}
/**
* This method overrides its superclass's onBindViewHolder method
* This method is used to update the contents of the SelectPatientViewHolder to reflect the patient
* at the given position.
*
* This method also checks if patient is a selected patient and do the following:
* 1. if true -> highlight the patient's card view in green
* 2. else -> don't highlight the patient's card view
*
* @param baseHolder the reference to the holder that will be used to display the patient's name
* @param position the position of the adapter
*/
@Override
public void onBindViewHolder(@NonNull BaseViewHolder baseHolder, int position) {
SelectPatientViewHolder holder = (SelectPatientViewHolder) baseHolder;
holder.checkBox.setChecked(patientState.get(position));
holder.background.setBackgroundResource(R.drawable.cardv_nonselected_bg);
holder.patientName.setText(getUniquePatients().get(position).getName());
PatientModel patient = getUniquePatients().get(position);
if (isSelectedPatient(patient) != null){
holder.checkBox.setChecked(true);
holder.background.setBackgroundResource(R.drawable.cardv_selected_bg);
patientState.set(position,true);
onPatientClickListener.onPatientClick(holder.checkBox.isChecked(), getUniquePatients().get(position));
// set chip to be checked if selected for monitoring observation(s) previously
for (ObservationType type: ObservationType.values()) {
switch (type) {
case CHOLESTEROL:
if (Objects.requireNonNull(isSelectedPatient(patient)).isObservationMonitored(type)) {
holder.cholesterolChip.setChecked(true);
}
else {
holder.cholesterolChip.setChecked(false);
}
case BLOOD_PRESSURE:
if (Objects.requireNonNull(isSelectedPatient(patient)).isObservationMonitored(type)) {
holder.bloodPressureChip.setChecked(true);
}
else {
holder.bloodPressureChip.setChecked(false);
}
}
}
}
}
/**
* This method overrides its superclass's method,
* It gets the total number of patients that is under HeathPractitioner
* @return total number of patients
*/
@Override
public int getItemCount() {
return getUniquePatients().size();
}
/**
* The SelectPatientViewHolder class are objects that holds the reference to the individual
* card views that is reused to display different patient's data in the recycler view.
*
* This class implements View.OnClickListener interface.
*/
public class SelectPatientViewHolder extends BaseViewHolder {
private TextView patientName;
private CheckBox checkBox; //hidden checkbox
private SelectPatientsAdapter.OnPatientClickListener onPatientClickListener;
private ConstraintLayout background;
private Chip cholesterolChip;
private Chip bloodPressureChip;
/**
* The SelectPatientViewHolder constructor
* initialise SelectPatientViewHolder object that will be used to hold patient's data
* @param onPatientClickListener the listener that is listening to patient's card clicks
*/
SelectPatientViewHolder(@NonNull View itemView, OnPatientClickListener onPatientClickListener) {
super(itemView);
patientName = itemView.findViewById(R.id.all_patient_txt_name);
checkBox = itemView.findViewById(R.id.checkBox);
background = itemView.findViewById(R.id.card_backgroud);
cholesterolChip = itemView.findViewById(R.id.cholesterol_chip);
bloodPressureChip = itemView.findViewById(R.id.blood_pressure_chip);
this.onPatientClickListener = onPatientClickListener;
itemView.setOnClickListener(this);
cholesterolChip.setOnClickListener(this);
bloodPressureChip.setOnClickListener(this);
}
private void observationStatus(Chip chip, int position, ObservationType observationType) {
if (chip.isChecked()) {
getUniquePatients().get(position).monitorObservation(observationType, true);
background.setBackgroundResource(R.drawable.cardv_selected_bg);
checkBox.setChecked(true);
patientState.set(position,true);
}
else {
if (!cholesterolChip.isChecked() && !bloodPressureChip.isChecked()) {
patientState.set(position,false);
background.setBackgroundResource(R.drawable.cardv_nonselected_bg);
checkBox.setChecked(false);
}
getUniquePatients().get(position).monitorObservation(observationType, false);
}
}
/**
* This method is called when user clicks on a patient's card-view.
* It notifies its onClickListener (SelectPatientFragment) to add the patient into the
* selected patient list/ remove the patient form the selected patient list
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.cholesterol_chip:
observationStatus(cholesterolChip, getAdapterPosition(), ObservationType.CHOLESTEROL);
break;
case R.id.blood_pressure_chip:
observationStatus(bloodPressureChip, getAdapterPosition(), ObservationType.BLOOD_PRESSURE);
break;
}
onPatientClickListener.onPatientClick(checkBox.isChecked(), getUniquePatients().get(getAdapterPosition()));
}
}
/**
* Class the uses this interface must implement their own onPatientClick method.
* onPatientClick is handle the events that should happen when a patient's card-view is clicked.
*/
public interface OnPatientClickListener {
void onPatientClick(boolean checked, PatientModel patient);
}
}
package com.sw.laryngoscope.FHIR.fragment;
import android.content.Context;
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.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.sw.laryngoscope.R;
import com.sw.laryngoscope.FHIR.adapter.SelectPatientsAdapter;
import com.sw.laryngoscope.databinding.FgPatientFragmentBinding;
import com.sw.laryngoscope.FHIR.model.PatientModel;
import com.sw.laryngoscope.FHIR.viewModel.SharedViewModel;
import java.util.ArrayList;
import java.util.HashMap;
public class SelectPatientsFragment extends Fragment implements SelectPatientsAdapter.OnPatientClickListener{
private String practitionerID;
private SelectPatientsFragment thisFrag; // a reference to this fragment
// private Toolbar toolbar;
private SharedViewModel sharedViewModel;
// private RecyclerView recyclerView;
private ArrayList<PatientModel> selectedPatients = new ArrayList<>();
// private TextView title;
// private TextView loadingTextView;
// private ImageButton backButton;
// private ProgressBar loadingSpinner;
private FgPatientFragmentBinding binding;
/**
* Constructor
* @param practitionerID the Health Practitioner's ID
*/
public SelectPatientsFragment(String practitionerID) {
this.practitionerID = practitionerID;
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FgPatientFragmentBinding.inflate(inflater, container, false);
return binding.getRoot();
}
public void onViewCreatred(@NonNull View view,@Nullable Bundle savedInstanceState){
sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
// find all the graphical components
// recyclerView = root.findViewById(R.id.select_patients_recycler_view);
// backButton = root.findViewById(R.id.btn_back);
// toolbar = root.findViewById(R.id.select_patients_toolbar);
// title = toolbar.findViewById(R.id.toolbar_title);
// loadingTextView = root.findViewById(R.id.select_patients_txt_loading);
// loadingSpinner = root.findViewById(R.id.select_patients_progressBar);
binding.selectPatientsTxtLoading.setVisibility(View.VISIBLE);
binding.selectPatientsProgressBar.setVisibility(View.VISIBLE);
sharedViewModel.setPractitionerID(practitionerID);
setUpToolBar();
//update UI when there's new patient under Health Practitioner
sharedViewModel.getAllPatients().observe(getViewLifecycleOwner(),patientUpdatedObserver);
thisFrag = this;
}
/**
* This observer observes for changes in patient list
* ( The list that contains all patients under Health Practitioner )
* It displays a loading screen when the app is still fetching data from the server,
* It immediately updates the UI to display the patients when the system completes
* the data fetching process.
*/
private Observer<HashMap<String,PatientModel>> patientUpdatedObserver = new Observer<HashMap<String,PatientModel >>() {
@Override
public void onChanged( HashMap < String, PatientModel > patientHashMap) {
if (patientHashMap.size() == 0) {
binding.selectPatientsTxtLoading.setText(R.string.zero_patients_message);
}
else{
binding.selectPatientsProgressBar.setVisibility(View.GONE);
binding.selectPatientsTxtLoading.setVisibility(View.GONE);
binding.selectPatientsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
binding.selectPatientsRecyclerView.setAdapter( new SelectPatientsAdapter(patientHashMap,thisFrag, selectedPatients));
}
}
};
private void setUpToolBar() {
binding.selectPatientsToolbar.toolbarTitle.setText(R.string.title_patient_selection);
binding.selectPatientsToolbar.getRoot().inflateMenu(R.menu.select_patients_menu);
Toolbar.OnMenuItemClickListener menuItemClickListener = item -> {
if (selectedPatients.size() > 0) {
// save list into view model
sharedViewModel.setSelectedPatients(selectedPatients);
// MainActivity main = (MainActivity) getActivity();
// Objects.requireNonNull(main).findFragment(MainActivity.home_fragment);
} else {
String message = "Please select AT LEAST 1 patient";
Context context = getContext();
Toast toast = Toast.makeText(context, message, Toast.LENGTH_LONG);
toast.show();
}
return true;
};
binding.selectPatientsToolbar.getRoot().setOnMenuItemClickListener(menuItemClickListener);
binding.selectPatientsToolbar.btnBack.setOnClickListener(v -> {
// MainActivity main = (MainActivity) getActivity();
// Objects.requireNonNull(main).findFragment(MainActivity.login_fragment);
});
}
public void onPatientClick(boolean checked, PatientModel patient) {
PatientModel patientWithSameID = null;
boolean found = false;
for (PatientModel p : selectedPatients){
if(p.getPatientID().equals(patient.getPatientID())){
found = true;
patientWithSameID = p;
break;
}
}
if (checked) {
if (!found) {
selectedPatients.add(patient);
}
} else if (!checked) {
if(found){
selectedPatients.remove(patientWithSameID);
}else{
selectedPatients.remove(patient);
}
}
updateToolbar();
}
/**
* This method updates the tool bar to display the total number of patients that is currently
* being selected
*/
private void updateToolbar() {
String text = selectedPatients.size() + " Patients Selected";
// Log.d("Select_Patient_Fragment","current sellected patient : " + selected_patients.toString());
binding.selectPatientsToolbar.toolbarTitle.setText(text);
}
}
package com.sw.laryngoscope.model;
package com.sw.laryngoscope.FHIR.model;
public class PatientAddressModel {
private String city;
......
package com.sw.laryngoscope.model;
package com.sw.laryngoscope.FHIR.model;
import android.text.format.DateFormat;
import com.sw.laryngoscope.model.observation.BloodPressureObservationModel;
import com.sw.laryngoscope.model.observation.ObservationModel;
import com.sw.laryngoscope.model.observation.ObservationType;
import com.sw.laryngoscope.FHIR.model.observation.BloodPressureObservationModel;
import com.sw.laryngoscope.FHIR.model.observation.ObservationModel;
import com.sw.laryngoscope.FHIR.model.observation.ObservationType;
import org.hl7.fhir.r4.model.Enumerations;
......
package com.sw.laryngoscope.model.observation;
package com.sw.laryngoscope.FHIR.model.observation;
import org.hl7.fhir.r4.model.Observation;
......
package com.sw.laryngoscope.model.observation;
package com.sw.laryngoscope.FHIR.model.observation;
import org.hl7.fhir.r4.model.Observation;
......
package com.sw.laryngoscope.model.observation;
package com.sw.laryngoscope.FHIR.model.observation;
import org.hl7.fhir.r4.model.Observation;
......
package com.sw.laryngoscope.model.observation;
package com.sw.laryngoscope.FHIR.model.observation;
public enum ObservationType {
CHOLESTEROL, BLOOD_PRESSURE;
......
package com.sw.laryngoscope.service;
package com.sw.laryngoscope.FHIR.service;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.client.api.IGenericClient;
......
package com.sw.laryngoscope.service.repository;
package com.sw.laryngoscope.FHIR.service.repository;
import com.sw.laryngoscope.model.observation.BloodPressureObservationModel;
import com.sw.laryngoscope.model.observation.CholesterolObservationModel;
import com.sw.laryngoscope.model.observation.ObservationModel;
import com.sw.laryngoscope.model.observation.ObservationType;
import com.sw.laryngoscope.service.FhirService;
import com.sw.laryngoscope.FHIR.model.observation.BloodPressureObservationModel;
import com.sw.laryngoscope.FHIR.model.observation.CholesterolObservationModel;
import com.sw.laryngoscope.FHIR.model.observation.ObservationModel;
import com.sw.laryngoscope.FHIR.model.observation.ObservationType;
import com.sw.laryngoscope.FHIR.service.FhirService;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Observation;
......
package com.sw.laryngoscope.service.repository;
package com.sw.laryngoscope.FHIR.service.repository;
import com.sw.laryngoscope.model.PatientAddressModel;
import com.sw.laryngoscope.model.PatientModel;
import com.sw.laryngoscope.service.FhirService;
import com.sw.laryngoscope.FHIR.model.PatientAddressModel;
import com.sw.laryngoscope.FHIR.model.PatientModel;
import com.sw.laryngoscope.FHIR.service.FhirService;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Encounter;
......
package com.sw.laryngoscope.FHIR.viewModel;
public interface Poll {
void polling();
}
package com.sw.laryngoscope.FHIR.viewModel;
import android.util.Log;
import android.os.Handler;
import android.os.HandlerThread;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.LiveData;
import com.sw.laryngoscope.FHIR.model.PatientModel;
import com.sw.laryngoscope.FHIR.model.observation.ObservationModel;
import com.sw.laryngoscope.FHIR.model.observation.ObservationType;
import com.sw.laryngoscope.FHIR.service.repository.ObservationRepositoryFactory;
import com.sw.laryngoscope.FHIR.service.repository.PatientRepository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;
public class SharedViewModel extends ViewModel implements Poll {
// for polling
private MutableLiveData<HashMap<String, PatientModel>> patientObservations = new MutableLiveData<>();
// to get all the patients under practitioner
private MutableLiveData<HashMap<String, PatientModel>> allPatients = new MutableLiveData<>();
private String practitionerID = "";
private PatientRepository patientRepository;
private ObservationRepositoryFactory observationRepositoryFactory;
private MutableLiveData<String> selectedFrequency = new MutableLiveData<>() ;
private MutableLiveData<ArrayList<PatientModel>> selectedPatients = new MutableLiveData<>();
private void initShareViewModel() {
patientRepository = new PatientRepository(practitionerID);
observationRepositoryFactory = new ObservationRepositoryFactory();
fetchAllPatients();
setSelectedPatients(new ArrayList<>());
selectedFrequency.setValue("10");
}
public void setPractitionerID(String practitionerID) {
this.practitionerID = practitionerID;
initShareViewModel();
}
public LiveData<String> getSelectedFrequency() {
return selectedFrequency;
}
public void updateCurrentSelected(String currentSelected) {
this.selectedFrequency.setValue(currentSelected);
}
public LiveData<HashMap<String, PatientModel>> getAllPatientObservations() {
return patientObservations;
}
public void setSelectedPatients(ArrayList<PatientModel> selectedPatientsArray) {
selectedPatients.setValue(selectedPatientsArray);
}
public LiveData<HashMap<String, PatientModel>> getAllPatients() {
return allPatients;
}
private ObservationModel getObservation(String id, ObservationType observationType) {
return observationRepositoryFactory.getObservationModel(id, observationType);
}
private void fetchAllPatients() {
// run asynchronous tasks on background thread to prevent network on main exception
HandlerThread backgroundThread = new HandlerThread("Background Thread");
backgroundThread.start();
Handler timer = new Handler(backgroundThread.getLooper());
timer.post(() -> {
HashMap < String, PatientModel > patientHashMap = new HashMap<>();
// loop through all patients
for (PatientModel patient : patientRepository.getAllPatients()) {
try {
// only show patients with cholesterol and bp values
for (ObservationType type: ObservationType.values()) {
patient.setObservation(type, getObservation(patient.getPatientID(), type));
patientHashMap.put(patient.getPatientID(), patient);
}
patient.addLatestBPReadings(observationRepositoryFactory.getLatestBloodPressureReadings(patient.getPatientID(),5));
}
// patient does not have the observation type
catch (Exception e) {
Log.e("Patient ", "No observation type");
}
}
// update LiveData and notify observers - used by select patient
allPatients.postValue(patientHashMap);
});
polling();
}
public void polling() {
// run asynchronous tasks on background thread to prevent network on main exception
HandlerThread backgroundThread = new HandlerThread("Background Thread");
backgroundThread.start();
Handler timer = new Handler(backgroundThread.getLooper());
timer.post(new Runnable() {
@Override
public void run() {
HashMap<String, PatientModel> poHashMap = new HashMap<>();
// loop through all patients. update observations if observation is selected to be monitored
for (PatientModel patientModel: Objects.requireNonNull(selectedPatients.getValue())) {
for (ObservationType type: ObservationType.values()) {
if (patientModel.isObservationMonitored(type)) {
patientModel.setObservation(type, getObservation(patientModel.getPatientID(), type));
poHashMap.put(patientModel.getPatientID(), patientModel);
if (type == ObservationType.BLOOD_PRESSURE) {
patientModel.addLatestBPReadings(observationRepositoryFactory.getLatestBloodPressureReadings(patientModel.getPatientID(),5));
}
}
}
}
// update LiveData and notify observers
patientObservations.postValue(poHashMap);
timer.postDelayed(this, Integer.parseInt(Objects.requireNonNull(getSelectedFrequency().getValue()))*1000);
}});
}
}
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/unselected" />
<corners android:radius="50dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/color_accent" />
<corners android:radius="10dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/color_selected_patient" />
<corners android:radius="10dp" />
</shape>
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_layout"
android:foreground="?selectableItemBackground"
card_view:cardBackgroundColor="@color/color_accent"
card_view:cardCornerRadius="12dp"
card_view:cardElevation="3dp"
android:layout_margin="5dp"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/card_backgroud"
android:layout_width="match_parent"
android:layout_height="94dp">
<LinearLayout
android:id="@+id/linear_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
card_view:layout_constraintBottom_toBottomOf="parent"
card_view:layout_constraintEnd_toStartOf="@id/guideline2"
card_view:layout_constraintHorizontal_bias="0"
card_view:layout_constraintStart_toStartOf="parent"
card_view:layout_constraintTop_toTopOf="parent"
card_view:layout_constraintVertical_bias="0.5">
<CheckBox
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:theme="@style/checkBoxStyle"
android:visibility="gone" />
</LinearLayout>
<TextView
android:id="@+id/all_patient_txt_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/patient_name"
android:textSize="25sp"
card_view:layout_constraintBottom_toBottomOf="@id/linear_layout"
card_view:layout_constraintEnd_toStartOf="@id/guideline2"
card_view:layout_constraintHorizontal_bias="0.0"
card_view:layout_constraintStart_toEndOf="@id/guideline"
card_view:layout_constraintTop_toTopOf="parent"
card_view:layout_constraintVertical_bias="0.285" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
card_view:layout_constraintGuide_percent="0.04" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
card_view:layout_constraintGuide_percent="0.96" />
<com.google.android.material.chip.Chip
android:id="@+id/cholesterol_chip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="45dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="267dp"
android:checkable="true"
android:text="@string/cholesterol"
card_view:chipIcon="@drawable/cardv_grey_bg"
card_view:layout_constraintBottom_toBottomOf="parent"
card_view:layout_constraintEnd_toEndOf="parent"
card_view:layout_constraintStart_toStartOf="parent"
card_view:layout_constraintTop_toBottomOf="@+id/all_patient_txt_name" />
<com.google.android.material.chip.Chip
android:id="@+id/blood_pressure_chip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="25dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="100dp"
android:checkable="true"
android:text="@string/blood_pressure"
card_view:chipIcon="@drawable/cardv_grey_bg"
card_view:layout_constraintEnd_toEndOf="parent"
card_view:layout_constraintStart_toEndOf="@+id/cholesterol_chip"
card_view:layout_constraintTop_toBottomOf="@+id/all_patient_txt_name" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<include
android:id="@+id/select_patients_toolbar"
layout = "@layout/toolbar"/>
<TextView
android:id="@+id/select_patients_txt_loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/loading_patients"
android:textSize="20sp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/select_patients_toolbar"
app:layout_constraintVertical_bias="0"/>
<ProgressBar
android:id="@+id/select_patients_progressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/select_patients_toolbar"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/select_patients_recycler_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/select_patients_toolbar"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_layout"
android:foreground="?selectableItemBackground"
card_view:cardBackgroundColor="@color/color_accent"
card_view:cardCornerRadius="12dp"
card_view:cardElevation="3dp"
android:layout_margin="5dp"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/card_backgroud"
android:layout_width="match_parent"
android:layout_height="94dp">
<LinearLayout
android:id="@+id/linear_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
card_view:layout_constraintBottom_toBottomOf="parent"
card_view:layout_constraintEnd_toStartOf="@id/guideline2"
card_view:layout_constraintHorizontal_bias="0"
card_view:layout_constraintStart_toStartOf="parent"
card_view:layout_constraintTop_toTopOf="parent"
card_view:layout_constraintVertical_bias="0.5">
<CheckBox
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:theme="@style/checkBoxStyle"
android:visibility="gone" />
</LinearLayout>
<TextView
android:id="@+id/all_patient_txt_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/patient_name"
android:textSize="25sp"
card_view:layout_constraintBottom_toBottomOf="@id/linear_layout"
card_view:layout_constraintEnd_toStartOf="@id/guideline2"
card_view:layout_constraintHorizontal_bias="0.0"
card_view:layout_constraintStart_toEndOf="@id/guideline"
card_view:layout_constraintTop_toTopOf="parent"
card_view:layout_constraintVertical_bias="0.285" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
card_view:layout_constraintGuide_percent="0.04" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
card_view:layout_constraintGuide_percent="0.96" />
<com.google.android.material.chip.Chip
android:id="@+id/cholesterol_chip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="45dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="267dp"
android:checkable="true"
android:text="@string/cholesterol"
card_view:chipIcon="@drawable/cardv_grey_bg"
card_view:layout_constraintBottom_toBottomOf="parent"
card_view:layout_constraintEnd_toEndOf="parent"
card_view:layout_constraintStart_toStartOf="parent"
card_view:layout_constraintTop_toBottomOf="@+id/all_patient_txt_name" />
<com.google.android.material.chip.Chip
android:id="@+id/blood_pressure_chip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="25dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="100dp"
android:checkable="true"
android:text="@string/blood_pressure"
card_view:chipIcon="@drawable/cardv_grey_bg"
card_view:layout_constraintEnd_toEndOf="parent"
card_view:layout_constraintStart_toEndOf="@+id/cholesterol_chip"
card_view:layout_constraintTop_toBottomOf="@+id/all_patient_txt_name" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/colorPrimary"
android:elevation="6dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageButton
android:id="@+id/btn_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:src="@drawable/ic_arrow_back_24dp"
android:layout_centerVertical="true"
android:layout_marginRight="20dp"
/>
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/btn_back"
android:text="Title Here"
android:textSize="23sp"
android:textColor="@color/color_white"
android:layout_centerVertical="true">
</TextView>
</RelativeLayout>
</androidx.appcompat.widget.Toolbar>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/patient_add"
app:showAsAction="always"
android:title="@string/start_monitoring" />
</menu>
......@@ -368,4 +368,6 @@
<string name="string_check_date">检查日期:</string>
<string name="string_examination_doctor">检查医生:</string>
</resources>
\ No newline at end of file
......
......@@ -61,6 +61,10 @@
<color name="color_4f4f4f">#4F4F4F</color>
<color name="color_565656">#565656</color>
<color name="color_737373">#737373</color>
<color name="color_accent">#E0E9FF</color>
<color name="color_accent_text">#35375A</color>
<color name="color_selected_patient">#bedec5</color>
<color name="unselected">#8c92ac</color>
<color name="colorPrimary">#5C4AE4</color>
</resources>
\ No newline at end of file
......
......@@ -388,4 +388,12 @@
<string name="normal_mode">标定模式</string>
<string name="single_mode">单帧模式</string>
<string name="loading_patients">Loading Patients…</string>
<string name="patient_name">Patient Name</string>
<string name="cholesterol">cholesterol</string>
<string name="blood_pressure">blood pressure</string>
<string name="zero_patients_message">You have 0 patients</string>
<string name="title_patient_selection">Select Patients</string>
<string name="start_monitoring">Start</string>
</resources>
\ No newline at end of file
......
......@@ -53,4 +53,9 @@
<item name="colorControlActivated">@color/color_42bf58</item>
</style>
<style name="checkBoxStyle" parent="Base.Theme.AppCompat">
<item name="colorAccent">@color/color_accent_text</item>
<item name="android:textColorSecondary">@color/color_accent_text</item>
</style>
</resources>
\ No newline at end of file
......