首页 > 系统 > Android > 正文

Android实现可滑动的自定义日历控件

2019-12-12 00:41:02
字体:
来源:转载
供稿:网友

最近用到的一个日历控件,记录下,效果如图

代码下载地址:点击打开链接

布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:visibility="visible">  <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/bg_gray" android:orientation="horizontal">  <ImageView  android:id="@+id/prevMonth"  android:layout_width="0dp"  android:layout_height="wrap_content"  android:layout_gravity="center"  android:layout_weight="1"  android:src="@drawable/prev_month" />  <TextView  android:id="@+id/currentMonth"  android:layout_width="0dp"  android:layout_height="35dp"  android:layout_weight="3"  android:gravity="center"  android:text="2016年9月"  android:textColor="@color/black"  android:textSize="18sp" />  <ImageView  android:id="@+id/nextMonth"  android:layout_width="0dp"  android:layout_height="wrap_content"  android:layout_gravity="center"  android:layout_weight="1"  android:src="@drawable/next_month" /> </LinearLayout>  <LinearLayout android:layout_width="match_parent" android:layout_height="20dp" android:background="@color/bg_gray">  <TextView  style="@style/weekName"  android:text="周日"  android:textColor="@color/green" />  <TextView  style="@style/weekName"  android:text="周一" />  <TextView  style="@style/weekName"  android:text="周二" />  <TextView  style="@style/weekName"  android:text="周三" />  <TextView  style="@style/weekName"  android:text="周四" />  <TextView  style="@style/weekName"  android:text="周五" />  <TextView  style="@style/weekName"  android:text="周六"  android:textColor="@color/green" /> </LinearLayout>  <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/line" />  <ViewFlipper android:id="@+id/flipper" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@color/line" android:padding="1dp" />  <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/line" /> </LinearLayout>

日历PopCalendar.class的代码

