2009-11-02 5 views
3

J'essaie d'avoir une interface utilisateur en plein écran avec un en-tête fixe (un gestionnaire avec quelques champs) et un contenu défilant (une liste de champ personnalisé). L'idée est d'émuler une sorte de liste déroulante.Blackberry VerticalFieldManager avec taille fixe: Défilement numéro

Pour cela, j'ai fait un VerticalFieldManager personnalisé qui accepte un maxHeight (la hauteur de l'écran - la hauteur de l'en-tête).

J'ai les problèmes suivants:

  • Les flèches de défilement ne montrent pas (jamais)
  • Sur OS 4.7 (Storm), je peux faire défiler plus bas que le dernier élément, jusqu'à avoir rien sur mon écran mais l'en-tête.

Mon code doit compiler avec le JDE 4.2.1 & 4.7 et fonctionner sur Pearl et Storm. (au pire, je pourrais avoir deux versions de cette classe)

Je soupçonne que les deux problèmes sont liés. Je fais probablement quelque chose de mal. J'ai regardé quelques exemples/forum et j'ai toujours trouvé une solution/code similaire. Est-ce que vous pouvez me dire ce que j'ai fait de mal?

/** 
* custom class, so we can set a max height (to keep the header visible) 
*/ 
class myVerticalFieldManager extends VerticalFieldManager{ 
private int maxHeight = 0; 

myVerticalFieldManager(int _maxHeight){ 
    super(
    //this provoc an "empty scrollable zone" on Storm 
    // but if you don't put it, on other OS, the vertical manager does not scroll at all. 
    Manager.VERTICAL_SCROLL 

    | Manager.VERTICAL_SCROLLBAR 
    ); 
    maxHeight = _maxHeight; 
} 


protected void sublayout(int width, int height){ 
     super.sublayout(width, getPreferredHeight()); 
     setExtent(width, getPreferredHeight()); 
} 

public int getPreferredWidth() { 
    return Graphics.getScreenWidth(); 
} 

/** 
* allow the manager to use all the given height. (vs auto Height) 
*/ 
public boolean forceMaxHeight = false; 
public int getPreferredHeight() { 
    if (forceMaxHeight) return maxHeight; 
    int m = super.getPreferredHeight(); 
    if (m > maxHeight) m = maxHeight; 
    return m; 
}  

//////////////////////////////////////////////////////////////////////////// 

protected boolean isUpArrowShown(){ 
    //TODO: does not seem to work (4.2.1 emulator & 4.5 device). (called with good return value but the arrows are not painted) 
    int i = getFieldWithFocusIndex(); 
    //Trace("isUpArrowShown " + i); 
    return i > 0; 
    // note: algo not correct, cause the up arrow will be visible event when no field are hidden. 
    //  but not so bad, so the user "know" that he can go up. 
} 

protected boolean isDownArrowShown(){ 
    int i = getFieldWithFocusIndex(); 
    return i < getFieldCount(); 
} 

//////////////////////////////////////////////////////////////////////////// 
// note : since 4.6 you can use 
// http://www.blackberry.com/developers/docs/4.6.0api/net/rim/device/api/ui/decor/Background.html 

public int myBackgroundColor = 0xffffff; 
protected void paint(Graphics g){ 
    g.setBackgroundColor(myBackgroundColor); 
    // Clears the entire graphic area to the current background 
    g.clear(); 
    super.paint(g); 
} 


} 

toute aide est la bienvenue.

Répondre

4

donc,

Je suis venu avec cette solution de contournement pour le problème « zone scrollable vide » STORM il est laid et ne permet pas une coutume ScrollChangeListener, mais il travaille sur Pearl & Tempête

implements ScrollChangeListener 

//in constructor: 

    setScrollListener(null); 
    setScrollListener(this); 


private boolean MY_CHANGING_SCROLL = false; 
public void scrollChanged(Manager manager, int newHorizontalScroll, int newVerticalScroll){ 
    if (!MY_CHANGING_SCROLL){ 
    MY_CHANGING_SCROLL = true; 
    myCheckVerticalScroll(); 
    MY_CHANGING_SCROLL = false; 
    }  
} 


protected int myMaxVerticalScrollPosition(){ 
    int vh = getVirtualHeight(); 
    int h = getHeight(); 
    if (vh < h) return 0; // no scroll 
    return vh - h; // don't scroll lower than limit. 
} 

protected void invCheckVerticalScroll() { 
    int i = getVerticalScroll(); 
    int m = myMaxVerticalScrollPosition(); 
    if (i > m){ 
     i = m; 
     setVerticalScroll(i); 
    } 
} 

Je suis toujours à la recherche d'une solution au problème des flèches de défilement ... Si quelqu'un a une idée ...

+2

Je trouve que vous pouvez avoir le même résultat par un moyen plus facile : - créer l'écran avec le drapeau NO_SCROLL. (Il me manquait ça); - ajouter l'en-tête comme champ normal; - ajouter un vfm avec tous vos trucs; -> la flèche apparaîtra et l'en-tête restera là où il devrait être. De plus, vous n'avez pas l'ombre laide dans la zone "setTitle()" – Loda

2

Vous pouvez utiliser la méthode setBanner() au lieu d'un dd pour votre en-tête. Ensuite, vous pouvez ajouter un VerticalFieldManager par défaut à l'écran et il défilera normalement mais ne cachera pas l'en-tête. Notez que le gestionnaire de délégué MainScreen est un VerticalScrollManager donc vous n'aurez peut-être pas besoin d'un second vfm.

HorizontalFieldManager hfm = new HorizontalFieldManager(); 
setBanner(hfm) 

add(new ButtonField("Hello 1"); 
add(new ButtonField("Hello 2"); 

...

+0

le problème avec setTitle() est que la lib ajoute une ombre 4-5px très moche sous la zone de titre. J'avoue: je n'ai pas essayé setBanner(). – Loda

0

Hey je l'ai fait la même chose en utilisant un HorizontalFieldManager qui contient une image et un titre

header_img = Bitmap.getBitmapResource("header.png"); 
      title = new LabelField("Welcome",LabelField.FIELD_RIGHT); 
      header_manager = new HorizontalFieldManager() 
      { 
       protected void paint(net.rim.device.api.ui.Graphics graphics) 
        { 
         int y = this.getVerticalScroll();          
         graphics.drawBitmap(0, y, header_img.getWidth(), header_img.getHeight(), header_img, 0, 0); 
         graphics.setColor(Color.LEMONCHIFFON); 
         super.paint(graphics); 
        } 

        protected void sublayout(int maxWidth, int maxHeight) 
        {      
         super.sublayout(Display.getWidth(), 240); 

         Field field = title; 
         layoutChild(field, title.getWidth(), title.getHeight()); 
         setPositionChild(field, (Display.getWidth()/2) -10, 13); 
         setExtent(Display.getWidth(),55); 

        } 
      }; 
      header_manager.add(title); 
Questions connexes