Android 自定义日历控件_自定义


跟着强哥的这篇文章顺便学习了一下:Android Studio 上传 Library 至 Jcenter 生成依赖的两种方式

然后把自己自定义的控件传到jcenter上了强哥的文章总结的还是很好的。

Android 自定义日历控件_自定义_02

compile 'com.danfeng:CalendarView:1.0.1'

思路

先来理一下自定义日历控件的思路:
1、自定义日历通过继承LinearLayout,添加布局进行实现的,布局主要由常见的控件RelativeLayout、GridView组成。比如

Android 自定义日历控件_ico_03


2、日历中当天的日期被圈出,因此自定义了一个TextView并在其ondraw方法中通过canvas进行绘制。

Android 自定义日历控件_ico_04


3、上月、下月、当月日期的显示

上下月

Android 自定义日历控件_ide_05


由于日期是通过gridview布局因此也要给gridview设置adapter并填充日期。(这里显示的包含上月跟下月的日期,对非本月日期文字颜色不同,对当天日期会被圈出。一般情况下都是5*7行就可以足够显示本月跟非半月日期,但是当1号恰好是周六的时候,显示就需要6*7行了,也因此我我们需要判断这个月的1号是星期几,算出多余了上月几天)

Android 自定义日历控件_自定义_06


4、此外设置了一系列自定义属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyCalendar">
<attr name="dateformat" format="string"></attr>
<attr name="titleSize" format="dimension"></attr>
<attr name="titleColor" format="color"></attr>
<attr name="goIcon" format="reference"></attr>
<attr name="preIcon" format="reference"></attr>
<attr name="dayInMonthColor" format="color"></attr>
<attr name="dayOutMonthcolor" format="color"></attr>
<attr name="todayColor" format="color"></attr>
<attr name="todayEmptycircleColor" format="color"></attr>
<attr name="todayFillcircleColor" format="color"></attr>
<attr name="calendarbackground" format="color|reference"></attr>
</declare-styleable>
</resources>

代码

1、自定义calendar

public class MyCalendar extends LinearLayout {
private ImageButton btnPre;
private ImageButton btnGo;
private TextView tvMonth;
private GridView gridDate;
private Calendar curDate= Calendar.getInstance();
private String displayformat;
private CalendarAdapter adapter;

//相关属性
private int titleColor;
private int titleSize;
private int goIcon;
private int preIcon;
private int dayInMonthColor;
private int dayOutMonthColor;
private int todayColor;
private int todayEmptyColor;
private int todayFillColor;

public MyCalendar(Context context) {
this(context,null);
}

public MyCalendar(Context context, AttributeSet attrs) {
this(context, attrs,0);
}


public MyCalendar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.MyCalendar);
//设置标题栏年月文本的显示格式
displayformat=ta.getString(R.styleable.MyCalendar_dateformat);
if (displayformat==null){
displayformat="yyyy MMM";
}
titleColor=ta.getColor(R.styleable.MyCalendar_titleColor,Color.RED);
titleSize= (int) ta.getDimension(R.styleable.MyCalendar_titleSize,18);
goIcon=ta.getResourceId(R.styleable.MyCalendar_goIcon,R.mipmap.go);
preIcon=ta.getResourceId(R.styleable.MyCalendar_preIcon,R.mipmap.pre);
dayInMonthColor=ta.getColor(R.styleable.MyCalendar_dayInMonthColor,Color.BLACK);
dayOutMonthColor=ta.getColor(R.styleable.MyCalendar_dayOutMonthcolor,Color.GRAY);
todayColor=ta.getColor(R.styleable.MyCalendar_todayColor,Color.BLUE);
todayEmptyColor=ta.getColor(R.styleable.MyCalendar_todayEmptycircleColor,Color.CYAN);
todayFillColor=ta.getColor(R.styleable.MyCalendar_todayFillcircleColor,Color.CYAN);
ta.recycle();
init(context);
}

