温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何使用Android实现可滑动的自定义日历控件

发布时间:2021-04-17 09:43:03 来源:亿速云 阅读:273 作者:小新 栏目:移动开发

小编给大家分享一下如何使用Android实现可滑动的自定义日历控件,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

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

如何使用Android实现可滑动的自定义日历控件

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

布局文件

<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      android:text="周日"   android:textColor="@color/green" />    <TextView      android:text="周一" />    <TextView      android:text="周二" />    <TextView      android:text="周三" />    <TextView      android:text="周四" />    <TextView      android:text="周五" />    <TextView      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);   }  });  } }

看完了这篇文章,相信你对“如何使用Android实现可滑动的自定义日历控件”有了一定的了解,如果想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI