修改TileList元件的ScrollBar位置

開始使用Flex開發不久,就遇到了一個不簡單的設計,就是設計師設計了一個把ScrollBar從預設的右邊移到左邊去的TileList,本以為這應該很常見,搜尋了一下竟找不到現成的改法,索性只好自己新手駕駛了。

TileList是繼承自ListBase的,而ListBase裡面可以找到verticalScrollBarhorizontalScrollBar這兩個唯一跟scrollbar有關的class property,改變這兩個物件的位置的時候,發現就可以移動scrollbar的位置了,就這麼簡單阿(?)。下面是修改後的code,簡單說明:新建的自訂元件LeftScrollBarTileList繼承自TileList,在複寫updateDisplayList方法的地方,判斷verticalScrollBar是否有被產生出來,有的話,就把它拉到最左邊,也就是verticalScrollBar.x = 0。

LeftScrollBarTileList.as
/* Copyright (c) 2009 blog.mediakid.org. All Rights Reserved. */
package {
    import mx.controls.TileList;
    public class LeftScrollBarTileList extends TileList {
        public function LeftScrollBarTileList() {
            super();
        }
        protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
                super.updateDisplayList(unscaledWidth, unscaledHeight);
                // 確認vertical是否存在
                if (verticalScrollBar && verticalScrollBar.visible){
                    verticalScrollBar.x = 0; // 移動scrollbar
                }
        }
    }
}
使用元件的主程式main.mxml
<?xml version="1.0"?>
<!--
//  Copyright (c) 2009 blog.mediakid.org. All Rights Reserved.
-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" fontSize="12" 
backgroundColor="#F0F0F0" 
horizontalScrollPolicy="off"
verticalScrollPolicy="off"
width="450"
height="350"
>

<mx:Script>
<![CDATA[
import mx.collections.XMLListCollection;
private var xml:XMLList = 
<>
<content>1</content> 
<content>2</content>
<content>3</content> 
<content>4</content>
<content>5</content> 
<content>6</content>
<content>7</content> 
<content>8</content>
<content>9</content> 
<content>10</content>
<content>11</content> 
<content>12</content>
<content>13</content>
</>;
[Bindable] private var ac : XMLListCollection = new XMLListCollection(xml);
]]>
</mx:Script>
<mx:Panel 
title="Reposition the scrollbar" 
height="300" 
width="400" >
<local:LeftScrollBarTileList
id="scroll"
dataProvider="{ac}"
xmlns:local="*" 
columnCount="2"
rowHeight="80"
borderStyle="none"
width="100%"
height="100%"
alternatingItemColors="[#FFFFFF,#CCCCCC,#999999]"
/>
</mx:Panel>
</mx:Application>

問題來了,雖然scrollbar是移到左邊了,可是TileList的右側仍然保留了預設的scrollBar的空間,事實上移動到左邊的scrollbar也壓到了一部分的TileList。

繼續trace發現,顯示"被拖曳內容"的是容器listContent,listContent上面還加了一個maskShape遮罩,所以scrollbar被移到左邊以後,這兩個物件的位置也要一併往右移動一些。只有這樣還不夠,listContent在更新位置的時候都會加上位移量leftOffset,所以leftOffset也要加上位移量,否則的話,每次一更新位置,listContent就會又跑回原來的位置。新增修改如下:
/* Copyright (c) 2009 blog.mediakid.org. All Rights Reserved. */
package {
    import mx.controls.TileList;
    public class LeftScrollBarTileList extends TileList {
        public function LeftScrollBarTileList() {
            super();
        }
        protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
                super.updateDisplayList(unscaledWidth, unscaledHeight);
                // vertical
                if (verticalScrollBar && verticalScrollBar.visible){
                    verticalScrollBar.x = 0; // 移動scrollbar
                    this.listContent.x =  verticalScrollBar.width; // 移動被拖曳內容
                    this.maskShape.x = this.listContent.x; // 移動被拖曳內容的mask
                    this.listContent.leftOffset = verticalScrollBar.width; // 設定被拖曳內容的位移量,如果是垂直的scrollbar則用topOffset
                }
        }
    }
}
效果Live Demo: 修改後的效果看似是ok的,但沒有完整的trace完全部的code,所以不曉得是否有更好的解法。而這個改法雖是以TileList為例,但我想對於所有繼承自ListBase的元件都是一樣的作法吧。以上方法同理也可以用來把預設位於下方的horizontalScrollBar改成位於上方。

3 意見

  1. p3p3

    09/8/20 下午6:39

    我只是納悶,這樣不就破壞了user習慣??

    Scrollbar在右邊也較符合右手操作的人

    一邊卷動一邊閱讀本文,都卡在左邊~似乎造成干擾!

  2. mediakid

    09/8/21 上午9:58

    在我用我們設計師的一句話讓我們乖乖安靜之前,先說說我的意見 :)

    我個人是覺得干擾是還好耶,主要是會衝擊使用者原來的使用習慣,可是衝擊也不見得是全然不好的,就好像這次UI Gathering討論到的一個問題,有人問符合使用者習慣和完全創新的介面要怎麼取捨,主講者是說這沒什麼標準,看主事者怎麼決定。我個人也是這樣覺得,大家都說要做"易學易用"的介面,可是我是覺得"易學易用"只是選項之一,"難學"也OK阿,重點是使用者覺得花費在學習的時間心力是值得的就好了,敢讓使用者花費得更多的心力那是因為你可以給他更多,大家都說光只有絢麗的介面沒有用,但吸引人目光也是絢麗的功能,所以就是看情況吧。

    好吧,那我們設計師是怎麼說的呢? "這個產品用的是觸控式螢幕,TA鎖定的是美國人,而美國有一半以上的左撇子。"

  3. mitch

    09/9/17 上午8:30

    阿~原來阿德跑來嗆聲!我一開始看也一直不懂白大為什麼要把它搞到左邊去,原本以為這個是大師級人物的作品,當然不可能理解背後博大深奧的精髓,結果是因為鎖定左撇子族群喔,突然讓小弟頓悟了~哈哈~~~