天天看点

Android 自定义实现日历控件

惯例:先上图后说话,谢谢各位伙伴的支持! 有你们是我的福分!

Android 自定义实现日历控件
Android 自定义实现日历控件

每日一言:犹豫一千次不如实践一次。

你将学到以下知识点:

                继承系统控件

                组合系统控件

                自定义绘制

                添加Attribute

                添加事件

-------------代码来啦---------

一.自定义 NewCalender 日历

public class NewCalendar extends LinearLayout {
    private ImageView iv_left;
    private ImageView iv_Right;
    private TextView tv_Date;
    private GridView gridView;
    private Calendar curDate = Calendar.getInstance();
    private String displayFormat;
    public NewCalendarListener calendarListener;

    public NewCalendar(Context context) {
        super(context);
    }

    public NewCalendar(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initControl(context, attrs);
    }

    public NewCalendar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initControl(context, attrs);
    }

    private void initControl(Context context, AttributeSet attr) {
        bindControl(context);
        bindControlEvent();

        TypedArray ta = getContext().obtainStyledAttributes(attr, R.styleable.NewCalendar);
        try {
            String format = ta.getString(R.styleable.NewCalendar_dateFormat);
            displayFormat = format;
            if (displayFormat == null) {
                displayFormat = "MMM yyyy";
            }

        } finally {
            ta.recycle();
        }
        renderCalendar();
    }

    /**
     * 初始化控件
     *
     * @param context
     */
    private void bindControl(Context context) {
        LayoutInflater inflater = LayoutInflater.from(context);
        inflater.inflate(R.layout.calendar_view, this);
        iv_left = (ImageView) findViewById(R.id.btnPre);
        iv_Right = (ImageView) findViewById(R.id.btnNext);
        tv_Date = (TextView) findViewById(R.id.txtData);
        gridView = (GridView) findViewById(R.id.calendar_grid);
        gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
                if (calendarListener == null) {
                    return false;
                } else {
                    calendarListener.onItemLongPress((Date) adapterView.getItemAtPosition(i));
                    return  true;
                }
            }
        });
    }

    /**
     * 绑定事件
     */
    private void bindControlEvent() {
        iv_left.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                curDate.add(Calendar.MONTH, -1);
                renderCalendar();
            }
        });
        iv_Right.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                curDate.add(Calendar.MONTH, +1);
                renderCalendar();
            }
        });
    }

    /**
     * 渲染日历
     */
    private void renderCalendar() {
        //格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat(displayFormat);
        tv_Date.setText(sdf.format(curDate.getTime()));
        //总共多少个cell
        ArrayList<Date> cells = new ArrayList<>();
        //日历克隆
        Calendar calendar = (Calendar) curDate.clone();
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        int preDays = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        calendar.add(Calendar.DAY_OF_MONTH, -preDays);

        int maxCellCount = 6 * 7;
        while (cells.size() < maxCellCount) {
            cells.add(calendar.getTime());
            calendar.add(Calendar.DAY_OF_MONTH, 1);
        }
        gridView.setAdapter(new CalendarAdapter(getContext(), cells));
    }

    /**
     * 日历显示适配器
     */
    private class CalendarAdapter extends ArrayAdapter {
        LayoutInflater inflate;

        public CalendarAdapter(@NonNull Context context, ArrayList<Date> days) {
            super(context, R.layout.calendar_text_day, days);
            inflate = LayoutInflater.from(context);
        }

        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            Date date = (Date) getItem(position);
            if (convertView == null) {
                convertView = inflate.inflate(R.layout.calendar_text_day, parent, false);
            }
            int day = date.getDate();
            ((Calendar_day_textView) convertView).setText(String.valueOf(day));
            //是否是当月
            Date now = new Date();
            boolean isTheSameMonth = false;
            if (now.getMonth() == date.getMonth()) {
                isTheSameMonth = true;
            }

            if (isTheSameMonth) {
                ((Calendar_day_textView) convertView).setTextColor(Color.parseColor("#000000"));

            } else {
                ((Calendar_day_textView) convertView).setTextColor(Color.parseColor("#666666"));

            }

            if (now.getDate() == date.getDate() && now.getMonth() == date.getMonth() && now.getYear() == date.getYear()) {
                ((Calendar_day_textView) convertView).setTextColor(Color.parseColor("#ff0000"));
                ((Calendar_day_textView) convertView).isToday = true;
            }

            return convertView;
        }
    }

    public interface NewCalendarListener {
        void onItemLongPress(Date date);
    }

}      

二.自定义每个日期的控件 Calendar_day_textView

public class Calendar_day_textView extends AppCompatTextView {
    //是否是今天
    public boolean isToday = false;
    private Paint paint = new Paint();

    public Calendar_day_textView(Context context) {
        super(context);
    }

    public Calendar_day_textView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initControl();
    }

    public Calendar_day_textView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initControl();
    }

    /**
     * 除使用画笔
     */
    private void initControl() {
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.parseColor("#ff0000"));
        paint.setAntiAlias(true);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (isToday) {
            canvas.translate(getWidth() / 2, getHeight() / 2);
            canvas.drawCircle(0, 0, getWidth() / 2, paint);
        }

    }
}      

三.自定义布局需要显示的地方

<com.example.jiaxufei.firstgitproject.NewCalendar
    android:id="@+id/new_calendar"
    xmlns:NewCalendarNS="http://schemas.android.com/apk/res/com.example.jiaxufei.firstgitproject"

    android:layout_width="match_parent"
    android:layout_height="match_parent"
    NewCalendarNS:dateFormat="yyyy MMMM"></com.example.jiaxufei.firstgitproject.NewCalendar>
      

四.日历文件xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="30dp">

        <ImageView
            android:id="@+id/btnPre"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_alignParentLeft="true"
            android:src="@mipmap/jiantouleft" />

        <ImageView
            android:id="@+id/btnNext"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_alignParentRight="true"
            android:src="@mipmap/jiantouright" />

        <TextView

            android:id="@+id/txtData"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@id/btnNext"
            android:layout_toRightOf="@id/btnPre"
            android:gravity="center"
            android:text=" Jun 2017" />
    </RelativeLayout>

    <LinearLayout
        android:layout_marginTop="15dp"
        android:id="@+id/calendar_week_header"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:text="星期日" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:text="星期一" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:text="星期二" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:text="星期三" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:text="星期四" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:text="星期五" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:text="星期六" />
    </LinearLayout>

    <GridView
        android:id="@+id/calendar_grid"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:numColumns="7"></GridView>
</LinearLayout>      

五.自定义的日历item

<?xml version="1.0" encoding="utf-8"?>
<com.example.jiaxufei.firstgitproject.Calendar_day_textView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="30dp"
    android:id="@+id/tv_calendar_day"
    android:textSize="20dp"
    android:gravity="center"
    android:layout_height="30dp"/>      

六.用到的attrs文件

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="NewCalendar">
        <attr name="dateFormat" format="string" />
    </declare-styleable>
</resources>      

欢迎大家一起讨论学习。QQ:732258496。 Android 技术QQ群:478720016