Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

Android 自定义日历控件

$
0
0

这里写图片描述
跟着强哥的这篇文章顺便学习了一下:Android Studio 上传 Library 至 Jcenter 生成依赖的两种方式
http://blog.csdn.net/lv_fq/article/details/72567208然后把自己自定义的控件传到jcenter上了强哥的文章总结的还是很好的。
这里写图片描述

compile 'com.danfeng:CalendarView:1.0.1'

思路

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


2、日历中当天的日期被圈出,因此自定义了一个TextView并在其ondraw方法中通过canvas进行绘制。
这里写图片描述
3、上月、下月、当月日期的显示
上下月
这里写图片描述
由于日期是通过gridview布局因此也要给gridview设置adapter并填充日期。(这里显示的包含上月跟下月的日期,对非本月日期文字颜色不同,对当天日期会被圈出。一般情况下都是5*7行就可以足够显示本月跟非半月日期,但是当1号恰好是周六的时候,显示就需要6*7行了,也因此我我们需要判断这个月的1号是星期几,算出多余了上月几天)
这里写图片描述
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 onCalendarItemClick(Date date);
    }

}

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 today) {
        isToday = today;
    }
}

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>
作者:danfengw 发表于2017/5/26 14:00:56 原文链接
阅读:65 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles