S60上的带鱼眼放大效果列表

来源:互联网 发布:知金教育是什么 编辑:程序博客网 时间:2024/04/29 07:18

首先要强烈鄙视一下给Nokia S60设计UI接口团队——用到现在最恶心的,文档最不完整的UI框架了。

 

然后要感谢一下Forum Nokia Wiki 上的 Mayank, 提供了一个鱼眼列表的范例程序,虽然有bug。

 

http://wiki.forum.nokia.com/index.php/How_to_implement_fisheye_view

 

源代码可在上面地址下到

 

这里说一下这个范例里的bug

 

如果列表很大,超出屏幕,那么最后一个可能没法显示全。

 

原因是父类的View只能按照等高度的item布局,鱼眼放大效果其实是在绘制过程中的hack方法,实际上view不知道我们放大了某个item。

 

修复方法是,如果这个焦点在当前屏幕内的最后一行(注意不是全部列表最后一行),那么改变调整逻辑,把列表下移腾出放大空间,改成列表上移。

 

这个调整后,范例里的Relign方法就没用了,改善了处理效率。

 

最后改进一下列表的Draw方法。

 

List控件的Draw方法必调用列表项绘制方法,否则是看不到内容的。

 

但是没必要全部都绘制一边。只要画当前屏幕开始项目和结束项目就行了。

 

这些改动,都已经放到wiki上了。不过需要手工覆盖到范例上。

 

void CCustomListItemDrawer::DrawActualItem(TInt aItemIndex,const TRect& aActualItemRect,
TBool aItemIsCurrent, TBool /*aViewIsEmphasized*/,
TBool /*aViewIsDimmed*/, TBool aItemIsSelected) const
{
TInt selectedIndex = iListBox.CurrentItemIndex();
TInt itemIndex = aItemIndex;
TRect itemRect = aActualItemRect;

if( selectedIndex == iListBox.BottomItemIndex() ) {
// selected item is at the bottom
itemRect.iTl.iY -= iItemCellSize.iHeight;
if( itemIndex < selectedIndex ) {
itemRect.iBr.iY -= iItemCellSize.iHeight;
}
} else {
if (aItemIsCurrent) {
itemRect.iBr.iY += iItemCellSize.iHeight;
} else if (itemIndex > selectedIndex) {
// Lets move the following entries down to accomodate fish eye window
itemRect.iTl.iY += iItemCellSize.iHeight;
itemRect.iBr.iY += iItemCellSize.iHeight;
}
}
// Call the Actual draw function
}
 
CFishEyeListBox::CFishEyeListBox()
:CAknSingleHeadingStyleListBox()
{
}
 
/**
* Override the default item drawer by our own
*/

void CFishEyeListBox::CreateItemDrawerL()
{
CColumnListBoxData* columnData = CColumnListBoxData::NewL(); // CColumnListBoxItemDrawer owns columnData
const CFont* myFont = CEikonEnv::Static()->DenseFont();
iItemDrawer = new(ELeave) CCustomListItemDrawer(Model(), myFont, columnData, *this);
}
 
/**
* To handle the item scrolling
*/

TKeyResponse CFishEyeListBox::OfferKeyEventL(const TKeyEvent& aKeyEvent,
TEventCode aType) {
if (EEventKey == aType) {
switch (aKeyEvent.iCode) {
// Down arrow
case EKeyDownArrow: {
ScrollDown();
DrawDeferred();
return EKeyWasConsumed;
}
 
// Up arrow
case EKeyUpArrow: {
ScrollUp();
DrawDeferred();
return EKeyWasConsumed;
}
 
default:
return CEikTextListBox::OfferKeyEventL(aKeyEvent, aType);
}
}
return EKeyWasNotConsumed;
}
 
void CFishEyeListBox::ScrollDown(void) {
TInt currIndex = CurrentItemIndex();
if( currIndex < Model()->NumberOfItems() - 1 ) {
SetCurrentItemIndex( currIndex + 1);
} else {
// Lets do circular scrolling by setting current index as the first item
SetCurrentItemIndex(0);
}
ScrollToMakeItemVisible( CurrentItemIndex() );
}
void CFishEyeListBox::ScrollUp(void) {
TInt currIndex = CurrentItemIndex();
if( currIndex > 0 ) {
SetCurrentItemIndex( currIndex - 1);
} else if( Model()->NumberOfItems() > 0) {
// Lets do circular scrolling by setting current index as the last item
SetCurrentItemIndex(Model()->NumberOfItems() - 1);
}
ScrollToMakeItemVisible( CurrentItemIndex() );
}
 
/**
* Override the draw function of the list
* Otherwise it will apply a default background instead of transparent
* On s60 3rd mr, there will be bugs when the list is large than default. ( A ugly white bar at the end of list)
*/

void CFishEyeListBox::Draw(const TRect& aRect) const {
CListBoxView* view = View();
TInt start = view->TopItemIndex();
TInt end = view->BottomItemIndex();
for( TInt i = start; i <= end; i++ ) {
view->DrawItem(i);
}
}

 

 

原创粉丝点击