Android仿IOS Dialog底部弹出月历式时间选择器
最近项目需求要写一个类IOS并且是月历样式的时间选择器,如图:
少废话,成品如下:
1. 思路
界面部分
<LinearLayout
<LinearLayout/>
<LinearLayout/>
<LinearLayout/>
<RecyclerView/>
/>
上面三个线性布局easy,下面的RecyclerView也很简单,只是,初学不太会用,花了点时间研究,主要是GridLayoutManager的几个参数、方法。
<android.support.v7.widget.RecyclerView
android:id="@+id/date_picker_recycler_view"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
注意到需求上面左右是没有边距的,所以只是加了上下的padding。
并且各个日期之间也是没有边距的所以item也很简单,
height没有设置成wrap_content完全是因为太高了,不好看。android:stateListAnimator="@null"
这句是为了取消Button点击产生的阴影,貌似API21以下还是有,待解决。
<?xml version="1.0" encoding="utf-8"?>
<Button
android:id="@+id/btn_date_item_date"
android:textColor="@color/monthForm_text"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@color/white"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:stateListAnimator="@null"/>
然后就是RecyclerView的设置了
RecyclerView的骚操作可以说完全就是靠LayoutManager完成的。
这里我们用到的是网页布局,直接贴代码。
recyclerView.setLayoutManager(new GridLayoutManager(context,7));
第一个参数context,第二个参数是列数,就完了。
如果要给item设置间距
如果要每个item之间有间距,我不知道高手是怎么实现的,我是通过给item设置margin实现的。
因为如果item宽度是wrap_content
,假如列数为7,recyclerView它会根据屏幕宽度把item的宽度设置为屏幕宽度的1/7,假如是定宽,那就排不了了,要么一行好多个要么一行几个,是吧,假如屏幕1000px,你一个item占了500px,它不能给你缩小吧。
但是这样设置出来的效果是这样的| #1##2##3##4##5##6##7#|
那,假如想各个item间隔均匀怎么办?就是|#1#2#3#4#5#6#7#|这样的效果
还在修炼中,淘宝是这样的,据说开源了,有空去看看。
逻辑部分
思路
-
顶部时间
这个简单,选中后将选中的时间显示上去即可;
需求:需要recyclerView记住选中位置的年、月、日(selectedYear、selectedMonth、selectedDay) -
菜单栏
-
左箭头,上一月
逻辑与右键头类似,参考右键头 -
中间显示当前年、月
这个也简单,左右箭头翻页时动态改变当前展示的年、月
需求:需要recyclerView记住当前展示的年、月(requestYear、requestMonth) -
右键头,下一月
这里通过Calendar类获取时间,通过roll方法设置需要显示的时间。
类初始化时设置一个全局变量Calendar now = Calendar.getInstance();
然后是点击右键头的代码(month+1是因为Calendar类获得月份范围是0-11)
if(now.get(Calendar.MONTH)==11){ now.roll(Calendar.YEAR,1); } now.roll(Calendar.MONTH,1); int year = now.get(Calendar.YEAR); int month = now.get(Calendar.MONTH)+1; tv_year_month.setText(context.getString(R.string.date_picker_year_month,year,month)); myAdapter.setRequestYear(year); myAdapter.setRequestMonth(month); initData(); myAdapter.notifyDataSetChanged();
-
-
日历主体
看起来难做起来容易,首先获得当前年、月、日;
然后now.set(Calendar.DATE,1); //设置为当月第一天 firstWeekday = now.get(Calendar.DAY_OF_WEEK); //获取第一天星期几,假如是2,就是星期一 now.roll(Calendar.DATE,-1); //这个月第一天倒退一天 dayCount =now.get(Calendar.DATE); //获取这个月总天数 ```
然后新建一个List<Integer>
数组;
先填入firstWeekday-1
个-1,再依次填入1、2、…到dayCount
;
然后recyclerView
新建适配器,设置一列显示7个
int thisDay = list.get(position); //当前遍历的日期
if(lthisDay>0){ //如果不是-1
item.setText(String.valueOf(thisDay)); //设置item显示值为这个日期,注意要转String
if(thisDay<CurrentDay&& requestMonth <= currentMonth && requestYear <= currentYear){ //如果这一天在今天之前,显示灰色
item.setTextColor(xxx);
}else{
item.setTextColor(xxx);显示黑色
item.setOnClickListener(xxx);设置点击事件
}
}