Java pour iPhone avec iSpectrum : tutoriel sur UIPageControl et UIScrollView

Java pour iPhone avec iSpectrum : tutoriel sur UIPageControl et UIScrollView

Dans ce tutoriel on explique comment implémenter un défilement de pages par des mouvement de balayage (swiping gesture) ainsi qu'à ajouter un widget page control qui permet de savoir sur quelle page on se trouve.

Introduction

Ce tutoriel présente 2 nouvelles classes UIKit : UIScrollView and UIPageControl. Une scroll view est utilisée pour afficher un contenu qui est plus grand que la taille allouée pour cette vue (habituellement, l'écran tout entier). Elle prend en charge les touches de l'utilisateur et permet de faire défiler la vue par des gestes de balayage (swiping gestures) ou de zoomer par pincement (pinch to zoom gesture). Elle ne dessine rien si ce n'est des barres de défilement verticales et horizontales et est utilisée pour contenir d'autres vues. Le composant graphique (widget) de contrôle de page représente l'ensemble des vues affichables par une ligne de point dont le blanc désigne la vue affichée. Un exemple d'utilisation peut être observé dans la gestion des onglets de Safari pour iPhone.

Pré-requis

Ce tutoriel ne couvre PAS la mise en place d'un projet FlexyCore dans Eclipse.

Veuillez vous référer à la section documentation pour plus d'informations (http://www.flexycore.com/ispectrum-doc-prerequesites.html).

Vous trouverez également sur le site une section sur l'utilisation des codes exemples disponibles (http://www.flexycore.com/ispectrum-doc-run-and-debug-sample-codes.html). Vous pouvez donc récupérer le code source de ce tutoriel dans le module PageControlExample.

Une connaissance des mécanismes de bases de UIKit est aussi nécessaire (MVC, delegates, TableView, NavigationController).

Description

Cette exemple d'application permet à l'utilisateur d'utiliser un mouvement de balayage afin de naviguer entre 4 pages monochromes. Ce geste fait apparaître la page suivant avec une animation de translation. Pendant ce temps de composant contrôle de page indique quelle est la page courante avec un point blanc.

MyView

Cette vue personnalisée est faite de 2 sous-vues : une scroll view et une vue page control.

public class MyView extends UIView {
    /**
    * Fields
    */
    private Vector<UIViewController> viewControllers;
    private UIScrollView scrollView;
    private UIPageControl pageControl;

Un Vector contient la liste de nos vues monochromes qui sont destinées à être placées dans la scroll view. Voici comment elles sont crées :

    public MyView(){
        super();
        initWithFrame(CGRect.CGRectMake(0, 0, 320, 380));

        /*
        * Views construction
        */
        Vector<UIColor> colors = new Vector<UIColor>();
        colors.add(UIColor.blueColor());
        colors.add(UIColor.whiteColor());
        colors.add(UIColor.redColor());
        colors.add(UIColor.greenColor());

        viewControllers = new Vector<UIViewController>();

        for(int i=0; i<colors.size(); i++)
        {
            // new UIViewController
            UIViewController viewCtr = new UIViewController();
            viewCtr.init();

            // new UIView
            UIView view = new UIView();
            view.initWithFrame(CGRect.CGRectMake(0, 0, 320, 380));
            view.setBackgroundColor(colors.elementAt(i));

            // Add a label
            UILabel label = new UILabel();
            label.initWithFrame(CGRect.CGRectMake(0, 100, 320, 40));
            label.setBackgroundColor(UIColor.clearColor());
            label.setTextColor(UIColor.blackColor());
            label.setTextAlignment(UITextAlignment.UITextAlignmentCenter);
            label.setText(\"PAGE \" + (i+1));
            view.addSubview(label);
            viewCtr.setView(view);
            viewControllers.add(viewCtr);
        }

Un Uilabel est ajouté sur la page pour indiquer de quelle page il s'agit afin de constater que le page control renvoit une bonne valeur.

        /*
        * PageControl
        */
        pageControl = new UIPageControl(){
            @Override
            public void controlEvent() {
                changePage(this.currentPage());
            }
        };
        pageControl.initWithFrame(CGRect.CGRectMake(0, 385, 320, 31));
        pageControl.setNumberOfPages(viewControllers.size());
        pageControl.setCurrentPage(0);
         pageControl.addTargetActionForControlEvents(UIControlEvents.UIControlEventValueChanged);
        addSubview(pageControl);

Le contrôle de page est initialisé pour gérer 4 pages, en commençant à la page 0 et réagit à l'évènement UIControlValueChanged. Quand cet événement ce produit, sa méthode controlEvent() est appelée. C'est de cette manière que le paradigme UIKit Cible-Action a été adapté en Java. Cet événement sera déclenché à chaque fois que l'attribut currentPage sera changé. Nous verrons quand cela est le cas dans la section section suivante avec le délégué de scroll view. Lorsque que cet événement survient, on appelle la méthode changePage().

    /**
    * Change content offset of the scrollView to the new current page.
    */
    public void changePage(int page){
        CGPoint contentOffset = new CGPoint();
        contentOffset.init(320*page, 0);
        scrollView.setContentOffsetAnimated(contentOffset, true);
    }

Comme le commentaire le laisse supposer, la méthode consiste à modifier l'offset de la scroll view qui détermine quel partie des vues contenues va être affichée. L'offset est choisi pour être un multiple de la largeur de l'écran (320), ce qui est aussi la largeur des sous vues. Ce qui fait que les pages sont affichée une à une entièrement.

Revenons à présent au constructeur : on crée maintenant la scroll view.

     /*
     * Scroll properties setting
     */
        scrollView = new UIScrollView();
        scrollView.initWithFrame(CGRect.CGRectMake(0, 0, 320, 380));
        float W = this.frame().getSize().getWidth()*viewControllers.size();
        float H = this.frame().getSize().getHeight();
        scrollView.setContentSize(new CGSize().init(W,H));
        scrollView.setPagingEnabled(true);
        scrollView.setShowsHorizontalScrollIndicator(false);
        scrollView.setShowsVerticalScrollIndicator(false);
        scrollView.setScrollsToTop(false);
        scrollView.setUIScrollViewDelegate(new ScrollDelegate(this));
        addSubview(scrollView);

La frame de la view est initialisée à plein écran ainsi que l'attribut contentSize afin de définir la zone d'affichage des sous vues. Ensuite pagingEnabled est mis a true ce qui a pour effet d'arrêter l'animation de défilement des pages sur des multiples de la taille de la vue. Comme cela correspond aux sous vues, on a un effet "page par page". Ensuite, on associe un delegate personnalisé puis on l'ajoute à la vue courante. Enfin on charge toutes les pages.

        // Load all views
        for(int i=0; i<viewControllers.size(); i++){
            loadScrollViewWithPage(i);
        }

Voyons de quoi il s'agit :

    public void loadScrollViewWithPage(int page){
        if(page < 0) return;
        if(page >= viewControllers.size()) return;

        UIViewController viewController = viewControllers.elementAt(page);
        if(viewController == null) return;

        // add the controller's view to the scroll view
        if(viewController.view().superview() == null){
            CGRect frame = this.frame();
            frame.setOrigin(new CGPoint().init(frame.getSize().getWidth()*page, 0));
            viewController.view().setFrame(frame);
            scrollView.addSubview(viewController.view());
        }
    }

Cette méthode met en place les sous vues, côte à côte dans la contentView du scroll view à partir des écrans créés et mis dans le Vector viewControllers.

ScrollDelegate

Seule une méthode d'UIScrollViewDelegate est implantée :

    @Override
    public void scrollViewDidEndDecelerating(UIScrollView scrollView) {
        CGPoint point = view.getScrollView().contentOffset();
        int page = 0;

        switch((int) point.getX()){
            case 0:
                break;

            case 320:
                page = 1;
                break;

            case 640:
                page = 2;
                break;

            case 960:
                page = 3;
                break;
        }

        view.getPageControl().setCurrentPage(page);
    }

Cette méthode callback est appelée à la fin de l'animation de changement de page qu'on a activée précédemment en mettant pagingEnabled à true. Dans cette méthode on regarde l'offset du scroll view pour savoir quelle est la page courante et ainsi mettre à jour le page control. Ceci va provoquer un évènement de type UIControlValueChanged. L'image suivante montre ce qu'il se passe lorsqu'on appelle setCurrentPage() est appelée.

Conclusion

Vous savez à présent comment intégrer des mouvement de balayage dans vos applications pour gérer plus pages en utilisant la classe UIScrollView and en l'associant avec le page control. Vous pourrez donner grâce à cela un rendu iPhone standard à vos applications.

A voir également
Ce document intitulé « Java pour iPhone avec iSpectrum : tutoriel sur UIPageControl et UIScrollView » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous