Android使用GridView实现日历的方法

在开发中可能会遇到某些情况下需要用到日历的功能,并且还要在日历上加标签什么的,最重要的就是android自带的日历由于各个系统版本不同导致日历的样式也不同,这样就会导致使用起来比较麻烦..而且在日历中加标签也不好实现...所以很多时候日历都是自己去实现的...由于自定义日历会比较麻烦...这里就教大家使用GridView来实现,主要是我们比较熟悉这个控件...到时候也可以根据自己的情况进行封装为自定义View

下面就先看看效果图.由于是从项目中抽取出来的,某些地方定制性比较强, 可以根据需求自行修改

效果图

图中的红点就是标签,蓝色背景就是选中的意思.

下面开始撸代码:

先上核心的GridView的适配器:

CalendarAdapter.java

/**
 * 日历gridview中的每一个item显示的textview
 */
public class CalendarAdapter extends BaseAdapter {

  private static String TAG = "CalendarAdapter";
  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 int currentYear = 0;
  private int currentMonth = 0;
  /**
   * 当前选中的日期位置
   */
  private int currentFlag = -1;
  /**
   * 当前选中天的字符串 例:20170830
   */
  private String currentDayStr;
  private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-d");
  private Set<Integer> schDateTagFlag = new ArraySet<>(); //存储当月所有的日程日期(标签)
  private String showYear = "";  //用于在头部显示的年份
  private String showMonth = ""; //用于在头部显示的月份
  private String animalsYear = "";
  private String leapMonth = "";  //闰哪一个月
  private Set<String> mSet = null;
  /**
   * 距离当前月的差(上一个月-1,当前月0,下一个月+1)
   */
  private int jumpMonth = 0;

  public CalendarAdapter(Context context, int year, int month, String currentDayStr) {
    this.context = context;
    sc = new SpecialCalendar();
    currentYear = year;
    currentMonth = month; //得到跳转到的月份
    this.currentDayStr = currentDayStr;
    getCalendar(currentYear, currentMonth);
  }

  @Override
  public int getCount() {
    return dayNumber.length;
  }

  @Override
  public Object getItem(int position) {
    return position;
  }

  @Override
  public long getItemId(int position) {
    return position;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder myViewHolder = null;
    if (convertView == null || convertView.getTag() == null) {
      convertView = LayoutInflater.from(context).inflate(R.layout.item_select_time, null);
      myViewHolder = new ViewHolder(convertView);
      convertView.setTag(myViewHolder);
    } else {
      myViewHolder = (ViewHolder) convertView.getTag();
    }
    myViewHolder.mIdTvItemSelectTimeDay.setText(dayNumber[position]);
    myViewHolder.mIdTvItemSelectTimeDay.setTextColor(Color.GRAY);//不是当前月为灰
    if (position < daysOfMonth + dayOfWeek && position >= dayOfWeek) {
      // 当前月信息显示
      myViewHolder.mIdTvItemSelectTimeDay.setTextColor(Color.BLACK);// 当月字体设黑
      myViewHolder.mIdTvItemSelectTimeDay.setTag(true);// 当月字体设黑
    }else {
      myViewHolder.mIdTvItemSelectTimeDay.setTag(false);// 当月字体设黑
    }

    if (currentFlag != -1 && currentFlag == position) {
      //设置当天的背景
      myViewHolder.mIdTvItemSelectTimeDay.setBackgroundResource(R.color.mainMenu);
      myViewHolder.mIdTvItemSelectTimeDay.setTextColor(Color.WHITE);
    } else {
      myViewHolder.mIdTvItemSelectTimeDay.setBackgroundColor(0);
    }

    //显示小圆点
    if (schDateTagFlag != null && schDateTagFlag.size() > 0) {
      if (schDateTagFlag.contains(position)) {
        if (myViewHolder.mIdImgItemSelectTimeLogo.getVisibility()!=View.VISIBLE) {
          myViewHolder.mIdImgItemSelectTimeLogo.setVisibility(View.VISIBLE);
        }
      } else {
        if (myViewHolder.mIdImgItemSelectTimeLogo.getVisibility()!=View.GONE) {
          myViewHolder.mIdImgItemSelectTimeLogo.setVisibility(View.GONE);
        }
      }
    } else {
      if (myViewHolder.mIdImgItemSelectTimeLogo.getVisibility()!=View.GONE) {
        myViewHolder.mIdImgItemSelectTimeLogo.setVisibility(View.GONE);
      }
    }

    return convertView;
  }

