1.思路:
日历内容我用了一个GridView装,实现的界面效果如下:
1.1分析:
1.1.1. 界面内容从上到下依次为:显示当前页面展示的年月;跳转到上一个月或者下一个月的按钮;周期标题头;数据内容(即当前展示的月份所有日期,以及上一个月和下一个月的几个日期)。
1.1.2. 数据内容部分我使用了一个GridView来实现,其余部分均为Button和TextView,因此最重要部分就是实现数据部分。
1.1.3. 数据内容部分分为三大块:1.上一个月的最后几天,2.本月的所有日期,3.下一个月的前几天。
1.1.4. 获得这三大块的数据,然后渲染在GridView上。
1.1.5. 将获得数据然后渲染在页面上写成一个方法,将当前年月的日期作为参数传进去,实现点击上一个月或下一个月按跳转日期页面。
2.步骤详情:
2.1.步骤一:
创建布局文件。以下是布局文件的代码:
<?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:gravity="center_horizontal" tools:context=".calendar.Calendar2Activity"> <TextView android:id="@+id/calendar_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="2020-10-1"/> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/calendar_last" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="上一个月"/> <Button android:id="@+id/calendar_next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="下一个月"/> LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:gravity="center" android:text="周一" android:background="@drawable/bg_white_black_border_yuanjiao"/> <TextView android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:gravity="center" android:text="周二" android:background="@drawable/bg_white_black_border_yuanjiao"/> <TextView android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:gravity="center" android:text="周三" android:background="@drawable/bg_white_black_border_yuanjiao"/> <TextView android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:gravity="center" android:text="周四" android:background="@drawable/bg_white_black_border_yuanjiao"/> <TextView android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:gravity="center" android:text="周五" android:background="@drawable/bg_white_black_border_yuanjiao"/> <TextView android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:gravity="center" android:text="周六" android:background="@drawable/bg_white_black_border_yuanjiao"/> <TextView android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:gravity="center" android:text="周日" android:background="@drawable/bg_white_black_border_yuanjiao"/> LinearLayout> <GridView android:id="@+id/calendar_gridview" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:numColumns="7"/>LinearLayout>
预览界面如下:
2.2.步骤二:
获得数据并将其渲染到GridView上。
数据分为下图标出的三部分:
蓝色部分为当前显示年月的一个月的所有日期,因此,我们需要获取当前显示的月份有多少天。代码如下:
Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.YEAR,year); calendar.set(Calendar.MONTH,month-1); calendar.set(Calendar.DATE,1);//把日期设置为当月第一天 calendar.roll(Calendar.DATE,-1);//日期回滚一天,也就最后一天 int date = calendar.get(Calendar.DATE);
红色部分为上一个月的最后几天,因此,我们需要得到上一个月的最后一天是几号,也就是上一个月的总天数(因为每个月的第一天都是1号,所以每个月的最后一天的号数就等于这个月的总天数),因此我将上面的求某个月份的天数的代码写成了一个方法,如下:
//获取输入月份的总天数 private int getMonthNum(int year,int month){ Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.YEAR,year); calendar.set(Calendar.MONTH,month-1); calendar.set(Calendar.DATE,1);//把日期设置为当月第一天 calendar.roll(Calendar.DATE,-1);//日期回滚一天,也就最后一天 return calendar.get(Calendar.DATE); }
先将红色和蓝色部分的数据放好,最后剩余几个格子就从1开始依次递增放入。
注意:当前月份1号是星期天,且这个月有30天或31天的天数则总共GridView有6行,即总共有42个格子,(例如2020年11月)。
在这里你可以直接将所有的月份的格子都规定成42个,也可以在当前月份的最后一天超出35个格子(即5行)的时候换成42个格子。在这里我就让它在超出35个格子的时候再换成42个格子。
这里我们要抓住零界点,也就是上一个月的最后一天到本月第一天和本月最后一天到下一个月的第一天。
由于我写的周期是从周一到周日,因此要先获取本月的第一天是周几,就能获得本月第一天的下标位置。获得当天是周几的代码如下(同样我将它写成了一个方法,方便多次使用),上一个月的总天数用变量lastdates表示,本月总天数用变量dates表示:
private int getWeek(String date){ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Calendar calendar = Calendar.getInstance(); try { calendar.setTime(format.parse(date)); } catch (ParseException e) { e.printStackTrace(); } //1:周日,7:周六 return calendar.get(Calendar.DAY_OF_WEEK); }
getWeek()方法返回的的周期数为:1,2,3,4,5,6,7,分别对应:周日,周一,周二,周三,周四,周五,周六;
但是我们需要让它的对应关系为:1,2,...,7,分别对应:周一,周二,...,周日。因此我们需要对获得到的周期数进行处理,代码如下:
//获取当前月份1号是周几 int week = getweek(today); if (week == 1) { week = 7;//周日 } else week = week - 1;
接下来就是重点了:获得三个部分的数据集合,直接放代码:
int num = week+dates-1;//当下标从1开始,num为输入月份的最后一个值的下标 if (num > 35){ gridview_size = 42; }else gridview_size = 35; int j = 1, a = 1; //当前月份的各个日期以及下一个月的日期 int last = lastdates - (week - 2);//第一个单元格的值 for (int i = 1; i <= gridview_size; i++) { if (i < week) {//上月剩余 dataList.add(last); last++; } else if (i <= num) { dataList.add(j);//本月 j++; } else { dataList.add(a);//下月 a++; } }
dataList为放三个部分的数据的整数型集合,即:
List dataList = new ArrayList<>();
我将下标从1开始
int num = week+dates-1,num为本月最后一天的下标,等于周期数(第一天的下标)+本月总天数-1
int last = lastdates - (week - 2);last为第一个格子的值,lastdates为上一个月的最后一天的号数,用最后一天的号数减去最后一天所在格子的前面的总格子数(最后一天的格子不算在内),就等于第一个格子内的值,比如数据:__,23,24,25,26;26数字前面有4个数,所以:26-4=22,所得的22就是横线处的值。
2.3.步骤三:
将获得的dataList渲染到GridView上。
3.所有代码(代码分为两部分:布局文件代码和Java代码):
1.布局文件的代码如上述的布局代码。
2.Java代码部分如下:
public class CalendarActivity extends AppCompatActivity implements View.OnClickListener { private Button calendar_last; private Button calendar_next; private GridView calendar_gridview; private List dataList = new ArrayList<>(); private String today; private TextView calendar_date; private int week,dates; private MyAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_calendar); initView(); //获取当前月份 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM"); Date date = new Date(System.currentTimeMillis()); today = simpleDateFormat.format(date); getData(today); } private void getData(String today) { calendar_date.setText(today); today = today + "-01"; String years = today.split("-")[0]; String months = today.split("-")[1]; Log.i("日历", months); //获取当前月份日期数 dates = getmoth(Integer.parseInt(years), Integer.parseInt(months)); //获取当前月份1号是周几 week = getweek(today); if (week == 1) { week = 7;//周日 } else week = week - 1; //获取上一个月份的天数 int lastdates; if (Integer.parseInt(months) == 1) { lastdates = getmoth(Integer.parseInt(years) - 1, 12); } else { lastdates = getmoth(Integer.parseInt(years), Integer.parseInt(months) - 1); } //获取当前展示的日历界面的数据 int num = week+dates-1;//当下标从1开始,num为输入月份的最后一个值的下标 int gridview_size; if (num > 35){ gridview_size = 42; }else gridview_size = 35; int j = 1, a = 1; //当前月份的各个日期以及下一个月的日期 int last = lastdates - (week - 2);//第一个单元格的值 for (int i = 1; i <= gridview_size; i++) { if (i < week) {//上月剩余 dataList.add(last); last++; } else if (i <= num) { dataList.add(j);//本月 j++; } else { dataList.add(a);//下月 a++; } } //渲染数据 if (adapter == null){ adapter = new MyAdapter(CalendarActivity.this, dataList); calendar_gridview.setAdapter(adapter); }else adapter.notifyDataSetChanged(); } private int getmoth(int year, int month) { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.YEAR, year); calendar.set(Calendar.MONTH, month - 1); calendar.set(Calendar.DATE, 1); calendar.roll(Calendar.DATE, -1); int date = calendar.get(Calendar.DATE); return date; } private int getweek(String date) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); Calendar calendar = Calendar.getInstance(); try { calendar.setTime(simpleDateFormat.parse(date)); } catch (ParseException e) { e.printStackTrace(); } //1:周日,7:周六 return calendar.get(Calendar.DAY_OF_WEEK); } private void initView() { calendar_last = (Button) findViewById(R.id.calendar_last); calendar_next = (Button) findViewById(R.id.calendar_next); calendar_gridview = (GridView) findViewById(R.id.calendar_gridview); calendar_last.setOnClickListener(this); calendar_next.setOnClickListener(this); calendar_date = (TextView) findViewById(R.id.calendar_date); calendar_date.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.calendar_last: //上一个月按钮的点击事件 dataList.clear(); int years = Integer.parseInt(today.split("-")[0]); int months = Integer.parseInt(today.split("-")[1]); if (months == 1) { months = 12; years = years - 1; getData(years + "-" + months); today = years + "-" + months; } else { months = months - 1; getData(years + "-" + months); today = years + "-" + months; } break; case R.id.calendar_next: //下一个月按钮的点击事件 dataList.clear(); int years1 = Integer.parseInt(today.split("-")[0]); int months1 = Integer.parseInt(today.split("-")[1]); if (months1 == 12) { months1 = 1; years1 = years1 + 1; getData(years1 + "-" + months1); today = years1 + "-" + months1; } else { months1 = months1 + 1; getData(years1 + "-" + months1); today = years1 + "-" + months1; } break; } } class MyAdapter extends BaseAdapter { private Context context; private List list; public MyAdapter(Context context, List list) { this.context = context; this.list = list; } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.calendar_gridview_item, null, false); } final TextView textView = (TextView) convertView.findViewById(R.id.calendar_gridview_item_tv); textView.setText(list.get(position) + ""); //设置本月的日期高亮显示,非本月的日期灰色显示 if (position >= week-1 && position < week+dates-1){//判断是当月的日期 textView.setTextColor(Color.BLACK);//黑色 }else textView.setTextColor(Color.GRAY);//灰色 return convertView; } }}
到这里就结束啦.