上来就干,是我一贯的作风!
先预览下效果图
未签到效果.png
已签到效果.png
分析控件结构:
从上到下依次是TextView→GridView→GridView
布局代码:
xmlns:android="/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white">
android:id="@+id/tvYear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="7月"
android:gravity="center"
android:textColor="@android:color/white"
android:background="@color/colorAccent"/>
android:id="@+id/gvWeek"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:numColumns="7">
android:id="@+id/gvDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:numColumns="7">
1、tvYear负责显示年月。
2、gvWeek负责显示星期几
3、gvDate负责显示日历
把整体布局作为组合控件封装在SignDate类里面,SignDate主要代码如下:
public class SignDate extends LinearLayout {
private TextView tvYear;
private InnerGridView gvWeek;
private InnerGridView gvDate;
private AdapterDate adapterDate;
public SignDate(Context context) {
super(context);
init();
}
...
private void init(){
View view = View.inflate(getContext(),R.layout.layout_signdate,this);
tvYear = view.findViewById(R.id.tvYear);
gvWeek = view.findViewById(R.id.gvWeek);
gvDate = view.findViewById(R.id.gvDate);
tvYear.setText(DateUtil.getCurrentYearAndMonth());
gvWeek.setAdapter(new AdapterWeek(getContext()));
adapterDate = new AdapterDate(getContext());
gvDate.setAdapter(adapterDate);
}
/**
* 签到成功的回调
* @param onSignedSuccess
*/
public void setOnSignedSuccess(OnSignedSuccess onSignedSuccess){
adapterDate.setOnSignedSuccess(onSignedSuccess);
}
}
代码中AdapterWeek就是简单的设置星期几数据,这里不多介绍。
在AdapterDate中实现了本月天数计算,开始天数应该显示在星期几的位置,和点击签到实现签到效果,代码如下:
public class AdapterDate extends BaseAdapter {
private Context context;
private List days = new ArrayList<>();
//日历数据
private List status = new ArrayList<>();
//签到状态,实际应用中初始化签到状态可通过该字段传递
private OnSignedSuccess onSignedSuccess;
//签到成功的回调方法,相应的可自行添加签到失败时的回调方法
public AdapterDate(Context context) {
this.context = context;
int maxDay = DateUtil.getCurrentMonthLastDay();//获取当月天数
for (int i = 0; i < DateUtil.getFirstDayOfMonth() - 1; i++) {
//DateUtil.getFirstDayOfMonth()获取当月第一天是星期几,星期日是第一天,依次类推
days.add(0);
//0代表需要隐藏的item
status.add(false);
//false代表为签到状态
}
for (int i = 0; i < maxDay; i++) {
days.add(i+1);
//初始化日历数据
status.add(false);
//初始化日历签到状态
}
}
@Override
public int getCount() {
return days.size();
}
@Override
public Object getItem(int i) {
return days.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(final int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder;
if(view==null){
view = LayoutInflater.from(context).inflate(R.layout.item_gv,null);
viewHolder = new ViewHolder();
view.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.tv = view.findViewById(R.id.tvWeek);
viewHolder.rlItem = view.findViewById(R.id.rlItem);
viewHolder.ivStatus = view.findViewById(R.id.ivStatus);
viewHolder.tv.setText(days.get(i)+"");
if(days.get(i)==0){
viewHolder.rlItem.setVisibility(View.GONE);
}
if(status.get(i)){
viewHolder.tv.setTextColor(Color.parseColor("#FD0000"));
viewHolder.ivStatus.setVisibility(View.VISIBLE);
}else{
viewHolder.tv.setTextColor(Color.parseColor("#666666"));
viewHolder.ivStatus.setVisibility(View.GONE);
}
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(status.get(i)){
Toast.makeText(context,"Already sign in!",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(context,"Sign in success!",Toast.LENGTH_SHORT).show();
status.set(i,true);
notifyDataSetChanged();
if(onSignedSuccess!=null){
onSignedSuccess.OnSignedSuccess();
}
}
}
});
return view;
}
class ViewHolder{
RelativeLayout rlItem;
TextView tv;
ImageView ivStatus;
}
public void setOnSignedSuccess(OnSignedSuccess onSignedSuccess){
this.onSignedSuccess = onSignedSuccess;
}
}
代码实在简单,没有什么技术上的难点,初始化数据、签到失败回调、界面效果等一些功能,大家可以自行补充。
工程源码地址:/StormFeng/SignDate