MainActivity
カレンダー画面の表示
カレンダー表示はアダプタークラスを使用
package to.msn.wings.weightmanagement;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CalendarView;
import android.widget.GridView;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import java.util.Locale;
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
private TextView titleText;
private Button prevButton, nextButton;
private CalendarAdapter mCalendarAdapter;
private GridView calendarGridView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
titleText = findViewById(R.id.titleText);
prevButton = findViewById(R.id.prevButton);
prevButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCalendarAdapter.prevMonth();
titleText.setText(mCalendarAdapter.getTitle());
}
});
nextButton = findViewById(R.id.nextButton);
nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCalendarAdapter.nextMonth();
titleText.setText(mCalendarAdapter.getTitle());
}
});
calendarGridView = findViewById(R.id.calendarGridView);
mCalendarAdapter = new CalendarAdapter(this);
calendarGridView.setAdapter(mCalendarAdapter);
titleText.setText(mCalendarAdapter.getTitle());
calendarGridView.setOnItemClickListener(this);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(getApplicationContext(), ContentActivity.class);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.JAPAN);
String str = dateFormat.format(mCalendarAdapter.getItem(position));
intent.putExtra("date", str);
startActivity(intent);
}
//オプションメニューの表示
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.option_menu,menu);
return true;
}
//オプションメニューの選択時の画面遷移
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()) {
case R.id.item1:
break;
case R.id.item2:
Intent intent2 = new Intent(MainActivity.this, GraphActivity.class);
startActivity(intent2);
break;
}
return true;
}
}
WeightFatDatabase
日付、体重、体脂肪 データベースSQLite
package to.msn.wings.weightmanagement;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class WeightFatDatabase extends SQLiteOpenHelper {
static final private String DBNAME = "weightfat.sqlite";
static final private int VERSION = 1;
WeightFatDatabase(Context context){
super(context,DBNAME,null,VERSION);
}
@Override
public void onOpen(SQLiteDatabase db){
super.onOpen(db);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE weightfat (" +
"dating TEXT PRIMARY KEY, weight Float, fat Float)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS weightfat");
onCreate(db);
}
}
CalendarAdapter
アダプタークラスを作成しカレンダーを表示
package to.msn.wings.weightmanagement;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class CalendarAdapter extends BaseAdapter {
private List dateArray = new ArrayList();
private Context mContext;
private DateManager mDateManager;
private LayoutInflater mLayoutInflater;
private WeightFatDatabase helper = null; //データベースヘルパー
//カスタムセルを拡張したらここでWigetを定義
private static class ViewHolder {
public TextView dateText;
public TextView memoText;
public TextView bmiText;
}
public CalendarAdapter(Context context){
mContext = context;
mLayoutInflater = LayoutInflater.from(mContext);
mDateManager = new DateManager();
dateArray = mDateManager.getDays();
}
@Override
public int getCount() {
return dateArray.size();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mLayoutInflater.inflate(R.layout.calendar_cell, null);
holder = new ViewHolder();
holder.dateText = convertView.findViewById(R.id.dateText);
holder.memoText = convertView.findViewById(R.id.memoText);
holder.bmiText = convertView.findViewById(R.id.bmiText);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
//セルのサイズを指定
float dp = mContext.getResources().getDisplayMetrics().density;
AbsListView.LayoutParams params = new AbsListView.LayoutParams(parent.getWidth()/7 - (int)dp, (parent.getHeight() - (int)dp * mDateManager.getWeeks() ) / mDateManager.getWeeks());
convertView.setLayoutParams(params);
//日付のみ表示させる
SimpleDateFormat dateFormat = new SimpleDateFormat("d", Locale.JAPAN);
holder.dateText.setText(dateFormat.format(dateArray.get(position)));
//カレンダーセルに体重・体脂肪
helper = new WeightFatDatabase(mContext);
SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd", Locale.JAPAN);
String date1 = dateFormat1.format(dateArray.get(position));
String[] clos = {"dating","weight","fat"};
String[] dating = {date1};
try (SQLiteDatabase db = helper.getReadableDatabase();
Cursor cs = db.query("weightfat" , clos , "dating = ?",dating,null,null,null,null))
{
String memo = "";
if (cs.moveToFirst()){
memo += cs.getString(1) + "kg\n";
memo += cs.getString(2) + "%";
holder.memoText.setText(memo);
}else{
memo = "";
holder.memoText.setText(memo);
}
}
//当月以外のセルをグレーアウト
if (mDateManager.isCurrentMonth(dateArray.get(position))){
convertView.setBackgroundColor(Color.WHITE);
}else {
convertView.setBackgroundColor(Color.LTGRAY);
}
//当日の背景
if (mDateManager.isToday(dateArray.get(position))) {
convertView.setBackgroundColor(Color.YELLOW);
}
//日曜日を赤、土曜日を青に
int colorId;
switch (mDateManager.getDayOfWeek(dateArray.get(position))){
case 1:
colorId = Color.RED;
break;
case 7:
colorId = Color.BLUE;
break;
default:
colorId = Color.BLACK;
break;
}
holder.dateText.setTextColor(colorId);
return convertView;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public Object getItem(int position) {
return dateArray.get(position);
}
//表示月を取得
public String getTitle(){
SimpleDateFormat format = new SimpleDateFormat("yyyy.MM", Locale.JAPAN);
return format.format(mDateManager.mCalendar.getTime());
}
//翌月表示
public void nextMonth(){
mDateManager.nextMonth();
dateArray = mDateManager.getDays();
this.notifyDataSetChanged();
}
//前月表示
public void prevMonth(){
mDateManager.prevMonth();
dateArray = mDateManager.getDays();
this.notifyDataSetChanged();
}
}
DateManager
カレンダー日付を操作する専用クラス。
package to.msn.wings.weightmanagement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class DateManager {
Calendar mCalendar;
public DateManager(){
mCalendar = Calendar.getInstance();
}
//当月の要素を取得
public List getDays(){
//現在の状態を保持
Date startDate = mCalendar.getTime();
//GridViewに表示するマスの合計を計算
int count = getWeeks() * 7 ;
//当月のカレンダーに表示される前月分の日数を計算
mCalendar.set(Calendar.DATE, 1);
int dayOfWeek = mCalendar.get(Calendar.DAY_OF_WEEK) - 1;
mCalendar.add(Calendar.DATE, -dayOfWeek);
List days = new ArrayList<>();
for (int i = 0; i < count; i ++){
days.add(mCalendar.getTime());
mCalendar.add(Calendar.DATE, 1);
}
//状態を復元
mCalendar.setTime(startDate);
return days;
}
//当月かどうか確認
public boolean isCurrentMonth(Date date){
SimpleDateFormat format = new SimpleDateFormat("yyyy.MM", Locale.JAPAN);
String currentMonth = format.format(mCalendar.getTime());
if (currentMonth.equals(format.format(date))){
return true;
}else {
return false;
}
}
//当日かどうか確認
public boolean isToday(Date date) {
SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd", Locale.JAPAN);
String today = format.format(Calendar.getInstance().getTime());
return today.equals(format.format(date));
}
//週数を取得
public int getWeeks(){
return mCalendar.getActualMaximum(Calendar.WEEK_OF_MONTH);
}
//曜日を取得
public int getDayOfWeek(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar.get(Calendar.DAY_OF_WEEK);
}
//翌月へ
public void nextMonth(){
mCalendar.add(Calendar.MONTH, 1);
}
//前月へ
public void prevMonth(){
mCalendar.add(Calendar.MONTH, -1);
}
}
ContentActivity
カレンダーの日付をタップ後の体重、体脂肪の入力画面
package to.msn.wings.weightmanagement;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.text.SimpleDateFormat;
import java.util.Locale;
public class ContentActivity extends AppCompatActivity {
private String currentDate;
private WeightFatDatabase helper = null; //データベースヘルパー
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_content);
//テキストビューにタップした日付表示
TextView tvToday = findViewById(R.id.txtToday);
Intent intent = getIntent();
currentDate = intent.getStringExtra("date");
tvToday.setText(currentDate);
//データベース準備
helper = new WeightFatDatabase(this);
//入力済みのテキストに体重・体脂肪の表示
EditText txtWeight = (EditText) findViewById(R.id.txtWeight);
EditText txtBodyfat = (EditText) findViewById(R.id.txtBodyfat);
Button btnUpdate = findViewById(R.id.btnUpdate);
String[] clos = {"dating","weight","fat"};
String[] params = {tvToday.getText().toString()};
try (SQLiteDatabase db = helper.getReadableDatabase();
Cursor cs = db.query("weightfat" , clos , "dating = ?",params,null,null,null,null) )
{
if (cs.moveToFirst()){
txtWeight.setText(cs.getString(1));
txtBodyfat.setText(cs.getString(2));
btnUpdate.setText("編集");
}
}
}
public void onUpdate(View view){
EditText txtWeight = (EditText) findViewById(R.id.txtWeight);
EditText txtBodyfat = (EditText) findViewById(R.id.txtBodyfat);
//体重・体脂肪の入力
try (SQLiteDatabase db = helper.getWritableDatabase()){
ContentValues cv = new ContentValues();
cv.put("dating",currentDate);
cv.put("weight",txtWeight.getText().toString());
cv.put("fat",txtBodyfat.getText().toString());
db.insertWithOnConflict("weightfat",null, cv, SQLiteDatabase.CONFLICT_REPLACE);
}
finish();
}
}
GraphActivity
体重の推移グラフ表示
package to.msn.wings.weightmanagement;
import androidx.appcompat.app.AppCompatActivity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Typeface;
import android.os.Bundle;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import java.util.ArrayList;
public class GraphActivity extends AppCompatActivity {
private LineChart mChart;
private WeightFatDatabase helper = null; //データベースヘルパー
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_graph);
mChart = findViewById(R.id.lineChart);
helper = new WeightFatDatabase(this);
ArrayList xLabel = new ArrayList<>();
int ava = 50;
// Grid背景色
mChart.setDrawGridBackground(true);
// no description text
mChart.getDescription().setEnabled(true);
// Grid縦軸を破線
XAxis xAxis = mChart.getXAxis();
xAxis.enableGridDashedLine(10f, 10f, 0f);
xAxis.setLabelCount(7, true);
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
YAxis leftAxis = mChart.getAxisLeft();
// Y軸最大最小設定
leftAxis.setAxisMaximum(80f);
leftAxis.setAxisMinimum(40f);
// Grid横軸を破線
leftAxis.enableGridDashedLine(10f, 10f, 0f);
leftAxis.setDrawZeroLine(true);
// 右側の目盛り
mChart.getAxisRight().setEnabled(false);
// add data
setData();
mChart.animateX(1000);
//mChart.invalidate();
// dont forget to refresh the drawing
// mChart.invalidate();
}
private void setData() {
// Entry()を使ってLineDataSetに設定できる形に変更してarrayを新しく作成
ArrayList values = new ArrayList<>();
//データベースから体重データの取得
try (SQLiteDatabase db = helper.getReadableDatabase();
Cursor cs = db.rawQuery("SELECT * FROM weightfat ORDER BY dating",null))
{
int number = 0;
boolean eol = cs.moveToFirst();
while (eol){
if (cs.getFloat(1 ) != 0){
values.add(new Entry(number, cs.getFloat(1), null, null));
number++;
eol = cs.moveToNext();
}else {
eol = cs.moveToNext();
}
}
}
LineDataSet set1;
if (mChart.getData() != null &&
mChart.getData().getDataSetCount() > 0) {
set1 = (LineDataSet) mChart.getData().getDataSetByIndex(0);
set1.setValues(values);
mChart.getData().notifyDataChanged();
mChart.notifyDataSetChanged();
} else {
set1 = new LineDataSet(values, "体重");
set1.setColor(Color.BLACK);
set1.setCircleColor(Color.BLACK);
ArrayList dataSets = new ArrayList();
dataSets.add(set1); // add the datasets
// create a data object with the datasets
LineData lineData = new LineData(dataSets);
// set data
mChart.setData(lineData);
}
}
}
activity_main
メインアクティビティのレイアウト
<?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:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/grayColor" > <RelativeLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2" android:background="@color/whiteColor"> <TextView android:id="@+id/titleText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="2018.2" android:textSize="20sp" android:layout_centerInParent="true"/> <Button android:id="@+id/prevButton" android:layout_width="wrap_content" android:layout_height="match_parent" android:text="Prev" android:layout_alignParentLeft="true" android:layout_marginVertical="10dp" android:layout_marginLeft="10dp" android:background="@color/colorAccent"/> <Button android:id="@+id/nextButton" android:layout_width="wrap_content" android:layout_height="match_parent" android:text="Next" android:layout_alignParentRight="true" android:layout_marginVertical="10dp" android:layout_marginRight="10dp" android:background="@color/colorAccent"/> </RelativeLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginVertical="1dp"> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_marginHorizontal="1dp" android:textAlignment="center" android:text="日" android:background="@color/whiteColor" android:textColor="@color/redColor"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_marginRight="1dp" android:layout_weight="1" android:background="@color/whiteColor" android:text="月" android:textColor="@color/blackColor" android:textAlignment="center"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_marginRight="1dp" android:textAlignment="center" android:text="火" android:textColor="@color/blackColor" android:background="@color/whiteColor"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_marginRight="1dp" android:textAlignment="center" android:text="水" android:textColor="@color/blackColor" android:background="@color/whiteColor"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_marginRight="1dp" android:textAlignment="center" android:text="木" android:textColor="@color/blackColor" android:background="@color/whiteColor"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_marginRight="1dp" android:textAlignment="center" android:text="金" android:textColor="@color/blackColor" android:background="@color/whiteColor"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_marginRight="1dp" android:textAlignment="center" android:text="土" android:textColor="@color/blueColor" android:background="@color/whiteColor"/> </LinearLayout> <GridView android:id="@+id/calendarGridView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="15" android:horizontalSpacing="1dp" android:layout_marginLeft="1dp" android:numColumns="7" android:stretchMode="columnWidth" android:verticalSpacing="1dp"></GridView> </LinearLayout>
activity_content
コンテンツアクティビティのレイアウト
<?xml version="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"android:layout_width="match_parent" android:layout_height="match_parent"> <TableLayout android:id="@+id/tableLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:stretchColumns="1"> <TableRow android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tvToday" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="日付"/> <TextView android:id="@+id/txtToday" android:layout_width="match_parent" android:layout_height="wrap_content"> <requestFocus/> </TextView> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tvWeight" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="体重"/> <EditText android:id="@+id/txtWeight" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal"/> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tvBodyfat" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="体脂肪"/> <EditText android:id="@+id/txtBodyfat" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal"/> </TableRow> </TableLayout> <Button android:id="@+id/btnUpdate" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="onUpdate" android:text="更新"/> </LinearLayout>
calendar_cell
カレンダーセルのレイアウト
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/dateText" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAlignment="center"/> <!--ここに拡張可能--> <!--追加--> <TextView android:id="@+id/memoText" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:textAlignment="center"/> <TextView android:id="@+id/bmiText" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:textAlignment="center"/> </RelativeLayout>
activity_graph
体重グラフのレイアウト
<?xml version="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"android:layout_width="match_parent" android:layout_height="match_parent"> <com.github.mikephil.charting.charts.LineChart android:id="@+id/lineChart" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
activity_graph
カラーファイル
<?xml version="1.0"encoding="utf-8"?> <resources> <colorname="purple_200">#FFBB86FC</color> <colorname="purple_500">#FF6200EE</color> <colorname="purple_700">#FF3700B3</color> <colorname="teal_200">#FF03DAC5</color> <colorname="teal_700">#FF018786</color> <colorname="black">#FF000000</color> <colorname="white">#FFFFFFFF</color> <colorname="colorPrimary">#3F51B5</color> <colorname="colorPrimaryDark">#303F9F</color> <colorname="colorAccent">#FF4081</color> <colorname="grayColor">#777</color> <colorname="blueColor">#00F</color> <colorname="redColor">#F00</color> <colorname="whiteColor">#FFF</color> <colorname="blackColor">#000</color> </resources>