Android中的CalendarView

时间:2015-03-27 03:14:18

标签: android android-calendar calendarview

我已经在我的项目中实现了CalendarView,我希望在点击日期时获得DD / MM / YY格式

我尝试了以下内容:

calendar =(CalendarView) findViewById(R.id.calendarforstart);
calendar.setShowWeekNumber(false);
    calendar.setFirstDayOfWeek(2);
    calendar.setOnDateChangeListener(new OnDateChangeListener() 
    {
        @Override
        public void onSelectedDayChange(CalendarView view, int year, int month, int day) 
        {
            Toast.makeText(getApplicationContext(), day + "/" + month + "/" + year, Toast.LENGTH_LONG).show();
        }
    });

以上工作正常但如果我将日历滚动到下个月或上个月。我得到了Toast,我不想要,我只想在点击日期时才能获得祝酒?

我该如何实现?

让我知道!

谢谢!

1 个答案:

答案 0 :(得分:1)

解决cannot select the current date是一个艰难的方法。想法是保存每个列表项的屏幕位置,并检查每个dispatchTouchEvent if(x,y)是否在日期视图项内。

private long lastDate = 0;

private int downX;
private int downY;

private int upX;
private int upY;

private int lastX=0;
private int lastY=0;

private ItemArea currentArea;

private int year = -1;
private int month;
private int day;

private ListView listView;

private int[] startPoint = new int[2];

private int listItemCount = 0;
private int listItemWidth = 0;
private int listItemHeight = 0;

ArrayList<ItemArea> areaList = new ArrayList<>();

private CalendarView calendar;

private boolean isInitialized = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    calendar =(CalendarView) findViewById(R.id.calendarforstart);
    calendar.setShowWeekNumber(false);
    calendar.setFirstDayOfWeek(2);
    calendar.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
        @Override
        public void onSelectedDayChange(CalendarView view, int year, int month, int day) {
            if(view.getDate() != lastDate) {
                lastDate = view.getDate();
                MainActivity.this.year = year;
                MainActivity.this.month = month;
                MainActivity.this.day = day;
                makeToast();
                currentArea = getItemArea(upX, upY);
                isInitialized = true;
            }
        }
    });

    listView = (ListView)calendar.findViewById(android.R.id.list);

}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            downX = (int)event.getX();
            downY = (int)event.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            break;
        case MotionEvent.ACTION_UP:
            upX = (int)event.getX();
            upY = (int)event.getY();

            if (areaList.size()==0) {
                generateList();
            }

            // make sure it's not move
            if (Math.abs(downX-upX)<3 && Math.abs(downY-upY)<3) {
                ItemArea area = getItemArea(upX, upY);

                // on application start up and click the current date, there are stored status.
                if (currentArea==null || !isInitialized) {
                    long time = calendar.getDate();
                    Calendar currentCalendar = new GregorianCalendar();
                    currentCalendar.setTimeInMillis(time);
                    year = currentCalendar.get(Calendar.YEAR);
                    month = currentCalendar.get(Calendar.MONTH);
                    day = currentCalendar.get(Calendar.DAY_OF_MONTH);
                    makeToast();
                }

                if (area!=null && area.equals(currentArea)) {
                    makeToast();
                }
            } else {
                // FIXME: still have bug when drag/scroll back
                // it's move event, list view will scroll up/down, and update the y
                if (currentArea!=null) {
                    if (downY<upY) {
                        // move down
                        int times = (upY-downY)/listItemHeight;
                        currentArea.top+=listItemHeight*(times+1);
                        currentArea.bottom+=listItemHeight*(times+1);
                    } else {
                        // move up
                        int times = (downY-upY)/listItemHeight;
                        currentArea.top-=listItemHeight*(times+1);
                        currentArea.bottom-=listItemHeight*(times+1);
                    }
                }
            }
            break;
    }

    return super.dispatchTouchEvent(event);
}

private void generateList() {
    listItemCount = listView.getChildCount();
    listItemHeight = listView.getChildAt(0).getHeight();
    listItemWidth = listView.getChildAt(0).getWidth();
    listView.getChildAt(0).getLocationOnScreen(startPoint);

    int deltaX = (int)(listItemWidth/7.0);

    for (int i=0; i< listItemCount; i++) {
        for (int j=0; j<7; j++) {
            areaList.add(new ItemArea(startPoint[0]+deltaX*j, startPoint[1]+listItemHeight*i,
                    startPoint[0]+deltaX*(j+1), startPoint[1]+listItemHeight*(i+1)));
        }

    }

}

private void makeToast() {
    Log.d("TAG", "do your job here");
    lastX = upX;
    lastY = upY;

    Toast.makeText(this, "" + day + "/" + month + "/" + year, Toast.LENGTH_LONG).show();
}

private ItemArea getItemArea(int x, int y) {
    for (int i=0; i < areaList.size(); i++) {
        if (areaList.get(i).contains(x, y)) {
            return areaList.get(i);
        }
    }
    return null;
}

private class ItemArea {
    int left;
    int top;
    int right;
    int bottom;

    ItemArea(int left, int top, int right, int bottom) {
        this.left = left;
        this.top = top;
        this.right = right;
        this.bottom = bottom;
    }

    boolean contains(int x, int y) {
        return x>=left && x<=right && y>=top && y<=bottom;
    }

    boolean equals(ItemArea area) {
        return area!=null &&
                this.right==area.right &&
                this.left==area.left &&
                this.bottom==area.bottom &&
                this.top==area.top;
    }
}

<强>更新

在API 22(android 5.1)中,android已将CalendarView更改为MATERIAL。根本没有ListView,请检查CalendarView MODE_MATERIALcalendarViewMode

中的代码

因此,如果使用默认样式,上述代码将失败,唯一的方法是强制使用CalendarViewLegacyDelegate,这意味着将calendarViewMode设置为MODE_HOLO。你可以通过添加style="@android:style/Widget.CalendarView"来实现这一点,就像这样:

<CalendarView
    android:id="@+id/calendarforstart"
    style="@android:style/Widget.CalendarView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

但是你会丢失你的素材UI。您可以根据自己的需要扩展Widget.CalendarView,但我认为它距离材料还很远。