  /**
   * 下一个月
   */
  public void addMonth() {
    jumpMonth++;
  }

  /**
   * 上一个月
   */
  public void lessMonth() {
    jumpMonth--;
  }

  /**
   * 更新日历数据
   */
  public void upDataMonth() {
    int stepYear;
    int stepMonth = currentMonth + jumpMonth;
    if (stepMonth > 0) {
      //下一个月
      if (stepMonth % 12 == 0) {
        stepYear = currentYear + stepMonth / 12 - 1;
        stepMonth = 12;
      } else {
        stepYear = currentYear + stepMonth / 12;
        stepMonth = stepMonth % 12;
      }
    } else {
      //上一个月
      stepYear = currentYear - 1 + stepMonth / 12;
      stepMonth = stepMonth % 12 + 12;
    }
    getCalendar(stepYear, stepMonth);
  }

  /**
   * 得到某年的某月的天数且这月的第一天是星期几
   *
   * @param year
   * @param month
   */
  private 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中
   *
   * @param year
   * @param month
   */
  private void getWeek(int year, int month) {
    schDateTagFlag.clear();
    currentFlag = -1;
    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) {//本月
        int day = i - dayOfWeek + 1;  //得到的日期
        dayNumber[i] = i - dayOfWeek + 1 + "";
        //对于当前月才去标记当前日期
        String yearStr = String.valueOf(year);
        String monthStr =getStr(String.valueOf(month),2);
        String dayStr =getStr(String.valueOf(day),2);
        String timeAll = yearStr + monthStr + dayStr;
        if (timeAll.equals(currentDayStr)) {//判断选中的位置
          currentFlag = i;
        }
        if (mSet != null && mSet.size() > 0) {
          for (String s : mSet) {//迭代器遍历判断是否需要带标签
            if (timeAll.equals(s)) {
              schDateTagFlag.add(i);
            }
          }
        }
        setShowYear(yearStr);
        setShowMonth(String.valueOf(month));
      } else {  //下一个月
        dayNumber[i] = j + "";
        j++;
      }
    }
  }

  /**
   * 获取当前时间 样式:20170830
   * @param position
   * @return
   */
  public String getItemTime(int position) {
    String month = getStr(getShowMonth(), 2);
    String day = getStr(getDateByClickItem(position), 2);
    return getShowYear() + month + day;

  }

  /**
   * 保留N位整数,不足前面补0
   *
   * @param file String
   * @param bit 位数
   * @return
   */
  public static String getStr(String file,int bit) {
    while (file.length() < bit)
      file = "0" + file;
    return file;
  }

  /**
   * 点击每一个item时返回item中的日期
   *
   * @param position
   * @return
   */
  public String getDateByClickItem(int position) {
    return dayNumber[position];
  }

  /**
   * 在点击gridView时,得到这个月中第一天的位置
   *
   * @return
   */
  public int getStartPositon() {
    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;
  }

  public String getAnimalsYear() {
    return animalsYear;
  }

  public void setAnimalsYear(String animalsYear) {
    this.animalsYear = animalsYear;
  }

  public String getLeapMonth() {
    return leapMonth;
  }

  public void setLeapMonth(String leapMonth) {
    this.leapMonth = leapMonth;
  }

  public Set<String> getSet() {
    return mSet;
  }

  public void setSet(Set<String> set) {
    mSet = set;
  }

  static class ViewHolder {
    @BindView(R.id.id_img_item_select_time_logo)
    ImageView mIdImgItemSelectTimeLogo;
    @BindView(R.id.id_tv_item_select_time_day)
    TextView mIdTvItemSelectTimeDay;

    ViewHolder(View view) {
      ButterKnife.bind(this, view);
    }
  }
}

日历工具类:

/**
 * 日历工具类
 */
public class SpecialCalendar {

  private int daysOfMonth = 0;   //某月的天数
  private int dayOfWeek = 0;    //具体某一天是星期几 