private void init(Context context){
bindView(context);
bindEvent();

}
private void bindView(Context context) {
View view=LayoutInflater.from(context).inflate(R.layout.calendar_view,this,false);
btnPre= (ImageButton) view.findViewById(R.id.btnpre);
btnPre.setImageResource(preIcon);
btnGo= (ImageButton) view.findViewById(R.id.btngo);
btnGo.setImageResource(goIcon);
tvMonth= (TextView) view.findViewById(R.id.tvmonth);
tvMonth.setTextColor(titleColor);
tvMonth.setTextSize(titleSize);
gridDate= (GridView) view.findViewById(R.id.calendar_grid);
addView(view);

}

private void bindEvent() {
btnPre.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//往前移动一个月份
curDate.add(Calendar.MONTH,-1);
//设置当月数据
renderCalendar();
}
});
btnGo.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//往后移动一个月份
curDate.add(Calendar.MONTH,1);
renderCalendar();
}
});
renderCalendar();
}

private void renderCalendar() {
SimpleDateFormat simpleformat=new SimpleDateFormat(displayformat);
tvMonth.setText(simpleformat.format(curDate.getTime()));
final ArrayList<Date> cells=new ArrayList<>();
Calendar calendar= (Calendar) curDate.clone();
//将日历设置到当月第一天
calendar.set(Calendar.DAY_OF_MONTH,1);
//获得当月第一天是星期几,如果是星期一则返回1此时1-1=0证明上个月没有多余天数
int prevDays=calendar.get(Calendar.DAY_OF_WEEK)-1;
//将calendar在1号的基础上向前推prevdays天。
calendar.add(Calendar.DAY_OF_MONTH,-prevDays);
//最大行数是6*7也就是,1号正好是星期六时的情况
int maxCellcount=6*7;
while(cells.size()<maxCellcount){
cells.add(calendar.getTime());
//日期后移一天
calendar.add(calendar.DAY_OF_MONTH,1);
}
adapter= new CalendarAdapter(getContext(),cells);
gridDate.setAdapter( adapter);
gridDate.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (myCalendarclickListener!=null){

myCalendarclickListener.onCalendarItemClick((Date) parent.getItemAtPosition(position));
((CalendarDayTextView)parent.getChildAt(position)).setSigned(true);
adapter.notifyDataSetChanged();
}
}
});
}


private class CalendarAdapter extends ArrayAdapter<Date>{
LayoutInflater layoutInflater;
public CalendarAdapter(Context context) {
this(context,null);
}

public CalendarAdapter(Context context, List<Date> objects) {
super(context, R.layout.calendar_text_day, objects);
layoutInflater=LayoutInflater.from(context);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
Date date=getItem(position);
if (convertView==null){
convertView=layoutInflater.inflate(R.layout.calendar_text_day,parent,false);
( (CalendarDayTextView) convertView).setEmptyColor(todayEmptyColor);
( (CalendarDayTextView) convertView).setFillColor(todayFillColor);

}
int day=date.getDate();
//设置文本
( (CalendarDayTextView) convertView).setText(String.valueOf(day));
Date now=new Date();
//设置颜色
if (now.getDate()==day&&now.getMonth()==date.getMonth()&&now.getYear()==date.getYear()){
( (CalendarDayTextView) convertView).setTextColor(todayColor);
(( CalendarDayTextView)convertView).setToday(true);
}else if (date.getMonth()==now.getMonth()){
( (CalendarDayTextView) convertView).setTextColor(dayInMonthColor);
}else {
( (CalendarDayTextView) convertView).setTextColor(dayOutMonthColor);
}

return convertView;
}
}


public void setOnCalendarClick(MyCalendarclickListener li){
myCalendarclickListener=li;
}
//日期点击事件接口回调
public MyCalendarclickListener myCalendarclickListener;
public interface MyCalendarclickListener{
void

2、自定义TextView标记今天

public class CalendarDayTextView extends TextView
public boolean isToday;
public boolean isSigned;

public void setEmptyColor(int emptyColor) {
this.emptyColor = emptyColor;
}

public void setFillColor(int fillColor) {
this.fillColor = fillColor;
}

private int emptyColor=Color.parseColor("#00ff00");
private int fillColor=Color.parseColor("#00ff00");

public boolean isSigned() {
return isSigned;
}

public void setSigned(boolean signed) {
isSigned = signed;
}

private Paint mPaint;
public CalendarDayTextView(Context context) {
super(context);
initview();
}

public CalendarDayTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initview();
}
private void initview(){
mPaint=new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.parseColor("#00ff00"));
mPaint.setStrokeWidth(2);
}

