On iOS, there are many ways to create a calendar using UICollectionView, but on Android, there aren't many ways to create a calendar using GridView, so it's a memo.
It is like this.
Let's create them in order.
Just define the colors to use in xml. Especially the calendar and GridView have nothing to do with it ...;
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="grayColor">#777</color>
<color name="blueColor">#00F</color>
<color name="redColor">#F00</color>
<color name="whiteColor">#FFF</color>
<color name="blackColor">#000</color>
</resources>
activity_main.xml
<?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="match_parent"
android:orientation="vertical"
android:background="@color/grayColor"
tools:context="jp.co.apps.workout.calendarsample.MainActivity">
<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="Day"
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="Month"
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="fire"
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="water"
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="wood"
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="Money"
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="soil"
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>
It's difficult to draw a border, so I'll color the background and draw a ruled line with a margin.
Since only the date is displayed this time, it may not be necessary to create a custom cell, but I will create it for future expansion.
calendar_cell.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/dateText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"/>
<!--Expandable here-->
</RelativeLayout>
Calendars often manipulate dates, so create a dedicated class.
DateManager.java
package jp.co.apps.workout.calendarsample;
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();
}
//Get the elements of the month
public List<Date> getDays(){
//Keep current state
Date startDate = mCalendar.getTime();
//Calculate the total number of squares to be displayed in GridView
int count = getWeeks() * 7 ;
//Calculate the number of days for the previous month displayed on the calendar for the current month
mCalendar.set(Calendar.DATE, 1);
int dayOfWeek = mCalendar.get(Calendar.DAY_OF_WEEK) - 1;
mCalendar.add(Calendar.DATE, -dayOfWeek);
List<Date> days = new ArrayList<>();
for (int i = 0; i < count; i ++){
days.add(mCalendar.getTime());
mCalendar.add(Calendar.DATE, 1);
}
//Restore state
mCalendar.setTime(startDate);
return days;
}
//Check if it is this month
public boolean isCurrentMonth(Date date){
SimpleDateFormat format = new SimpleDateFormat("yyyy.MM", Locale.US);
String currentMonth = format.format(mCalendar.getTime());
if (currentMonth.equals(format.format(date))){
return true;
}else {
return false;
}
}
//Get the number of weeks
public int getWeeks(){
return mCalendar.getActualMaximum(Calendar.WEEK_OF_MONTH);
}
//Get the day of the week
public int getDayOfWeek(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar.get(Calendar.DAY_OF_WEEK);
}
//To the next month
public void nextMonth(){
mCalendar.add(Calendar.MONTH, 1);
}
//To the previous month
public void prevMonth(){
mCalendar.add(Calendar.MONTH, -1);
}
}
This time, I also defined a method to change the month in the adapter class, and I'm wearing it a little sideways. Please pardon. .. ..
CalendarAdapter.java
package jp.co.apps.workout.calendarsample;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
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<Date> dateArray = new ArrayList();
private Context mContext;
private DateManager mDateManager;
private LayoutInflater mLayoutInflater;
//After expanding the custom cell, define Wiget here
private static class ViewHolder {
public TextView dateText;
}
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);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
//Specify cell size
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);
//Display only the date
SimpleDateFormat dateFormat = new SimpleDateFormat("d", Locale.US);
holder.dateText.setText(dateFormat.format(dateArray.get(position)));
//Gray out cells other than this month
if (mDateManager.isCurrentMonth(dateArray.get(position))){
convertView.setBackgroundColor(Color.WHITE);
}else {
convertView.setBackgroundColor(Color.LTGRAY);
}
//Sunday to red, Saturday to blue
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 0;
}
@Override
public Object getItem(int position) {
return null;
}
//Get display month
public String getTitle(){
SimpleDateFormat format = new SimpleDateFormat("yyyy.MM", Locale.US);
return format.format(mDateManager.mCalendar.getTime());
}
//Next month display
public void nextMonth(){
mDateManager.nextMonth();
dateArray = mDateManager.getDays();
this.notifyDataSetChanged();
}
//Previous month display
public void prevMonth(){
mDateManager.prevMonth();
dateArray = mDateManager.getDays();
this.notifyDataSetChanged();
}
}
MainActivity.java
package jp.co.apps.workout.calendarsample;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.GridView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
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());
}
}
This works all the way.
If you want to operate when you select a calendar, set setOnItemClickListener
in GridView and entangle around getItem
and getItemId
of CalendarAdapter.
Actually, it would be better to create a DateManager with MainActivity and pass it to the Adapter ... but this time. .. ..
Recommended Posts