本文出自简书:尧沐,如需转载请标明出处,尊重原创谢谢
博客地址://www.greatytc.com/p/6f40fb8d64e6
自定义View学习很久了,一直想写点什么巩固一下自己,从最简单的自定一个日历开始吧
组合控件就是用系统已经封装好的东西然后加以组合形成一个我们需要的东西,相对于各种画出来的简单很多很多。由易到难
首先我们看一下日历-没错这就是win10自带的 注意看红色字体,是每个地方的组成,这么一看是不是简单很多很多
接下来写布局- -写布局注意几点 不要嵌套很深,这样解析会慢(最近看书学的优化~ ~)
说实在的很不想写布局这种东西 麻烦的一逼 你就当我写好了吧- -
因为是组合控件 所以就不是继承VIew 而是一个布局 我这里继承线性布局
然后实现三个构造方法
@RequiresApi(api = Build.VERSION_CODES.N)
public DataView(Context context) {
super(context);
initFindIdAndLinsen(context);
}
@RequiresApi(api = Build.VERSION_CODES.N)
public DataView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initFindIdAndLinsen(context);
}
@RequiresApi(api = Build.VERSION_CODES.N)
public DataView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initFindIdAndLinsen(context);
}
initFindIdAndLinsen 这个方法是绑定控件以及设置监听
里面的代码很简单
@RequiresApi(api = Build.VERSION_CODES.N)
private void initFindIdAndLinsen(final Context context) {
LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.view_calendar, this);
mWeekUp = (ImageView) findViewById(R.id.week_up);
mWeeknExt = (ImageView) findViewById(R.id.weekn_ext);
mWeekToday = (TextView) findViewById(R.id.week_today);
mWeekRecy = (RecyclerView) findViewById(R.id.week_recy);
renderCalender(context);
mWeekUp.setOnClickListener(new OnClickListener() {
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void onClick(View v) {
calendata.add(Calendar.MONTH, -1);
renderCalender(context);
}
});
mWeeknExt.setOnClickListener(new OnClickListener() {
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void onClick(View v) {
calendata.add(Calendar.MONTH, 1);
renderCalender(context);
}
});
}
这些都没什么好说的对吧,其实难点就一个 就是日期的计算
注意看,我这个月的第一天是1号 他在星期日的位置 主要就是这个的计算,这个要怎么算呢
/**
* 渲染界面
*
* @param context
*/
@RequiresApi(api = Build.VERSION_CODES.N)
private void renderCalender(Context context) {
/**
* 时间格式化
*/
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM yyyy");
mWeekToday.setText(simpleDateFormat.format(calendata.getTime()));
/**
* 为了不污染 本身的时间所以复制一个
*/
Calendar calendarOne = (Calendar) calendata.clone();
List<Date> mDate = new ArrayList<>();
/**
* 把日期放在第一天 然后看最后一个周末剩下几天 然后位移
*/
calendarOne.set(Calendar.DAY_OF_MONTH, 1);
calendarOne.add(Calendar.DAY_OF_MONTH, - calendarOne.get(Calendar.DAY_OF_WEEK) - 1);
/**
* 装数据进去
*/
while (mDate.size() < 42) {
mDate.add(calendarOne.getTime());
calendarOne.add(Calendar.DAY_OF_MONTH, 1);
}
/**
* recylerview的Adapert总会把- -
*/
DataViewAdapter dataViewAdapter = new DataViewAdapter(R.layout.item_data, mDate);
mWeekRecy.setAdapter(dataViewAdapter);
GridLayoutManager gridLayoutManager = new GridLayoutManager(context, 7);
mWeekRecy.setLayoutManager(gridLayoutManager);
}
这样这个控件就好了,难的地方就在怎么算日期上面 - -