2.9 学习总结 之 【Android】体温统计APP
一、说在前面
昨天 | 学习了JQ的相关知识 |
今天 | 编写体温统计APP |
我的工程源码:https://github.com/xiaotian12-call/Take-body-temperature
二、所有知识
1、使用Room管理数据库。
2、使用ViewModel管理UI数据。
3、使用hellochart图表展示数据。
4、使用liveData管理数据库数据(观察者),时时更新界面数据。
三、设计思路
1、构建底层数据库。
2、UI设计(卡片视图界面,单个卡片界面,折线图表界面,录入体温界面,菜单界面)。
3、编写Navigation,将卡片视图界面,折线图表界面,录入体温界面加入其中,并确定界面跳转关系。
4、编写适配器,体温数据工厂。
5、编写ViewModel,通过‘工厂’操控数据。
6、完善各个界面的逻辑代码。
1)卡片视图界面,组件绑定,菜单绑定及菜单功能实现,界面跳转。
2)折线图表界面,根据数据库数据,封装好点,线,轴的相关数据。
3)录入体温界面,绑定组件,根据输入数据及当前系统时间更新数据库。
四、体温统计APP编写
1、构建底层数据库。
1)表结构
2)代码实体 :Entity
package com.me.temperature; import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey; @Entity(tableName = "temperature")
public class temperature {
@PrimaryKey(autoGenerate = true)
private int id;
@ColumnInfo(name = "tp")
private String tp;
@ColumnInfo(name = "time")
private String time; public temperature(String tp, String time) {
this.tp = tp;
this.time = time;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getTp() {
return tp;
} public void setTp(String tp) {
this.tp = tp;
} public String getTime() {
return time;
} public void setTime(String time) {
this.time = time;
}
}
3)Dao
package com.me.temperature; import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update; import java.util.List;
@Dao
public interface TempDao {
@Insert
void insertTp (temperature ... temperatures);
@Update
void updateTp (temperature ... temperatures);
@Delete
void deleteTp (temperature ... temperatures);
@Query("DELETE From TEMPERATURE")
void deleteAllTp ();
@Query("SELECT * From TEMPERATURE ORDER BY ID DESC")
LiveData<List<temperature>> getAllTp ();
}
4)Database
package com.me.temperature; import android.content.Context; import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase; @Database(entities = {temperature.class },version = 1,exportSchema = false)
public abstract class TempDatabase extends RoomDatabase {
private static TempDatabase INSTANCE;
public abstract TempDao getTempDao();
static synchronized TempDatabase getTempDatabase(Context context){
if (INSTANCE == null){
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),TempDatabase.class,"tp_database")
.build();
}
return INSTANCE;
}
}
2、UI设计(卡片视图界面,单个卡片界面,折线图表界面,录入体温界面,菜单界面)
1)卡片视图界面
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AccountRecordFragment"
android:id="@+id/frameLayout"> <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/buttonTpAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_margin="16dp"
android:clickable="true"
android:focusable="true"
android:src="@drawable/ic_add_witer_24dp"
tools:layout_conversion_absoluteHeight="56dp"
tools:layout_conversion_absoluteWidth="56dp"
tools:layout_editor_absoluteX="178dp"
tools:layout_editor_absoluteY="659dp" /> <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:layout_conversion_absoluteHeight="731dp"
tools:layout_conversion_absoluteWidth="411dp"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="0dp" />
</FrameLayout>
2)单个卡片界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"> <androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"> <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="4dp"
android:foreground="?selectableItemBackground"> <androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.1" /> <TextView
android:id="@+id/textViewId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="36sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="1" /> <TextView
android:id="@+id/textViewTp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:textSize="36sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/textViewTime"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toTopOf="parent" /> <TextView
android:id="@+id/textViewTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="@+id/textViewTp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/textViewTp"
app:layout_constraintTop_toTopOf="@+id/textViewTp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
3)折线图表界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"> <lecho.lib.hellocharts.view.LineChartView
android:id="@+id/chart"
android:padding="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent" /> </LinearLayout>
4)录入体温界面
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/frameLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AddFragment" > <TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/add_title_tp"
android:textSize="36sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.05" /> <ImageView
android:id="@+id/imageView2"
android:layout_width="326dp"
android:layout_height="262dp"
android:layout_marginTop="8dp"
android:contentDescription="@string/add_image"
android:src="@drawable/temp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:layout_constraintVertical_bias="0.05" /> <Button
android:id="@+id/buttonAdd"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:text="@string/add_but"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.7" /> <EditText
android:id="@+id/editTextTp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:ems="10"
android:hint="@string/add_tp_in"
android:importantForAutofill="no"
android:inputType="number"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.6" /> </androidx.constraintlayout.widget.ConstraintLayout>
5)菜单界面
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item
android:id="@+id/clearAll"
android:title="@string/menu_claer" />
<item
android:id="@+id/chart"
android:title="@string/menu_chart" />
</menu>
3、编写Navigation,将卡片视图界面,折线图表界面,录入体温界面加入其中,并确定界面跳转关系。
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/navigation"
app:startDestination="@id/investigationFragment"> <fragment
android:id="@+id/investigationFragment"
android:name="com.me.temperature.InvestigationFragment"
android:label="fragment_investigation"
tools:layout="@layout/fragment_investigation" >
<action
android:id="@+id/action_investigationFragment_to_chartFragment"
app:destination="@id/chartFragment" />
<action
android:id="@+id/action_investigationFragment_to_addFragment"
app:destination="@id/addFragment" />
</fragment>
<fragment
android:id="@+id/chartFragment"
android:name="com.me.temperature.ChartFragment"
android:label="fragment_chart"
tools:layout="@layout/fragment_chart" />
<fragment
android:id="@+id/addFragment"
android:name="com.me.temperature.AddFragment"
android:label="fragment_add"
tools:layout="@layout/fragment_add" >
<action
android:id="@+id/action_addFragment_to_investigationFragment"
app:destination="@id/investigationFragment" />
</fragment>
</navigation>
4、编写适配器,体温数据工厂。
1)适配器
package com.me.temperature; import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList;
import java.util.List; public class MyAdpter extends RecyclerView.Adapter <MyAdpter.MyViewHolder>{
List<temperature> allTemperature = new ArrayList<>();
public void setAllTemperature(List<temperature> allTemperature) {
this.allTemperature = allTemperature;
} @NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View itemView = layoutInflater.inflate(R.layout.tp_cell,parent,false);
MyViewHolder holder = new MyViewHolder(itemView);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { }
});
return holder;
} @Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
temperature temperature = allTemperature.get(position);
holder.textViewId.setText(String.valueOf(position+1));
holder.textViewTime.setText(temperature.getTime());
holder.textViewType.setText(temperature.getTp());
} @Override
public int getItemCount() {
return allTemperature.size() ;
} static class MyViewHolder extends RecyclerView.ViewHolder{
TextView textViewId,textViewType,textViewMoney,textViewTime;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
textViewId = itemView.findViewById(R.id.textViewId);
textViewType = itemView.findViewById(R.id.textViewTp);
textViewTime = itemView.findViewById(R.id.textViewTime);
}
} }
2)工厂
package com.me.temperature; import android.content.Context;
import android.os.AsyncTask; import androidx.lifecycle.LiveData; import java.util.List; public class TpRepository {
private LiveData<List<temperature>> allTemperature;
private static List<temperature> allTemperatures; private TempDao tempDao;
public TpRepository(Context context) {
TempDatabase accountRecordDatabase = TempDatabase.getTempDatabase(context.getApplicationContext());
tempDao = accountRecordDatabase.getTempDao();
allTemperature = tempDao.getAllTp();
} public LiveData<List<temperature>> getAllTemperature() {
return allTemperature;
}
void insertTemperature(temperature ... temperatures){
new InsertAsyncTask(tempDao).execute(temperatures);
}
void deleteAllTemperature(){
new DeleteAsyncTask(tempDao).execute();
}
void deleteTemperature(temperature ... temperatures){
new DeleteAsyncTask_2(tempDao).execute(temperatures);
}
static class InsertAsyncTask extends AsyncTask<temperature ,Void,Void> {
private TempDao tempDao; public InsertAsyncTask(TempDao tempDao) {
this.tempDao = tempDao;
} @Override
protected Void doInBackground(temperature... temperatures) {
tempDao.insertTp(temperatures);
return null;
}
}
static class DeleteAsyncTask extends AsyncTask<Void ,Void,Void>{
private TempDao tempDao; public DeleteAsyncTask(TempDao tempDao) {
this.tempDao = tempDao;
} @Override
protected Void doInBackground(Void... Voids) {
tempDao.deleteAllTp();
return null;
}
}
static class DeleteAsyncTask_2 extends AsyncTask<temperature ,Void,Void>{
private TempDao tempDao; public DeleteAsyncTask_2(TempDao tempDao) {
this.tempDao = tempDao;
} @Override
protected Void doInBackground(temperature... temperatures ) {
tempDao.deleteTp(temperatures);
return null;
}
}
}
5、编写ViewModel,通过‘工厂’操控数据。
package com.me.temperature; import android.app.Application; import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData; import java.util.List; public class TpViewModel extends AndroidViewModel {
private TpRepository tpRepository; public TpViewModel(@NonNull Application application) {
super(application);
tpRepository = new TpRepository((application));
} public LiveData<List<temperature>> getAllTemperature() {
return tpRepository.getAllTemperature();
} void insertTemperature(temperature ... temperatures){
tpRepository.insertTemperature(temperatures);
}
void deleteAllTemperature(){
tpRepository.deleteAllTemperature();
}
void deleteTemperature(temperature ... temperatures){
tpRepository.deleteTemperature(temperatures);
}
}
6、完善各个界面的逻辑代码。
1)卡片视图界面,组件绑定,菜单绑定及菜单功能实现,界面跳转。
package com.me.temperature; import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.floatingactionbutton.FloatingActionButton; import java.util.List; /**
* A simple {@link Fragment} subclass.
*/
public class InvestigationFragment extends Fragment {
private TpViewModel tpViewModel;
private RecyclerView recyclerView;
private MyAdpter myAdpter;
private FloatingActionButton floatingActionButton;
private LiveData<List<temperature>> findTemperature;
private List<temperature> allTemperatures;
public InvestigationFragment() {
setHasOptionsMenu(true);
// Required empty public constructor
} @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_investigation, container, false);
} @Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()){
case R.id.clearAll:
AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
builder.setTitle("清空账单");
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
tpViewModel.deleteAllTemperature();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) { }
});
builder.create();
builder.show();
break;
case R.id.chart:
NavController navController = Navigation.findNavController(requireActivity(),R.id.fragment);
navController.navigate(R.id.action_investigationFragment_to_chartFragment);
}
return super.onOptionsItemSelected(item);
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu,menu);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
tpViewModel = ViewModelProviders.of(requireActivity()).get(TpViewModel.class);
recyclerView = requireActivity().findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(requireActivity()));
myAdpter = new MyAdpter();
recyclerView.setAdapter(myAdpter);
findTemperature = tpViewModel.getAllTemperature();
findTemperature.observe(requireActivity(), new Observer<List<temperature>>() {
@Override
public void onChanged(List<temperature> temperatures) {
allTemperatures = temperatures;
myAdpter.setAllTemperature(temperatures);
myAdpter.notifyDataSetChanged();
}
});
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.START | ItemTouchHelper.END) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
return false;
} @Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
temperature temperature = allTemperatures.get(viewHolder.getLayoutPosition());
tpViewModel.deleteTemperature(temperature);
}
}).attachToRecyclerView(recyclerView);
floatingActionButton = requireActivity().findViewById(R.id.buttonTpAdd);
floatingActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
NavController navController = Navigation.findNavController(v);
navController.navigate(R.id.action_investigationFragment_to_addFragment);
}
});
}
}
2)折线图表界面,根据数据库数据,封装好点,线,轴的相关数据。
package com.me.temperature; import android.graphics.Color;
import android.os.Bundle; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders; import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap; import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.AxisValue;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.model.ValueShape;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.LineChartView; /**
* A simple {@link Fragment} subclass.
*/
public class ChartFragment extends Fragment {
private LineChartView mChart;
private Map<String,String> table = new TreeMap<>();
private LineChartData mData;
private TpViewModel tpViewModel;
private List<AxisValue> mAxisXValues = new ArrayList<AxisValue>();
private List<AxisValue> values = new ArrayList<>(); public ChartFragment() {
// Required empty public constructor
} @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_chart, container, false);
} @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mChart = view.findViewById(R.id.chart);
} @Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
tpViewModel = ViewModelProviders.of(requireActivity()).get(TpViewModel.class);
mData = new LineChartData();
List<temperature> allDate = tpViewModel.getAllTemperature().getValue();
generateValues(allDate);
generateData();
}
private void generateData() {
List<Line> lines = new ArrayList<>();
List<PointValue> values = new ArrayList<>();
int indexX = 0;
for(String value : table.values()){
char [] chars = value.toCharArray();
String string = "";
if(chars.length>0){
string += chars[0];
}
if(chars.length>1){
string += chars[1];
}
values.add(new PointValue(indexX, Integer.valueOf(string)));
indexX++;
}
Line line = new Line(values);
line.setColor(ChartUtils.COLORS[0]);
line.setShape(ValueShape.CIRCLE);
line.setPointColor(ChartUtils.COLORS[1]);
lines.add(line);
mData.setLines(lines);
setAxis();
mChart.setLineChartData(mData);
} private void generateValues(List<temperature> allDate) {
if(allDate != null){
for (int i = 0; i < allDate.size(); i++) {
temperature costBean = allDate.get(i);
String costDate = costBean.getTime();
String costTp = costBean.getTp();
//mAxisXValues.add(new AxisValue(allDate.size() - i - 1).setLabel(costDate));
mAxisXValues.add(new AxisValue(i).setLabel(costDate));
if(!table.containsKey(costDate)){
table.put(costDate,costTp);
//mAxisXValues.add(new AxisValue(i).setLabel(costDate));
}else {
table.put(costDate,costTp);
}
}
}
} private void setAxis() {
//坐标轴
Axis axisX = new Axis(); //X轴
axisX.setHasTiltedLabels(true); //X坐标轴字体是斜的显示还是直的,true是斜的显示
axisX.setTextColor(Color.GRAY); //设置字体颜色
axisX.setName("日期"); //表格名称
axisX.setTextSize(10);//设置字体大小
axisX.setMaxLabelChars(7); //最多几个X轴坐标,意思就是你的缩放让X轴上数据的个数7<=x<=mAxisXValues.length
axisX.setValues(mAxisXValues); //填充X轴的坐标名称
mData.setAxisXBottom(axisX); //x 轴在底部
//data.setAxisXTop(axisX); //x 轴在顶部
axisX.setHasLines(true); //x 轴分割线 Axis axisY = new Axis().setHasLines(true);
axisY.setMaxLabelChars(6);//max label length, for example 60 for(int i = 35; i < 45; i+= 1){
AxisValue value = new AxisValue(i);
String label = i + "℃";
value.setLabel(label);
values.add(value);
}
axisY.setValues(values);
axisY.setName("体温");//y轴标注
axisY.setTextSize(10);//设置字体大小
mData.setAxisYLeft(axisY); //Y轴设置在左边
//data.setAxisYRight(axisY); //y轴设置在右边
}
}
3)录入体温界面,绑定组件,根据输入数据及当前系统时间更新数据库。
package com.me.temperature; import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProviders;
import androidx.navigation.NavController;
import androidx.navigation.Navigation; import java.text.SimpleDateFormat;
import java.util.Date; /**
* A simple {@link Fragment} subclass.
*/
public class AddFragment extends Fragment {
private Button buttonSubmit;
private EditText editTextTp;
private TpViewModel tpViewModel; public AddFragment() {
// Required empty public constructor
} @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_add, container, false);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
FragmentActivity activity = requireActivity();
tpViewModel = ViewModelProviders.of(activity).get(TpViewModel.class);
buttonSubmit = activity.findViewById(R.id.buttonAdd);
editTextTp = activity.findViewById(R.id.editTextTp);
buttonSubmit.setEnabled(false);
TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
String type = editTextTp.getText().toString().trim();
buttonSubmit.setEnabled(!type.isEmpty()); } @Override
public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override
public void afterTextChanged(Editable s) { }
};
editTextTp.addTextChangedListener(textWatcher);
buttonSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String tp = editTextTp.getText().toString().trim();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");// HH:mm:ss
//获取当前时间
Date date = new Date(System.currentTimeMillis());
temperature temperature = new temperature(tp+"℃",simpleDateFormat.format(date));
tpViewModel.insertTemperature(temperature);
NavController navController = Navigation.findNavController(v);
navController.navigate(R.id.action_addFragment_to_investigationFragment);
}
});
}
}
2.9 学习总结 之 【Android】体温统计APP的更多相关文章
- android体温登记APP开发过程+问题汇总+源码
源码上传至https://github.com/durtime/myproject下的temperature 实际效果: 开发过程 1.首先进行布局文件的编写,布局前台页面 2.布置两个按钮,一个 ...
- 体温填报app作业演示
今日学习 今天把这个体温填写app作业,做完了. 具体开发流程:https://www.cnblogs.com/yuxuan-light-of-Taihu-Lake/p/14362107.html 点 ...
- 【java学习系列】 Android第一本书《第一行代码》
开始Java的学习,从Android,开始吧.<第一代码>开始阅读和调试demo例子. 下面是 <第一行代码>的思维导图:
- Android Stduio统计项目的代码行数
android studio统计项目的代码行数的步骤如下: 1)按住Ctrl+Shift+A,在弹出的框输入‘find’,然后选择Find in Path.(或者使用快捷键Ctrl+Shift+F) ...
- Android学习系列(39)--Android主题和样式之系统篇(上)
[基于最新的Android4.4的源码分析] 每家公司或者每个移动团队无不想开发出一套自己的UI框架,融入自己的设计和特性,这必然会去修改android的ui.所以,学习和理解android的UI设计 ...
- [原]零基础学习视频解码之android篇系列文章
截止今天,<零基础学习视频解码系列文章>.<零基础学习在Android进行SDL开发系列文章>以及<零基础学习视频解码之android篇>系列文章基本算是告一段落了 ...
- Android流量统计TrafficStats类
对于Android流量统计来说在2.2版中新加入了TrafficStats类可以轻松获取,其实本身TrafficStats类也是读取Linux提供的文件对象系统类型的文本进行解析. android.n ...
- 学习新手给Android新手的一些学习建议
时间紧张,先记一笔,后续优化与完善. Shamoo做Android开辟已有一年了,对Android开辟也有一点点了解.上面就给Android新手说说我对Android浅面的意识和一点建议吧,知道的大牛 ...
- Android 事件统计
title: Android 事件统计 1.写在前面的话 最近都在看framework的东西,也几天没有写什么东西,今天有点时间写下上次面试遇到的一个问题.问题大概是这样的,如果我需要统计页面的点击事 ...
随机推荐
- 苹果系统 MacOS 安装根证书
12306 网上购票以及一些其他内部使用的系统,需要安装.cer扩展名的根证书的情况,windows安装较为简单大家也比较熟悉,使用mac安装根证书在此做下详细介绍. 当前以10.13.5版本为例,其 ...
- 2月送书福利:ASP.NET Core开发实战
大家都知道我有一个公众号“恰童鞋骚年”,在公众号2020年第一天发布的推文<2020年,请让我重新介绍我自己>中,我曾说到我会在2020年中每个月为所有关注“恰童鞋骚年”公众号的童鞋们送一 ...
- 本地启动tomcat的时候报java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: PermGen space
1.问题:我在tomcat中放入了大量的war包,启动的时候报:java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: ...
- springcloud-zuul进阶篇
一 前言 经过zuul初级篇(博客或者公主号springcloud专栏可以找到)的学习,读者都懂得如何简单的使用zuul进行路由网关配置,在进阶篇中你将获得zuul核心功能过滤器的基本使用,通过zuu ...
- 140、Java内部类之实例化内部类对象
01.代码如下: package TIANPAN; class Outer { // 外部类 private String msg = "Hello World !"; class ...
- 多年珍藏的55w御剑字典
御剑珍藏55w目录字典,很给力,放在以前直接数据库都能给跑出来. 用法:直接把放入配置文件的目录 链接:https://pan.baidu.com/s/1MGxdd9hH006Y7AO7CpkO8g ...
- [排错] VO对象和POJO对象的关系
这或许是一个很蠢的笔记吧...... 这次项目中, 作为一个新人, 没少被这两个概念虐得死去活来的, 现在特别做一次记录, 关于它们二者之间在项目中的应用. 在这里呢, 就不再赘述 VO(view o ...
- 4专题总结-图论和DFS、BFS
1图论: 1.1 133. Clone Graph https://leetcode.com/problems/clone-graph/#/description 思路:这题可以对照拷贝随机链表那道 ...
- python绘制WordCloud词云图
目录 前言 核心代码 测试 前言 当我们想快速了解书籍.小说.电影剧本中的内容时,可以绘制 WordCloud 词云图,显示主要的关键词(高频词),可以非常直观地看到结果 核心代码 from word ...
- 如何使用Docker部署PHP开发环境
本文主要介绍了如何使用Docker构建PHP的开发环境,文中作者也探讨了构建基于Docker的开发环境应该使用单容器还是多容器,各有什么利弊.推荐PHP开发者阅读.希望对大家有所帮助. 环境部署一直是 ...