  /**
   * 判断是否为闰年
   * @param year
   * @return
   */
  public boolean isLeapYear(int year) {
    if (year % 100 == 0 && year % 400 == 0) {
      return true;
    } else if (year % 100 != 0 && year % 4 == 0) {
      return true;
    }
    return false;
  }

  /**
   * 得到某月有多少天数
   * @param isLeapyear
   * @param month
   * @return
   */
  public int getDaysOfMonth(boolean isLeapyear, int month) {
    switch (month) {
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 10:
    case 12:
      daysOfMonth = 31;
      break;
    case 4:
    case 6:
    case 9:
    case 11:
      daysOfMonth = 30;
      break;
    case 2:
      if (isLeapyear) {
        daysOfMonth = 29;
      } else {
        daysOfMonth = 28;
      } 

    }
    return daysOfMonth;
  }

  /**
   * 指定某年中的某月的第一天是星期几
   * @param year
   * @param month
   * @return
   */
  public int getWeekdayOfMonth(int year, int month){
    Calendar cal = Calendar.getInstance();
    cal.set(year, month-1, 1);
    dayOfWeek = cal.get(Calendar.DAY_OF_WEEK)-1;
    return dayOfWeek;
  } 

}

布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical">

  <include
    layout="@layout/layout_public_finish_menu"
    />

  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:background="@color/bg_home_gone_menu"
    android:gravity="center"
    android:orientation="horizontal"
    >

    <ImageView
      android:id="@+id/id_img_select_time_less"
      android:layout_width="wrap_content"
      android:layout_height="match_parent"
      android:layout_weight="1"
      android:padding="5dp"
      android:src="@mipmap/ic_sd_time_less"
      android:background="@drawable/selector_public_btn_bg"
      />

    <TextView
      android:id="@+id/id_tv_select_time_show"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_weight="4"
      android:gravity="center"
      android:text="年月"
      android:textColor="@color/white"
      android:textSize="@dimen/default_big"
      />

    <ImageView
      android:id="@+id/id_img_select_time_add"
      android:layout_width="wrap_content"
      android:layout_height="match_parent"
      android:layout_weight="1"
      android:padding="5dp"
      android:src="@mipmap/ic_sd_time_add"
      android:background="@drawable/selector_public_btn_bg"
      />

  </LinearLayout>

  <GridView
    android:id="@+id/id_gv_select_item"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/bg_rectangle_null_black_1"
    android:clickable="true"
    android:gravity="center"
    android:layout_gravity="center"
    android:clipChildren="true"
    android:listSelector="@null"
    android:numColumns="7"
    android:padding="1dp"
    android:layout_margin="5dp"
    android:stretchMode="columnWidth"
    />

</LinearLayout>

Item布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/bg_rectangle_null_black_1">

  <TextView
    android:id="@+id/id_tv_item_select_time_day"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:text="天"
    android:textSize="@dimen/default_big"
    android:layout_margin="1dp"
    android:textStyle="bold"
    />

  <ImageView
    android:id="@+id/id_img_item_select_time_logo"
    android:layout_width="5dp"
    android:layout_height="5dp"
    android:layout_margin="3dp"
    android:src="@drawable/shap_doorbell_oval_red"
    android:visibility="gone"
    />
</RelativeLayout>

布局只供参考...可以根据需求进行修改

下面就看看简单的调用

 //传入当前的年,月..已经选中的时间(20170830)
 mAdapter = new CalendarAdapter(mContext, year_c, month_c, currentDayStr);
 mIdGvSelectItem.setAdapter(mAdapter);

 /**
   * GridView Item的点击事件
   */
  private class MyGvListener implements AdapterView.OnItemClickListener {

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
      TextView mTv = (TextView) view.findViewById(R.id.id_tv_item_select_time_day);
      boolean isOnClick = (boolean) mTv.getTag();
      if (isOnClick) {
        String time = mAdapter.getItemTime(position);
        Intent mIntent = getIntent();
        mIntent.putExtra("fileDate", time);
        setResult(AppStart.SDVA_SDTA, mIntent);
        finish();
        Log.i(TAG,"当前选择的时间:" + time);
      }
    }
  }

 /**
   * 点击事件逻辑处理
   */
  private class MyListener implements View.OnClickListener {
    @Override
    public void onClick(View v) {
      switch (v.getId()) {

        //上一个月
        case R.id.id_img_select_time_less:
          mAdapter.lessMonth();
          mHandler.sendEmptyMessage(UPDATA_TIME);
          addTextToTopTextView(mIdTvSelectTimeShow);
          break;

        //下一个月
        case R.id.id_img_select_time_add:
          mAdapter.addMonth();
          mHandler.sendEmptyMessage(UPDATA_TIME);
          addTextToTopTextView(mIdTvSelectTimeShow);
          break;

      }
    }
  }

