在Workspace.Java类实现,相关方法有:
1) computeScroll():重写了父类的computeScroll();主要功能是计算拖动的位移量、更新背景、设置要显示的屏幕(setCurrentScreen(mCurrentScreen);)。
2) dispatchDraw():重写了父类的dispatchDraw();主要功能是判断抽屉是否打开、绘制指定的屏幕,可以绘制当前一屏,也可以绘制当前屏幕和下一屏幕,也可以绘制所有的屏幕,这儿的绘制指显示屏幕上的child(例如:app、folder、Wiget)。和computeScroll()中的setCurrentScreen(mCurrentScreen);方法配合使用可以实现屏幕的拖动多少显示多少的功能。
3) onMeasure():重写了父类的onMeasure();主要功能是设置屏幕的显示大小。由每个child的measure()方法设置。
4) onLayout():重写了父类的onLayout();主要功能是设置屏幕的显示位置。由child的layout()方法设置。
5) onInterceptTouchEvent():重写了父类的onInterceptTouchEvent();主要功能是在onTouchEvent()方法之前处理touch事件。包括:down、up、move事件。
用xy记录鼠标移动时的坐标值;
mLastMotionX和mLastMotionY记录了上次鼠标按下时的XY值,在ACTION_MOVE中赋值;
xDiff和yDiff记录xy与mLastMotionX、mLastMotionY差值的绝对值;
touchSlop为系统定义的标准值,初值为16;
当xDiff和yDiff大于touchSlop时就认为界面拖动了足够大的距离,屏幕就可以移动了;
当onInterceptTouchEvent()返回true时进入onTouchEvent()。
6) onTouchEvent():重写了父类的onTouchEvent();主要功能是处理onInterceptTouchEvent()返回值为true时传递过来的touch事件。
l;
Creating a Calendar
1:You create a calendar object by specifying an identifier for the calendar you want. Mac OS X provides data for several different calendars—Buddhist, Chinese, Gregorian, Hebrew, Islamic, and Japanese—specified by constants in NSLocale.
NSCalendar *japaneseCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSJapaneseCalendar];
2:You can get the calendar for the user's preferred locale (or in general from any NSLocale object) using the key NSLocaleCalendar,
NSCalendar *usersCalendar = [[NSCalendar alloc] initWithCalendarIdentifier: [[NSLocale currentLocale] objectForKey:NSLocaleCalendar]];
3:or most easily using the NSCalendar method currentCalendar. The following code fragment shows how to create a calendar object for the Japanese calendar, and for the current user:
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
Calendrical Calculations
取得时间差
NSDate *startDate = ...; NSDate *endDate = ...; NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; unsigned int unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit; NSDateComponents *components = [gregorian components:unitFlags fromDate:startDate toDate:endDate options:0]; int months = [components month]; int days = [components day];
api:
1:从NSDate 中取得NSDateComponents 对象
Returns a NSDateComponents object containing a given date decomposed into specified components.
- (NSDateComponents *)components:(NSUInteger)unitFlags fromDate:(NSDate *)date
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit; NSDate *date = [NSDate date]; NSDateComponents *comps = [gregorian components:unitFlags fromDate:date];
2:取得时间差
Returns, as an NSDateComponents object using specified components, the difference between two supplied dates.
- (NSDateComponents *)components:(NSUInteger)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options:(NSUInteger)opts
NSDate *startDate = ...; NSDate *endDate = ...; unsigned int unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit; NSDateComponents *comps = [gregorian components:unitFlags fromDate:startDate toDate:endDate options:0]; int months = [comps month]; int days = [comps day];
3:在给定的NSDate 上增加几天,几年等。。。。
Returns a new NSDate object representing the absolute time calculated by adding given components to a given date.
- (NSDate *)dateByAddingComponents:(NSDateComponents *)comps toDate:(NSDate *)date options:(NSUInteger)opts
NSDate *currentDate = [NSDate date]; NSDateComponents *comps = [[NSDateComponents alloc] init]; [comps setMonth:2]; [comps setDay:3]; NSDate *date = [gregorian dateByAddingComponents:comps toDate:currentDate options:0]; [comps release];
4:取得一个指定的时间
Returns a new NSDate object representing the absolute time calculated from given components.
- (NSDate *)dateFromComponents:(NSDateComponents *)comps
NSDateComponents *comps = [[NSDateComponents alloc] init]; [comps setYear:1965]; [comps setMonth:1]; [comps setDay:6]; [comps setHour:14]; [comps setMinute:10]; [comps setSecond:0]; NSDate *date = [gregorian dateFromComponents:comps]; [comps release];
Calendar Units
Specify calendrical units such as day and month.
enum {
NSEraCalendarUnit = kCFCalendarUnitEra,
NSYearCalendarUnit = kCFCalendarUnitYear,
NSMonthCalendarUnit = kCFCalendarUnitMonth,
NSDayCalendarUnit = kCFCalendarUnitDay,
NSHourCalendarUnit = kCFCalendarUnitHour,
NSMinuteCalendarUnit = kCFCalendarUnitMinute,
NSSecondCalendarUnit = kCFCalendarUnitSecond,
NSWeekCalendarUnit = kCFCalendarUnitWeek,
NSWeekdayCalendarUnit = kCFCalendarUnitWeekday,
NSWeekdayOrdinalCalendarUnit = kCFCalendarUnitWeekdayOrdinal
};
1) 大家都知道workspace是有celllayout组成。Celllayout被划分为了4行4列的表格,用Boolean类型的mOccupied二维数组来标记每个cell是否被占用。在attrs.xml中定义了shortAxisCells和longAxisCells分别存储x轴和y轴方向的cell个数。在Celllayout构造函数中初始化。
2) 内部类CellInfo为静态类,实现了ContextMenu.ContextMenuInfo接口。其对象用于存储cell的基本信息。
VacantCell类用于存储空闲的cell,用到了同步机制用于管理对空闲位置的操作。所有的空cell都存储在vacantCells中。
cellX和cellY用于记录cell的位置,起始位0。如:(0,0) (0,1),每一页从新开始编号。
clearVacantCells作用是将Vacant清空:具体是释放每个cell,将list清空。
findVacantCellsFromOccupied从存放cell的数值中找到空闲的cell。在Launcher.Java中的restoreState方法中调用。
3) mPortrait用于标记是横屏还是竖屏,FALSE表示竖屏,默认为FALSE。
4) 修改CellLayout页面上cell的布局:
CellLayout页面上默认的cell为4X4=16个,可以通过修改配置文件来达到修改目的。
在CellLayout.Java类的CellLayout(Context context, AttributeSet attrs, int defStyle)构造方法中用变量mShortAxisCells和mLongAxisCells存储行和列。
其值是在自定义配置文件attrs.xml中定义的,并在workspace_screen.xml中赋初值的,初值都为4,即4行、4列。可以在workspace_screen.xml修改对应的值。
注意:CellLayout构造方法中从attrs.xml中获取定义是这样的:mShortAxisCells = a.getInt(R.styleable.CellLayout_shortAxisCells, 4);当workspace_screen.xml中没有给定义的变量赋值时,上面的4就起作用。
5)下面的分析转载自:http://blog.csdn.net/netpirate/archive/2009/06/05/4245445.aspx
Launcher(主屏/待机) App的BUG: 没有初始化定义CellLayout中屏幕方向的布尔值参数
Launcher App:\cupcake\packages\apps\Launcher
待机画面分为多层,桌面Desktop Items在\res\layout-*\workspace_screen.xml中置:
<com.android.launcher.CellLayout
... ...
launcher:shortAxisCells="4"
launcher:longAxisCells="4"
... ...
/>
表示4行4列
再看看 com.android.launcher.CellLayout ,其中有定义屏幕方向的参数,
private boolean mPortrait;
但是一直没有初始化,也就是mPortrait=false,桌面的单元格设置一直是以非竖屏(横屏)的设置定义进行初始化。
再来看看横屏和竖屏情况下的初始化不同之处,就可以看出BUG了。
boolean[][] mOccupied;//二元单元格布尔值数组
if (mPortrait) {
mOccupied = new boolean[mShortAxisCells][mLongAxisCells];
} else {
mOccupied = new boolean[mLongAxisCells][mShortAxisCells];
}
如果我们满屏显示桌面(横向和纵向的单元格数不一致),而不是默认的只显示4行4列,则mShortAxisCells = 4, mLongAxisCells = 5,数组应该初始化是:new boolean[4][5],但是实际是按照非竖屏处理,初始化成了new boolean[5][4],会产生数组越界异常。
可以在构造函数中,添加通过屏幕方向初始化mPortrait,代码如下:
public CellLayout(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
mPortrait = this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;// 新增代码
... ...