public class PopCalendar extends PopupWindow implements View.OnClickListener { private View contentView; private Context mContext; private WindowManager windowManager; private GestureDetector gestureDetector = null; private CalendarAdapter calV = null; private ViewFlipper flipper = null; private GridView gvCalendar = null; private static int jumpMonth = 0; // 每次滑动,增加或减去一个月,默认为0(即显示当前月) private static int jumpYear = 0; // 滑动跨越一年,则增加或者减去一年,默认为0(即当前年) private int yearC = 0; private int monthC = 0; private int dayC = 0; private String currentDate = ""; //当前年月,显示在日历顶端 private TextView currentMonthTv; //上个月,下个月的图标 private ImageView prevMonthIv; private ImageView nextMonthIv;  public PopCalendar(final Activity context) { this.mContext = context; this.windowManager = context.getWindowManager();; Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-d"); currentDate = sdf.format(date); // 当期日期 yearC = Integer.parseInt(currentDate.split("-")[0]); monthC = Integer.parseInt(currentDate.split("-")[1]); dayC = Integer.parseInt(currentDate.split("-")[2]); jumpMonth = 0; jumpYear = 0;  //设置PopWindow的属性 LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); contentView = inflater.inflate(R.layout.pop_calendar, null); this.setContentView(contentView); this.setWidth(WindowManager.LayoutParams.FILL_PARENT); this.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); this.setFocusable(true); this.setOutsideTouchable(true); this.update(); ColorDrawable dw = new ColorDrawable(0000000000); this.setBackgroundDrawable(dw);  currentMonthTv = (TextView) contentView.findViewById(R.id.currentMonth); prevMonthIv = (ImageView) contentView.findViewById(R.id.prevMonth); nextMonthIv = (ImageView) contentView.findViewById(R.id.nextMonth); setListener();  gestureDetector = new GestureDetector(mContext, new MyGestureListener()); flipper = (ViewFlipper) contentView.findViewById(R.id.flipper); flipper.removeAllViews(); calV = new CalendarAdapter(mContext, mContext.getResources(), jumpMonth, jumpYear, yearC, monthC, dayC); addGridView(); gvCalendar.setAdapter(calV); flipper.addView(gvCalendar, 0); addTextToTopTextView(currentMonthTv); }  private class MyGestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {  if (e1.getX() - e2.getX() > 120) {  // 像左滑动  enterNextMonth();  return true;  } else if (e1.getX() - e2.getX() < -120) {  // 向右滑动  enterPrevMonth();  return true;  }  return false; } }  /** * 移动到下一个月 * */ private void enterNextMonth() { addGridView(); // 添加一个gridView jumpMonth++; // 下一个月  calV = new CalendarAdapter(mContext, mContext.getResources(), jumpMonth, jumpYear, yearC, monthC, dayC); gvCalendar.setAdapter(calV); addTextToTopTextView(currentMonthTv); // 移动到下一月后,将当月显示在头标题中 flipper.addView(gvCalendar, 1); flipper.setInAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_left_in)); flipper.setOutAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_left_out)); flipper.showNext(); flipper.removeViewAt(0); }  /** * 移动到上一个月 * */ private void enterPrevMonth() { addGridView(); // 添加一个gridView jumpMonth--; // 上一个月  calV = new CalendarAdapter(mContext, mContext.getResources(), jumpMonth, jumpYear, yearC, monthC, dayC); gvCalendar.setAdapter(calV); addTextToTopTextView(currentMonthTv); // 移动到上一月后,将当月显示在头标题中 flipper.addView(gvCalendar, 1);  flipper.setInAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_right_in)); flipper.setOutAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_right_out)); flipper.showPrevious(); flipper.removeViewAt(0); }  /** * 添加头部的年份 闰哪月等信息 * @param view */ public void addTextToTopTextView(TextView view) { StringBuffer textDate = new StringBuffer(); textDate.append(calV.getShowYear()).append("年").append(calV.getShowMonth()).append("月").append("/t"); view.setText(textDate); }  private void addGridView() { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.MATCH_PARENT); // 取得屏幕的宽度和高度 Display display = windowManager.getDefaultDisplay(); int Width = display.getWidth(); int Height = display.getHeight(); gvCalendar = new GridView(mContext); gvCalendar.setNumColumns(7); gvCalendar.setColumnWidth(40); // gridView.setStretchMode(GridView.STRETCH_COLUMN_WIDTH); if (Width == 720 && Height == 1280) {  gvCalendar.setColumnWidth(40); } gvCalendar.setGravity(Gravity.CENTER_VERTICAL); gvCalendar.setSelector(new ColorDrawable(Color.TRANSPARENT)); // 去除gridView边框 gvCalendar.setVerticalSpacing(2); gvCalendar.setHorizontalSpacing(2); gvCalendar.setOnTouchListener(new View.OnTouchListener() {  // 将gridView中的触摸事件回传给gestureDetector  public boolean onTouch(View v, MotionEvent event) {  // TODO Auto-generated method stub  return PopCalendar.this.gestureDetector.onTouchEvent(event);  } });  gvCalendar.setOnItemClickListener(new AdapterView.OnItemClickListener() {   @Override  public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {  // TODO Auto-generated method stub  // 点击任何一个item,得到这个item的日期(排除点击的是周日到周六(点击不响应))  int startPosition = calV.getStartPosition();  int endPosition = calV.getEndPosition();  if (startPosition <= position + 7 && position <= endPosition - 7) {   String scheduleDay = calV.getDateByClickItem(position); // 这一天的阳历   String scheduleYear = calV.getShowYear();   String scheduleMonth = calV.getShowMonth();   Toast.makeText(mContext, scheduleYear + "-" + scheduleMonth + "-" + scheduleDay, Toast.LENGTH_SHORT).show();  }  } }); gvCalendar.setLayoutParams(params); }  private void setListener() { prevMonthIv.setOnClickListener(this); nextMonthIv.setOnClickListener(this); }  @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) {  case R.id.nextMonth: // 下一个月  enterNextMonth();  break;  case R.id.prevMonth: // 上一个月  enterPrevMonth();  break;  default:  break; } }  /** * 显示popWindow */ public void showPopupWindow(View parent) { if (!this.isShowing()) {  // 以下拉方式显示popupwindow  this.showAsDropDown(parent); } else {  this.dismiss(); } }}

日历的内容是一个GridView,可以自定义类似签到效果的图标

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@color/bg_gray" >  <TextView android:id="@+id/tv_text" android:layout_width="fill_parent" android:layout_height="30dp" android:gravity="center" />  <ImageView android:layout_width="15dp" android:layout_height="15dp" android:visibility="invisible" android:layout_alignParentBottom="true" android:background="@drawable/pen" android:layout_alignParentEnd="true" android:id="@+id/iv_pen" />  </RelativeLayout>

日历的adapter

public class CalendarAdapter extends BaseAdapter { private boolean isLeapYear = false; // 是否为闰年 private int daysOfMonth = 0; // 某月的天数 private int dayOfWeek = 0; // 具体某一天是星期几 private int lastDaysOfMonth = 0; // 上一个月的总天数 private Context context; private String[] dayNumber = new String[42]; // 一个gridview中的日期存入此数组中 private SpecialCalendar sc = null; private Resources res = null;  private String currentYear = ""; private String currentMonth = "";  private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-d"); private int currentFlag = -1; // 用于标记当天  private String showYear = ""; // 用于在头部显示的年份 private String showMonth = ""; // 用于在头部显示的月份  // 系统当前时间 private String sysDate = ""; private String sys_year = ""; private String sys_month = ""; private String sys_day = ""; public CalendarAdapter() { Date date = new Date(); sysDate = sdf.format(date); // 当期日期 sys_year = sysDate.split("-")[0]; sys_month = sysDate.split("-")[1]; sys_day = sysDate.split("-")[2]; }  public CalendarAdapter(Context context, Resources rs, int jumpMonth, int jumpYear, int year_c, int month_c, int day_c) { this(); this.context = context; sc = new SpecialCalendar(); this.res = rs;  int stepYear = year_c + jumpYear; int stepMonth = month_c + jumpMonth; if (stepMonth > 0) {  // 往下一个月滑动  if (stepMonth % 12 == 0) {  stepYear = year_c + stepMonth / 12 - 1;  stepMonth = 12;  } else {  stepYear = year_c + stepMonth / 12;  stepMonth = stepMonth % 12;  } } else {  // 往上一个月滑动  stepYear = year_c - 1 + stepMonth / 12;  stepMonth = stepMonth % 12 + 12;  if (stepMonth % 12 == 0) {   } }  currentYear = String.valueOf(stepYear); // 得到当前的年份 currentMonth = String.valueOf(stepMonth); // 得到本月 // (jumpMonth为滑动的次数,每滑动一次就增加一月或减一月)  getCalendar(Integer.parseInt(currentYear), Integer.parseInt(currentMonth));  }  @Override public int getCount() { // TODO Auto-generated method stub return dayNumber.length; }  @Override public Object getItem(int position) { // TODO Auto-generated method stub return position; }  @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; }  @Override public View getView(int position, View convertView, ViewGroup parent) {  if (convertView == null) {  convertView = LayoutInflater.from(context).inflate(R.layout.calendar_item, null); } TextView textView = (TextView) convertView.findViewById(R.id.tv_text); ImageView ivPen = (ImageView) convertView.findViewById(R.id.iv_pen); String d = dayNumber[position];  SpannableString sp = new SpannableString(d); sp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, d.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); sp.setSpan(new RelativeSizeSpan(1.2f), 0, d.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  textView.setText(sp); textView.setTextColor(Color.BLACK);// 字体设黑 if (position % 7 == 0 || position % 7 == 6) {  // 当前月信息显示  textView.setTextColor(res.getColor(R.color.green));// 周末字体设绿色 }  if (position >= dayOfWeek && position < daysOfMonth + dayOfWeek  && (Integer.parseInt(sys_month) >= Integer.parseInt(currentMonth)&&Integer.parseInt(sys_year)==Integer.parseInt(currentYear)  ||Integer.parseInt(sys_year)> Integer.parseInt(currentYear))) {  // 当前月信息显示  int a[] = {2, 6, 29};//每个月不标记的天数  for (int i = 0; i < a.length; i++) {  if (position == a[i]+dayOfWeek-1) {   textView.setBackgroundColor(res.getColor(R.color.yellow));//为写日记日期填充黄色   ivPen.setVisibility(View.INVISIBLE);   break;  } else {   ivPen.setVisibility(View.VISIBLE);  }  } } else if (position < dayOfWeek || position >= daysOfMonth + dayOfWeek) {  textView.setTextColor(res.getColor(R.color.bg_gray)); }  if (Integer.parseInt(sys_year)==Integer.parseInt(currentYear)  &&Integer.parseInt(sys_month) == Integer.parseInt(currentMonth)&& currentFlag < position) {  // 设置本月当天之后的背景  textView.setBackgroundColor(res.getColor(R.color.bg_gray));//全部填充灰色  ivPen.setVisibility(View.INVISIBLE); }  if (currentFlag == position) {  //设置当天的背景  textView.setBackgroundColor(res.getColor(R.color.blue));  textView.setTextColor(Color.WHITE); } return convertView; }  // 得到某年的某月的天数且这月的第一天是星期几 public void getCalendar(int year, int month) { isLeapYear = sc.isLeapYear(year); // 是否为闰年 daysOfMonth = sc.getDaysOfMonth(isLeapYear, month); // 某月的总天数 dayOfWeek = sc.getWeekdayOfMonth(year, month); // 某月第一天为星期几 lastDaysOfMonth = sc.getDaysOfMonth(isLeapYear, month - 1); // 上一个月的总天数 getWeek(year, month); }  // 将一个月中的每一天的值添加入数组dayNuber中 private void getWeek(int year, int month) { int j = 1; // 得到当前月的所有日程日期(这些日期需要标记) for (int i = 0; i < dayNumber.length; i++) {  if (i < dayOfWeek) { // 前一个月  int temp = lastDaysOfMonth - dayOfWeek + 1;  dayNumber[i] = (temp + i) + "" ;  } else if (i < daysOfMonth + dayOfWeek) { // 本月  String day = String.valueOf(i - dayOfWeek + 1); // 得到的日期  dayNumber[i] = i - dayOfWeek + 1 + "";  // 对于当前月才去标记当前日期  if (sys_year.equals(String.valueOf(year)) && sys_month.equals(String.valueOf(month)) && sys_day.equals(day)) {   // 标记当前日期   currentFlag = i;  }  setShowYear(String.valueOf(year));  setShowMonth(String.valueOf(month));  } else { // 下一个月  dayNumber[i] = j + "";  j++;  } } }  /** * 点击每一个item时返回item中的日期 * @param position * @return */ public String getDateByClickItem(int position) { return dayNumber[position]; }  /** * 在点击gridView时,得到这个月中第一天的位置 * @return */ public int getStartPosition() { return dayOfWeek + 7; }  /** * 在点击gridView时,得到这个月中最后一天的位置 * @return */ public int getEndPosition() { return (dayOfWeek + daysOfMonth + 7) - 1; }  public String getShowYear() { return showYear; }  public void setShowYear(String showYear) { this.showYear = showYear; }  public String getShowMonth() { return showMonth; }  public void setShowMonth(String showMonth) { this.showMonth = showMonth; }}

在MainActivity点击显示日历,可以指定PopWindow在哪一个控件的下方出现

public class MainActivity extends AppCompatActivity {  @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);  final Button button = (Button)findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() {  @Override  public void onClick(View view) {  PopCalendar popCalendar = new PopCalendar(MainActivity.this);  popCalendar.showPopupWindow(button);  } }); }}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表