private Set<String> dayEventCount = new HashSet<>();
//设置需要显示标签的实际
 mAdapter.setSet(dayEventCount);

//更新
  @Override
  protected void uiHandlerMessage(Message msg) {

    switch (msg.what) {
      case UPDATA_TIME:
        mAdapter.upDataMonth();
        mAdapter.notifyDataSetChanged();
        break;

    }

  }

调用部分的代码由于是从项目中直接复制出来的..代码的前后没有什么关联性,主要是说明功能的..请根据自己的项目进行调整..

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

(0)

相关推荐

  • 详解Android 中AsyncTask 的使用

    详解Android 中AsyncTask 的使用 1.首先我们来看看AsyncTask 的介绍:   Handler 和 AsyncTask 都是android 中用来实现异步任务处理的方式:其中: Handler 实例向 UI 线程发送消息,完成界面更新, 优点:对整个过程控制的比较精细:         缺点:代码相对臃肿,多个任务同时执行时,不易对线程进行精确的控制: AsyncTask :比Handler 更轻量级一些,适用于简单的异步处理: 优点:简单 | 快捷 | 过程可控:    

  • Android编程实现播放视频时切换全屏并隐藏状态栏的方法

    本文实例讲述了Android编程实现播放视频时切换全屏并隐藏状态栏的方法.分享给大家供大家参考,具体如下: 1. Demo示例: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (this.getResources().getConfiguration().ori

  • 浅谈Android 的线程和线程池的使用

    Android 的线程和线程池 从用途上分,线程分为主线程和子线程:主线程主要处理和界面相关的事情,子线程则往往用于耗时操作. 主线程和子线程 主线程是指进程所拥有的线程.Android 中主线程交 UI 线程,主要作用是运行四大组件以及处理它们和用户的交互:子线程的作业则是执行耗时任务. Android 中的线程形态 1.AsyncTask AsyncTask 是一种轻量级的异步任务类,可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新 UI, AsyncTas

  • Android开发实现各种图形绘制功能示例

    本文实例讲述了Android开发实现各种图形绘制功能.分享给大家供大家参考,具体如下: 这里结合本人的开发事例,简单介绍一下如何在Android平台下实现各种图形的绘制. 首先自定义一个View类,这个view类里面需要一个Paint对象来控制图形的属性,需要一个Path对象来记录图形绘制的路径,需要一个Canvas类来执行绘图操作,还需要一个Bitmap类来盛放绘画的结果. Paint mPaint = new Paint(); mPaint.setAntiAlias(true); mPain

  • Android开发之全屏与非全屏的切换设置方法小结

    本文实例讲述了Android开发之全屏与非全屏的切换设置方法.分享给大家供大家参考,具体如下: 静态方法 1. 代码方式 在Activity类OnCreate方法中设置,代码如下 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().se

  • Android Spinner 组件的应用实例

    Android Spinner 组件 Spinner: 下拉组件 使用事项:布局在XML 中实现,具体的数据在JAVA 代码中实现: 所用知识点: 数组适配器:ArrayAdapter  用于关系M 层和 C 层: 事件:OnItemSelectedListener; 案列:查看十二星座效果图: xml:代码如下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tool

  • Android 中WallpaperManager用法实例

    Android 中WallpaperManager用法实例 注意:壁纸的设置得加入权限: <uses-permission android:name="android.permission.SET_WALLPAPER"/> 1.WallpaperManager  对象的获得: wallpaperManager =WallpaperManager.getInstance(this); 2.设置壁纸的方法: 方法一:wallpaperManager.setBitmap(); /

  • Android使用GridView实现日历的方法

    在开发中可能会遇到某些情况下需要用到日历的功能,并且还要在日历上加标签什么的,最重要的就是android自带的日历由于各个系统版本不同导致日历的样式也不同,这样就会导致使用起来比较麻烦..而且在日历中加标签也不好实现...所以很多时候日历都是自己去实现的...由于自定义日历会比较麻烦...这里就教大家使用GridView来实现,主要是我们比较熟悉这个控件...到时候也可以根据自己的情况进行封装为自定义View 下面就先看看效果图.由于是从项目中抽取出来的,某些地方定制性比较强, 可以根据需求自行

  • Android使用GridView实现日历功能示例(详细代码)

    Android使用GridView实现日历功能示例,代码有点多,发个图先: 如果懒得往下看的,可以直接下载源码吧,最近一直有人要,由于时间太久了,懒得找出来整理,今天又看到有人要,正好没事就整理了一下 源码下载.... 布局文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/an

  • Android中GridView插件的使用方法

    布局文件activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent&q

  • Android使用GridView实现日历的简单功能

    简单的日历实现,只是显示了每一个月,没有显示当天和记事这些功能 主要是计算月初是周几,月末是周几,然后相应的显示上一月多少天和下一月多少天. 先看一下关于日期的用到的几个工具类 /** * 获取该月天数 */ public static int getCurrentMonthDay(long millSec) { Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(millSec); calendar.set(

  • Android开发之使用GridView展示图片的方法

    本文实例讲述了Android使用GridView展示图片的方法.分享给大家供大家参考,具体如下: 今天说说GridView的使用. 所谓GvidView翻译过来就是网格布局:是一个ViewGroup以网格显示它的子视图(view)元素,即二维的.可滚动的网格.网格元素通过ListAdapter自动插入到网格. 这个GridView用处特别多,我这里是用来展示广告的.2*3的广告位置. 废话少说先看个效果图,有图就可以说个XX,对吧,大家都懂的. 大家可以看到搜索下面的那6个块,效果布局还行吧,哈

  • Android实现GridView中ImageView动态变换的方法

    本文实例讲述了Android实现GridView中ImageView动态变换的方法.分享给大家供大家参考.具体如下: 使用YY影音的时候,发现点击GridView的某一个Item,Item里面的图标会在按下的时候发生变换,变成另外一个图片. 自己写了一个类似的demo,具体步骤如下: 1.创建一个包含Grid的Acitity 2.创建item.xml 里面包含一个imageview和一个textview 3.自定义一个adapter,从baseadapter继承 4.在getView中为每个im

  • Android 中 GridView嵌套在ScrollView里只有一行的解决方法

    在做android项目中遇到一个bug,GridView嵌套在ScrollView里只有一行的问题.下面小编在网上找到了解决方法,具体方法如下所示: 方法一:就是上面说的通过计算出来ListView或者GridView中的子列高度和 进行显示: public void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdap

  • Android中ScrollView嵌套GridView显示不全解决方法

    Android中ScrollView嵌套GridView显示不全解决方法 由于ScrollView和GridView这两款控件都自带滚动条,一起使用GridView会显示不全 解决方法:自定义gridview 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

  • Android开发实现横向列表GridView横向滚动的方法【附源码下载】

    本文实例讲述了Android开发实现横向列表GridView横向滚动的方法.分享给大家供大家参考,具体如下: Android 横向列表实现,可左右滑动,如下图 1. 主界面布局代码:activity_main.xml a.包裹HorizontalScrollView控件是GirdView横向滚动的基本条件 b.GirdView外包裹LinearLayout是java代码中参数设置的必要条件 <?xml version="1.0" encoding="utf-8"

  • Android中GridView布局实现整体居中方法示例

    前言 本文主要给大家介绍了关于Android中GridView布局整体居中的相关内容,是对于自己在项目中遇到问题的一个记录,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 效果图: 示例代码: /** * 对高度和宽度进行统计 然后设置gridView的宽高. * @param numColumns 设定行数 * @param gridView */ public static void calGridViewSumWH(int numColumns ,GridView gri

随机推荐