不多说,先上图,第一次录屏,剪切的有点烂,将就看
正文开始
1.先看布局图
我们可以清晰的看到视图的结构
1.头部两个TextView,左边是日期,右边是星期
2.下方三个ListView ,每个ListView中间有个选择指示的圆
下面是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"
android:orientation="vertical"
android:background="@color/black"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_margin="30dp"
android:background="@drawable/shape_all_round"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_marginTop="15dp"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/show_title_year_month_day"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/show_title_week"
android:layout_marginLeft="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="200dp">
<RelativeLayout
android:layout_margin="10dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent">
<ListView
android:id="@+id/list_view_year"
android:divider="@null"
android:scrollbars="none"
android:listSelector="@color/color_null"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:background="@drawable/shap_calendar_list_btm_plastic"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
app:srcCompat="@drawable/ic_round"
android:layout_centerInParent="true"
android:layout_width="80dp"
android:layout_height="80dp" />
</RelativeLayout>
<RelativeLayout
android:layout_margin="10dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent">
<ListView
android:id="@+id/list_view_month"
android:divider="@null"
android:scrollbars="none"
android:listSelector="@color/color_null"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:background="@drawable/shap_calendar_list_btm_plastic"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
app:srcCompat="@drawable/ic_round"
android:layout_centerInParent="true"
android:layout_width="80dp"
android:layout_height="80dp" />
</RelativeLayout>
<RelativeLayout
android:layout_margin="10dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent">
<ListView
android:id="@+id/list_view_day"
android:divider="@null"
android:scrollbars="none"
android:listSelector="@color/color_null"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:background="@drawable/shap_calendar_list_btm_plastic"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
app:srcCompat="@drawable/ic_round"
android:layout_centerInParent="true"
android:layout_width="80dp"
android:layout_height="80dp" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
上面的圆形图片用的是svg格式的矢量图,不会用svg的小伙伴,可以将图片替换为png的图片,把app:srcCompat 改成 android:src就行了
shap_calendar_list_btm_plastic.xml 这就是做一个毛玻璃的效果,从上下开始到中间,透明度逐渐变高,就能显示出类似滚轮的效果来,下面贴出代码,顺便把color的代码一起贴出来
布局文件的背景
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white"/>
<corners android:radius="15dp"/>
</shape>
这是shap_calendar_list_btm_plastic.xml的
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="90"
android:startColor="@color/white_btm_f"
android:centerColor="@color/white_btm_0"
android:endColor="@color/white_btm_f"/>
</shape>
这是color的
<color name="white_btm_0">#00ffffff</color>
<color name="white_btm_1">#11ffffff</color>
<color name="white_btm_2">#22ffffff</color>
<color name="white_btm_3">#33ffffff</color>
<color name="white_btm_4">#44ffffff</color>
<color name="white_btm_5">#55ffffff</color>
<color name="white_btm_6">#66ffffff</color>
<color name="white_btm_7">#77ffffff</color>
<color name="white_btm_8">#88ffffff</color>
<color name="white_btm_9">#99ffffff</color>
<color name="white_btm_a">#aaffffff</color>
<color name="white_btm_b">#bbffffff</color>
<color name="white_btm_c">#ccffffff</color>
<color name="white_btm_d">#ddffffff</color>
<color name="white_btm_e">#eeffffff</color>
<color name="white_btm_f">#ffffffff</color>
2.java代码部分
适配器
/**
* 适配器
* Created by zcy on 2017/8/2.
*/
public class CalendarListAdapter extends BaseAdapter {
private Context mContext;
private List<Integer> list;
//listView中显示的item个数
private int count;
//最小个数,如果count比这个值小,将会默认使用MIN_COUNT
private static final int MIN_COUNT = 3;
public static final int TYPE_YEAR = 10;//年
public static final int TYPE_MONTH = 11;//月
public static final int TYPE_DAY = 12;//日
private int type;
public CalendarListAdapter(Context mContext, List<Integer> list , int count , int type) {
this.mContext = mContext;
this.list = list;
this.count = count;
this.type = type;
}
public CalendarListAdapter(Context mContext) {
this.mContext = mContext;
}
@Override
public int getCount() {
return null == list ? 0 : list.size();
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
int height = viewGroup.getHeight();
TextView textView = new TextView(mContext);
textView.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
textView.setHeight(count < MIN_COUNT ? height/MIN_COUNT : height/count);
textView.setGravity(Gravity.CENTER);
textView.setText(list.get(i) < 0 ? "" :new StringBuilder().append(list.get(i)).append(getTypeName()));
return textView;
}
private String getTypeName(){
String name = null;
switch (type){
case TYPE_YEAR:
name = "年";
break;
case TYPE_MONTH:
name = "月";
break;
case TYPE_DAY:
name = "日";
break;
default:
name = "";
break;
}
return name;
}
}
实现代码
/**
* 日历fragment
* Created by zcy on 2017/8/2.
*/
public class CalendarFragment extends BaseFragment {
public static CalendarFragment getInstance(){
return new CalendarFragment();
}
// 年月日 , 星期几
@BindView(R.id.show_title_year_month_day)
TextView titleYMD;
@BindView(R.id.show_title_week) TextView titleNeek;
//年份选择 , 月份选择 ,天数选择
@BindView(R.id.list_view_year)
ListView listViewYear;
@BindView(R.id.list_view_month) ListView listViewMonth;
@BindView(R.id.list_view_day) ListView listViewDay;
//年份listView中显示的第一个item编号
private int firstVisibleYearItem;
//月份listView中显示的第一个item编号
private int firstVisibleMonthItem;
//天数listView中显示的第一个item编号
private int firstVisibleDayItem;
private List<Integer> listYear;
private List<Integer> listMonth;
private List<Integer> listDay;
//初始年份和结束年份
private int firstYear;
private int lastYear;
//年月日的适配器
private CalendarListAdapter yearAdapter;
private CalendarListAdapter monthAdapter;
private CalendarListAdapter daydApter;
//日历对象
private Calendar calendar;
//当前时间,年,月,日,周
private int currentTimeYear;
private int currentTimeMonth;
private int currentTimeDay;
@Override
protected int getLayoutId() {
return R.layout.fragment_calendar;
}
@Override
protected void initViews() {
initYearListView();
initMonthListView();
initDayListView();
listViewYear.setSelection(listYear.indexOf(currentTimeYear)-1);
listViewMonth.setSelection(listMonth.indexOf(currentTimeMonth)-1);
listViewDay.setSelection(listDay.indexOf(currentTimeDay)-1);
upData(false);
}
@Override
protected void init() {
initYear();
initMonth();
calendar = Calendar.getInstance();
currentTimeYear = calendar.get(Calendar.YEAR);
currentTimeMonth = calendar.get(Calendar.MONTH)+1;
currentTimeDay = calendar.get(Calendar.DAY_OF_MONTH);
upData(false);
}
//初始化天数的listView
private void initDayListView() {
daydApter = new CalendarListAdapter(getContext() , listDay , 0 , CalendarListAdapter.TYPE_DAY);
listViewDay.setAdapter(daydApter);
listViewDay.setSelected(true);
listViewDay.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int i) {
if (i == SCROLL_STATE_IDLE){
listViewDay.setSelection(firstVisibleDayItem);
calendar.set(Calendar.DAY_OF_MONTH ,listDay.get(firstVisibleDayItem+1));
upData(false);
}
}
@Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {
firstVisibleDayItem = i;
}
});
}
//初始化月份的listView
private void initMonthListView() {
monthAdapter = new CalendarListAdapter(getContext() , listMonth , 0 , CalendarListAdapter.TYPE_MONTH);
listViewMonth.setAdapter(monthAdapter);
listViewMonth.setSelected(true);
listViewMonth.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int i) {
if (i == SCROLL_STATE_IDLE){
listViewMonth.setSelection(firstVisibleMonthItem);
// upDayList();
calendar.set(Calendar.DAY_OF_MONTH , 1);
calendar.set(Calendar.MONTH , listMonth.get(firstVisibleMonthItem+1)-1);
upData(true);
}
}
@Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {
firstVisibleMonthItem = i;
}
});
}
//初始化年份的listView
private void initYearListView() {
yearAdapter = new CalendarListAdapter(getContext() , listYear , 0 , CalendarListAdapter.TYPE_YEAR);
listViewYear.setAdapter(yearAdapter);
listViewYear.setSelected(true);
listViewYear.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int i) {
if (i == SCROLL_STATE_IDLE){
listViewYear.setSelection(firstVisibleYearItem);
// upDayList();
calendar.set(Calendar.DAY_OF_MONTH , 1);
calendar.set(Calendar.YEAR , listYear.get(firstVisibleYearItem + 1));
upData(true);
}
}
@Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {
//此处i代表屏幕中显示的第一个item
firstVisibleYearItem = i;
}
});
}
/**
* 有任何动作之后刷新数据和界面
* @param isNotify 是否对天数的适配器进行刷新
*/
private void upData(boolean isNotify){
initDay();
if (isNotify && null != daydApter){
daydApter.notifyDataSetChanged();
//这里须要在刷新之后将selection设置为0,否则在31号的时候调整月份,会出现显示异常的情况
listViewDay.setSelection(0);
}
if (null != calendar){
if (null != titleYMD)titleYMD.setText(getYMD());
if (null != titleNeek)titleNeek.setText(getNeek());
}
}
//从Calendar中取出年月日并拼接成想要的格式
private String getYMD(){
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
StringBuilder sb = new StringBuilder();
if (year >= 1900){
sb.append(year).append("年");
if (month >= 0 && month <12){
sb.append(month+1).append("月")
.append(day);
}
}
return sb.toString();
}
//从Calendar中取出星期数,并返回对应的名称
private String getNeek(){
int dayOfNeek = calendar.get(Calendar.DAY_OF_WEEK);
String neek = null;
switch (dayOfNeek){
case 1:
neek = "星期日";
break;
case 2:
neek = "星期一";
break;
case 3:
neek = "星期二";
break;
case 4:
neek = "星期三";
break;
case 5:
neek = "星期四";
break;
case 6:
neek = "星期五";
break;
case 7:
neek = "星期六";
break;
default:
neek = "";
break;
}
return neek;
}
//初始化天数list数据
private void initDay(){
//指定年份指定月份有多少天
int actualMaximum = calendar.getActualMaximum(Calendar.DATE);
if (null == listDay)listDay = new ArrayList<>();
else listDay.clear();
listDay.add(-1);
for (int i = 1 ; i <= actualMaximum ; i++){
listDay.add(i);
}
listDay.add(-1);
}
//初始化年份相关
private void initYear() {
firstYear = 2000;
lastYear = 2017;
if (null == listYear) listYear = new ArrayList<>();
else listYear.clear();
listYear.add(-1);
for (int i = firstYear ; i <= lastYear ; i++){
listYear.add(i);
}
listYear.add(-1);
}
//初始化月份
private void initMonth(){
if (null == listMonth) listMonth = new ArrayList<>();
else listMonth.clear();
listMonth.add(-1);
for (int i = 0 ; i < 12 ; i++){
listMonth.add(i+1);
}
listMonth.add(-1);
}
}
这里我将逻辑全写在Fragment里面了,哪里需要用的时候,直接加载这个fragment就行了,还有个BaseFragment,也贴个代码吧
/**
* baseFragment
* Created by zcy on 2017/8/2.
*/
public abstract class BaseFragment extends Fragment{
/**
* 这个方法提供初始化的布局id
* @return 布局id
*/
protected abstract int getLayoutId();
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(getLayoutId(),container,false);
ButterKnife.bind(this,view);
initViews();
return view;
}
/**
* 初始化视图控件,代替了onCreateView,不需要再重写onCreateView在该方法里面写具体实现就可以了
*/
protected abstract void initViews();
/**
* 初始化成员属性,不需要手动调用,只需要重写内容即可
*/
protected abstract void init();
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
}
有点乱,也不是很复杂,需要用到的可以自己整理一下;基本全局就对一个Calendar对象操作,然后在合适的地方刷新页面就行了;还有疑问的小伙伴可以私信我