@Override
protected void onDraw(Canvas canvas) {
if (isToday){
if (isSigned){
//绘制实心圆
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(fillColor);
canvas.save();
//移动到当前控件的中心,以中心为圆点绘制实心圆
canvas.translate(getWidth()/2,getHeight()/2);
canvas.drawCircle(0,0,getWidth()/2-2,mPaint);
canvas.restore();
//此处必须将圆移动回开始位置,否则文本显示会受到影响
canvas.translate(0,0);
}else {
//绘制空心圆
mPaint.setColor(emptyColor);
canvas.save();
canvas.translate(getWidth()/2,getHeight()/2);
canvas.drawCircle(0,0,getWidth()/2-2,mPaint);
canvas.restore();
canvas.translate(0,0);
}

}
super.onDraw(canvas);
}

public boolean isToday() {
return isToday;
}

public void setToday(boolean

3、calendar_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginTop="8dp"
<ImageButton
android:id="@+id/btnpre"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@mipmap/pre"
android:background="@null"
android:layout_marginLeft="20dp"
android:layout_centerVertical="true"
<TextView
android:id="@+id/tvmonth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="五月"
android:textSize="24sp"
android:layout_centerInParent="true"
<ImageButton
android:id="@+id/btngo"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@mipmap/go"
android:background="@null"
android:layout_marginRight="20dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="30dp"
android:orientation="horizontal"
android:id="@+id/calendar_week_header"
android:layout_marginTop="5dp"
android:gravity="center_vertical"
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="星期日"
android:textSize="16sp"
android:textAlignment="center"
android:layout_gravity="center_vertical"
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="星期一"
android:textSize="16sp"
android:textAlignment="center"
android:layout_gravity="center_vertical"
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="星期二"
android:textSize="16sp"
android:textAlignment="center"
android:layout_gravity="center_vertical"
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="星期三"
android:textSize="16sp"
android:textAlignment="center"
android:layout_gravity="center_vertical"
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="星期四"
android:textSize="16sp"
android:layout_gravity="center_vertical"
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="星期五"
android:textSize="16sp"
android:textAlignment="center"
android:layout_gravity="center_vertical"
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="星期六"
android:textSize="16sp"
android:textAlignment="center"
android:layout_gravity="center_vertical"
</LinearLayout>
<GridView
android:id="@+id/calendar_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:numColumns="7"
android:gravity="center"
</GridView>
</LinearLayout>

4、calendar_text_day.xml

<?xml version="1.0" encoding="utf-8"?>
<com.danfeng.mycalendar.CalendarDayTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="30dp" android:layout_height="30dp"
android:textSize="18sp"
android:id="@+id/tv_calenadr_day"
android:gravity="center"
</com.danfeng.mycalendar.CalendarDayTextView>

使用

Activity

public class MainActivity extends AppCompatActivity
private MyCalendar mMyCalendar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMyCalendar= (MyCalendar) findViewById(R.id.mycalendar);
mMyCalendar.setOnCalendarClick(new MyCalendar.MyCalendarclickListener() {
@Override
public void onCalendarItemClick(Date date) {
SimpleDateFormat format=new SimpleDateFormat("yyyy年MM月dd日");
Toast.makeText(getApplicationContext(),"今天是"+format.format(date)+"签到成功",Toast.LENGTH_LONG).show();
}

});

}
}

xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"

<com.danfeng.mycalendar.MyCalendar
android:id="@+id/mycalendar"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:dateformat="MM yyyy"
app:titleColor="@color/colorAccent"
app:titleSize="18sp"
app:dayInMonthColor="#000000"
app:dayOutMonthcolor="#00A05f"
app:todayColor="#0fefef"
app:todayEmptycircleColor="#ffa0e0"
app:todayFillcircleColor="#ffa0e0"

</com.danfeng.mycalendar.MyCalendar>
</RelativeLayout>