通过GridView实现一个自定义的一个日历控件
最近工作的需求上面需要一个日历控件,之前也在网上找了不少开源的日历控件,但是效果总是不尽人意,也许也是自己水平有限,有些代码确实太过繁琐还看不周全,没办法,只好自己动手来写了。先简单上一张效果图实现的很简单,只能选择起始时间和结束时间,并且加了一些简单的验证。
·
最近工作的需求上面需要一个日历控件,之前也在网上找了不少开源的日历控件,但是效果总是不尽人意,也许也是自己水平有限,有些代码确实太过繁琐还看不周全,没办法,只好自己动手来写了。
先简单上一张效果图
实现的很简单,只能选择起始时间和结束时间,并且加了一些简单的验证。
首先是布局文件:
picker_layout.xml布局,展示每个月份的GridView
<?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="wrap_content"
android:background="@color/back_color"
android:orientation="vertical">
<TextView
android:id="@+id/date_txt"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:text="2016年4月"
android:textColor="@color/white" />
<com.newtimer.app.MyGridView
android:id="@+id/picker_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
接着是对应每一天的item picker_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/picker_txt"
android:layout_width="50dp"
android:layout_height="50dp"
android:gravity="center"
android:text="" />
</LinearLayout>
最后一个是主布局文件了 activity_main.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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/back_color"
tools:context="com.newtimer.app.MainActivity">
<TextView
android:id="@+id/txt1"
android:layout_width="150dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:background="@color/back_color"
android:gravity="center"
android:text="入住时间"
android:textColor="@color/hotel_name_txt_color" />
<Button
android:id="@+id/btn_reset"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:background="@color/back_color"
android:gravity="center"
android:text="重置"
android:textColor="@color/hotel_name_txt_color" />
<TextView
android:id="@+id/txt2"
android:layout_width="150dp"
android:layout_height="50dp"
android:layout_alignParentRight="true"
android:gravity="center"
android:text="离店时间"
android:textColor="@color/hotel_name_txt_color" />
<LinearLayout
android:id="@+id/week_linear"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_below="@id/txt1"
android:layout_marginBottom="20dp"
android:layout_marginTop="20dp"
android:background="@color/hotel_banner_color"
android:elevation="20dp"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_weight="1"
android:gravity="center"
android:paddingRight="10dp"
android:text="日"
android:textColor="@color/hotel_intro_txt_color" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_weight="1"
android:gravity="center"
android:paddingRight="10dp"
android:text="一"
android:textColor="@color/white" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_weight="1"
android:gravity="center"
android:paddingRight="10dp"
android:text="二"
android:textColor="@color/white" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_weight="1"
android:gravity="center"
android:paddingRight="10dp"
android:text="三"
android:textColor="@color/white" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_weight="1"
android:gravity="center"
android:paddingRight="10dp"
android:text="四"
android:textColor="@color/white" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_weight="1"
android:gravity="center"
android:paddingRight="10dp"
android:text="五"
android:textColor="@color/white" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_weight="1"
android:gravity="center"
android:paddingRight="10dp"
android:text="六"
android:textColor="@color/hotel_intro_txt_color" />
</LinearLayout>
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/week_linear"
android:divider="@color/transparent"
android:scrollbars="none">
</ListView>
</RelativeLayout>
接下来核心Java类如下:
首先是控件类:
MyGridView.java
public class MyGridView extends GridView {
public MyGridView(Context context) {
super(context);
}
public MyGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyGridView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
该类主要做了一个测量高度的工作。
接下来是控件类PickerLinear.java ,这个类主要做的就是展示每个月份的时间了,代码如下:
public class PickerLinear extends LinearLayout {
View view;
MyGridView myGridView;
List<String> dateList;
Calendar calendar;
MyPickerAdapter myPickerAdapter;
TextView dateTxt;
Context mContext;
private int month;
private GetDateStrInterface myInterface;
public PickerLinear(Context context, int month) {
super(context);
mContext = context;
this.month = month;
view = LayoutInflater.from(context).inflate(R.layout.picker_layout, this, true);
initView();
init();
setListener();
setAdapter();
}
public void setInterface(GetDateStrInterface interfaceParams) {
this.myInterface = interfaceParams;
}
public PickerLinear(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PickerLinear(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private void initView() {
myGridView = (MyGridView) view.findViewById(R.id.picker_grid);
myGridView.setNumColumns(7);
dateTxt = (TextView) view.findViewById(R.id.date_txt);
}
private void init() {
dateList = new ArrayList<>();
calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
if (month > 12) {
int someYear = month / 12;
year += someYear;
month = month - 12 * someYear;
if (month == 0) {
month = 12;
year -= 1;
}
}
int day = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1);
int taday = calendar.get(Calendar.DAY_OF_WEEK);
//如果不是每月第一天,则追加空白天数
if (taday != 1) {
for (int i = 0; i < taday - 1; i++) {
dateList.add(" , ");
}
}
for (int i = 1; i <= day; i++) {
dateList.add(year + "-" + month + "-" + i + "," + i);
}
myPickerAdapter = new MyPickerAdapter(mContext);
myPickerAdapter.setData(dateList);
dateTxt.setText(year + "年" + month + "月");
}
public void setListener() {
myGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
try {
String str = (String) adapterView.getItemAtPosition(i);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = format.parse(str);
Calendar c = Calendar.getInstance();
String str_1 = str.split(",")[0];
String currentStr = c.get(Calendar.YEAR) + "-" + (c.get(Calendar.MONTH) + 1) + "-" + c.get(Calendar.DAY_OF_MONTH);
Date currentDate = format.parse(currentStr);
if (date.getTime() >= currentDate.getTime() || currentStr.equals(str_1)) { //判断只有今天之后包括今天的日期才可以点
if (((MainActivity) mContext).frist == null) {
((MainActivity) mContext).frist = (TextView) view.findViewById(R.id.picker_txt);
((MainActivity) mContext).frist.setBackgroundColor(getResources().getColor(R.color.hotel_intro_txt_color));
TextView tx = ((MainActivity) mContext).frist;
tx.setTextColor(getResources().getColor(R.color.white));
if (currentStr.equals(str_1)) {
tx.setText(tx.getText().toString().substring(0, tx.getText().toString().indexOf("\n")) + "\n入住");
} else {
tx.setText(tx.getText().toString() + "\n入住");
}
myInterface.getPreTime(str);
} else if (((MainActivity) mContext).last == null && ((MainActivity) mContext).frist != null && !str_1.trim().equals(((MainActivity) mContext).frist.getText().toString().trim())) {
String txTag = ((MainActivity) mContext).frist.getTag().toString();
Date fristDate = format.parse(txTag);
if (fristDate.getTime() < date.getTime()) {
((MainActivity) mContext).last = (TextView) view.findViewById(R.id.picker_txt);
TextView tx = ((MainActivity) mContext).last;
tx.setText(tx.getText().toString() + "\n结束");
tx.setTextColor(getResources().getColor(R.color.white));
((MainActivity) mContext).last.setBackgroundColor(getResources().getColor(R.color.hotel_intro_txt_color));
myInterface.getNextTime(str);
} else {
Toast.makeText(mContext, "不能选择之前的时间", Toast.LENGTH_SHORT).show();
}
}
} else {
// Toast.makeText(mContext, "不能选择过去的时间", Toast.LENGTH_SHORT).show();
//这个提示没什么卵用...只要不傻都知道
}
} catch (ParseException exception) {
Toast.makeText(mContext, "报错了" + exception.getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
public void setAdapter() {
myGridView.setAdapter(myPickerAdapter);
}
interface GetDateStrInterface { //回调接口,让前边儿页面可以获取到时间
void getPreTime(String preStr);
void getNextTime(String nextStr);
}
}
接下来是 MyPickerAdapter.java ,这个文件的作用是给显示每个月份的GridView绑定数据。
public class MyPickerAdapter extends BaseAdapter {
private List<String> dateList;
private Context mContext;
public MyPickerAdapter(Context context) {
this.mContext = context;
}
public void setData(List<String> data) {
this.dateList = data;
}
@Override
public int getCount() {
if (dateList != null && dateList.size() > 0) {
return dateList.size();
}
return 0;
}
@Override
public Object getItem(int i) {
return dateList.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder vh;
if (view == null) {
vh = new ViewHolder();
view = LayoutInflater.from(mContext).inflate(R.layout.picker_item, null, false);
vh.tx = (TextView) view.findViewById(R.id.picker_txt);
view.setTag(vh);
} else {
vh = (ViewHolder) view.getTag();
}
String[] strArr = dateList.get(i).toString().split(",");
Calendar calendar = Calendar.getInstance();
int month = calendar.get(Calendar.MONTH) + 1;
if (strArr[0].equals(" ") || strArr[0].equals("")) {
vh.tx.setText(strArr[0]);
} else {
String currentStr = calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH) + 1) + "-" + calendar.get(Calendar.DAY_OF_MONTH);
Date currentDate = getDate(currentStr);
Date date = getDate(strArr[0]);
String s = strArr[0].split("-")[1];
int now_month = Integer.parseInt(s);
int day = Integer.parseInt(strArr[1].trim());
if (date.getTime() < currentDate.getTime()) {
vh.tx.setTextColor(mContext.getResources().getColor(R.color.hotel_name_txt_color));
} else {
if ((i + 1) % 7 == 1) { //计算为周日时显示的颜色
vh.tx.setTextColor(mContext.getResources().getColor(R.color.hotel_intro_txt_color));
} else if ((i + 1) % 7 == 0) {//计算为周六时显示的颜色
vh.tx.setTextColor(mContext.getResources().getColor(R.color.hotel_intro_txt_color));
} else {
vh.tx.setTextColor(mContext.getResources().getColor(R.color.white));
}
}
StringBuffer dateValue = new StringBuffer();
dateValue.append(strArr[1]);
if (day == calendar.get(Calendar.DAY_OF_MONTH) && month == now_month) {
dateValue.append("\n今天");
}
vh.tx.setText(dateValue);
vh.tx.setTag(strArr[0]);
}
return view;
}
class ViewHolder {
TextView tx;
}
public Date getDate(String currentStr) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date currentDate = null;
try {
currentDate = format.parse(currentStr);
} catch (ParseException e) {
e.printStackTrace();
}
return currentDate;
}
}
使用方法的MainActivity.java代码如下:
public class MainActivity extends AppCompatActivity implements PickerLinear.GetDateStrInterface {
PickerLinear pickerLinear;
Calendar calendar;
ListView list_view;
List<PickerLinear> pickerLinears;
TextView tx1, tx2;
Button btn_reset;
public TextView frist;
public TextView last;
private ListAdapter listAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list_view = (ListView) findViewById(R.id.list_view);
tx1 = (TextView) findViewById(R.id.txt1);
tx2 = (TextView) findViewById(R.id.txt2);
btn_reset = (Button) findViewById(R.id.btn_reset);
init();
setListener();
}
private void init() {
pickerLinears = new ArrayList<>();
calendar = Calendar.getInstance();
int month = calendar.get(Calendar.MONTH) + 1;
for (int i = 0; i < 6; i++) {
pickerLinear = new PickerLinear(this, month + i);
pickerLinear.setInterface(this);
pickerLinears.add(pickerLinear);
}
listAdapter = new ListAdapter();
list_view.setAdapter(listAdapter);
}
private void setListener() {
btn_reset.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (frist != null) {
String fristStr = frist.getText().toString().substring(0, frist.getText().toString().indexOf("\n")).trim();
int fristDate = Integer.parseInt(fristStr);
if (fristDate % 7 == 1) {
frist.setTextColor(getResources().getColor(R.color.hotel_intro_txt_color));
} else if (fristDate % 7 == 0) {
frist.setTextColor(getResources().getColor(R.color.hotel_intro_txt_color));
} else {
frist.setTextColor(getResources().getColor(R.color.hotel_name_txt_color));
}
frist.setBackgroundColor(getResources().getColor(R.color.back_color));
if (fristStr.equals(calendar.get(Calendar.DAY_OF_MONTH) + "")) {
frist.setText(fristStr + "\n今天");
} else {
frist.setText(fristStr);
}
}
if (last != null) {
String lastStr = last.getText().toString().substring(0, last.getText().toString().indexOf("\n")).trim();
int lastDate = Integer.parseInt(lastStr);
if (lastDate % 7 == 1) {
last.setTextColor(getResources().getColor(R.color.hotel_intro_txt_color));
} else if (lastDate % 7 == 0) {
last.setTextColor(getResources().getColor(R.color.hotel_intro_txt_color));
} else {
last.setTextColor(getResources().getColor(R.color.hotel_name_txt_color));
}
last.setBackgroundColor(getResources().getColor(R.color.back_color));
last.setText(lastStr);
}
frist = null;
last = null;
tx1.setText("入住时间");
tx2.setText("离店时间");
listAdapter.notifyDataSetChanged();
}
});
}
@Override
public void getPreTime(String preStr) {
String date = preStr.split(",")[0];
String[] dateArr = date.split("-");
tx1.setText("入住时间\n" + dateArr[0] + "年" + dateArr[1] + "月" + dateArr[2] + "日");
}
@Override
public void getNextTime(String nextStr) {
String date = nextStr.split(",")[0];
String[] dateArr = date.split("-");
tx2.setText("离店时间\n" + dateArr[0] + "年" + dateArr[1] + "月" + dateArr[2] + "日");
}
class ListAdapter extends BaseAdapter {
@Override
public int getCount() {
return pickerLinears.size();
}
@Override
public Object getItem(int i) {
return pickerLinears.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
return pickerLinears.get(i);
}
}
}
以上就是所有源代码了,算是一个基础的demo,希望能帮助到新手,如果有更好意见和建议欢迎交流,共同学习。
代码地址: https://github.com/color9169/customCalendar
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献1条内容
所有评论(0)