2015年

2月

15日

Cocos2d-x Ver 3.x TableView 画面遷移と行表示

TableViewをクリックしたら画面遷移して該当の行番目が表示する方法
UserDefaultを使いrow行番号を保存し次ページにてUserDefaultから行番号を読み込みrow行番号を表示しています。PlistやSQLiteなどを使えばリストデータを表示することが容易に出来ます。

Cocos2dx 3.x C++言語

Overview.hを次のように変更してみてください。

#ifndef __TableView01__Overview__

#define __TableView01__Overview__


#include <iostream>

#include "cocos2d.h"

#include <extensions/cocos-ext.h>


USING_NS_CC;

using namespace extension;


class Overview : public Layer,

public TableViewDataSource,

public TableViewDelegate

{

    Size window_size;

public:

    static cocos2d::Scene* createScene();

    virtual bool init();

    

    //TableViewDataSourceの抽象メソッド

    virtual Size cellSizeForTable(TableView* table);

    virtual TableViewCell* tableCellAtIndex(TableView* table,ssize_t idx);

    virtual ssize_t numberOfCellsInTableView(TableView* table);

    

    //TableViewDelegateの抽象メソッド

    virtual void tableCellTouched(TableView* table,TableViewCell* cell);

    

    //TableViewDelegateが継承しているScrollViewの抽象メソッド

    virtual void scrollViewDidScroll(ScrollView* view){};

    virtual void scrollViewDidZoom(ScrollView* view){};

    

    CREATE_FUNC(Overview);

    

};


#endif /* defined(__TableView01__Overview__) */


Overview.cppを次のように変更してみてください。

#include "Overview.h"

#include "SecondScene.h"

//音をならすためにinclude

#include "SimpleAudioEngine.h"


/// 行数格納用のキー

const char* ROW_KEY = "row";


Scene* Overview::createScene()

{

    auto scene = Scene::create();

    auto layer = Overview::create();

    // scenelayerを読み込み表示する

    scene->addChild(layer);

    

    return scene;

}


// on "init" you need to initialize your instance

bool Overview::init()

{

    //初期化

    if ( !Layer::init() ) return false;

    

    //画面サイズサイズを取得

    window_size = Director::getInstance()->getWinSize();

    

    // バックグランドカラー

    auto background = LayerColor::create(Color4B::WHITE,

                                         window_size.width,

                                         window_size.height);

    

    // バックグランドカラー 第2引数は表示順

    this->addChild(background, 0);

    

    // テーブル一覧ラベルを生成

    auto label1 = Label::createWithSystemFont("テーブル一覧", "Arial", 60);

    

    label1->setColor(Color3B::BLACK);

    

    // ラベルの設置

    label1->setPosition(Vec2(window_size.width / 2 ,window_size.height - 80));

    

    // ラベルタイトルを呼び込み追加

    this->addChild(label1,1);

    

    

    // テーブルのヘッダー空間

    TableView* tableView = TableView::create

                     (this,Size(window_size.width,window_size.height*9/10));

    // テーブル全体表示

    //TableView* tableView = TableView::create(this, window_size);

    

    //展開方向

    tableView->setDirection(TableView::Direction::VERTICAL);

    //表示順序上からしたへ

    tableView->setVerticalFillOrder(TableView::VerticalFillOrder::TOP_DOWN);

    

    //追加

    tableView->setDelegate(this);

    addChild(tableView);

    // tableViewに呼び込む

    tableView->reloadData();

    

    return true;

}


// セルの大きさを設定する

Size Overview::cellSizeForTable(TableView *table){

    return Size(window_size.width, 100);

}


// 1セルに表示させるValueをセット

TableViewCell* Overview::tableCellAtIndex(TableView *table, ssize_t idx){

    

    // 行番号

    std::string id = StringUtils::format("%zd", idx);

    // 行テキスト

    std::string text = StringUtils::format("行目");

    // セル

    //auto *cell = table->dequeueCell();

    TableViewCell *cell = table->dequeueCell();

    

    cell = new TableViewCell();

    // autoreleaseを呼び出す

    cell->autorelease();

    

    // セルの背景は交互に色を変更する

    auto background_color = Color3B::GREEN;

    if (idx%2) {

        background_color = Color3B::BLUE;

    }

    

    // Background

    Sprite* bg = Sprite::create();

    bg->setAnchorPoint(Point(0, 0));

    bg->setTextureRect(Rect(0, 0, window_size.width, 90));

    bg->setColor(background_color);

    bg->setTag(100);

    // Backgroundを呼び出し表示

    cell->addChild(bg);

    

    // ボーダーライン

    Sprite* line = Sprite::create();

    line->setAnchorPoint(Point(0, 0));

    line->setTextureRect(Rect(0, 0, window_size.width, 1));

    line->setColor(Color3B::WHITE);

    cell->addChild(line);

    

    // 画像

    Sprite* imge_1 = Sprite::create("imge80.png");

    imge_1->setAnchorPoint(Point(0, 0));

    imge_1->setPosition(Point(10, +5));

    cell->addChild(imge_1);

    

    // IDテキスト部分

    auto *label_1 = LabelTTF::create(id.c_str(), "Arial", 80);

    label_1->setAnchorPoint(Point(0, 0));

    label_1->setPosition(Point(110, -4));

    label_1->setColor(Color3B::WHITE);

    cell->addChild(label_1);

    

    // テキスト部分

    auto *label_2 = LabelTTF::create(text.c_str(), "Arial", 80);

    label_2->setAnchorPoint(Point(0, 0));

    label_2->setPosition(Point(210, -4));

    label_2->setColor(Color3B::WHITE);

    cell->addChild(label_2);

    

    return cell;

}


// セル数

ssize_t Overview::numberOfCellsInTableView(TableView *table){

    return 60;

}


// セルがタッチされた時のcallback

void Overview::tableCellTouched(TableView* table, TableViewCell* cell){

    

    log("%ziのセルがタッチされました", cell->getIdx());

    // cell 行番号

    float row = cell->getIdx();

    

    // 行番号保存

    UserDefault::getInstance()->setIntegerForKey(ROW_KEY, row);


    // 効果音を鳴らす

    CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("onepoint26.mp3");

    

    

    // 遷移先の画面のインスタンス

    auto *pScene = SecondScene::createScene();

    

    // 0.5秒かけてフェードアウトしながら次の画面に遷移します

    //    引数1:フィードの時間

    //    引数2:移動先のシーン

    //    引数3:フィードの色(オプション)

    TransitionFade* transition = TransitionFade::create(0.5f, pScene);

    

    // 遷移実行  遷移時のアニメーション http://study-cocos2d-x.info/scenelayer/55/

    // 直前のsceneはもう使わないから捨ててしまう方法。基本はこれになります。

    Director::getInstance()->replaceScene(transition);

}

 

SecondScene画面のソースコード

SecondScene.hを次のように変更してみてください。

#ifndef __TableView01__SecondScene__

#define __TableView01__SecondScene__


#include "cocos2d.h"


class SecondScene : public cocos2d::Layer

{

protected:


    

public:

    static cocos2d::Scene* createScene();

    

    //初期化のメソッド

    virtual bool init();

    

    // スタートボタン押下時の処理宣言 戻る Object → Ref に変更

    void pushBack(cocos2d::Ref *pSender);

    

    // create()を使えるようにしている。

    CREATE_FUNC(SecondScene);

};


#endif /* defined(__TableView01__SecondScene__) */

SecondScene.cppを次のように変更してみてください。

#include "SecondScene.h"

#include "Overview.h"


//音をならすためにinclude

#include "SimpleAudioEngine.h"


// 名前空間 #define USING_NS_CC using namespace cocos2d

USING_NS_CC;


using namespace std; // String*


/// 行数格納用のキー

const char* ROW_KEY1 = "row";


Scene* SecondScene::createScene()

{

    // 「シーン」は自動解放オブジェクトです

    auto scene = Scene::create();

    

    // 「レイアウト」は自動解放オブジェクトです

    auto layer = SecondScene::create();

    

    // シーンに子としてレイヤーを追加

    scene->addChild(layer);

    

    // シーンを返す

    return scene;

}


// INIT」初期化

bool SecondScene::init()

{

    if ( !Layer::init() )

    {

        return false;

    }

    

    //画面の座標関係の詳しい説明はここ http://www.cocos2d-x.org/wiki/Coordinate_System

    //画面サイズを取得

    Size winSize = Director::getInstance()->getVisibleSize();

    Point origin = Director::getInstance()->getVisibleOrigin();

    

    // バックグランドカラー

    auto background = LayerColor::create(Color4B::BLUE,

                                         winSize.width,

                                         winSize.height);

    //バックグランドカラー追加 第2引数は表示順

    this->addChild(background, 0);

    

    // UserDefault 読込 LOG表示

    auto userDefault =UserDefault::getInstance();

    int row = userDefault->getIntegerForKey("row");

    

    // row + 行目との結合

    auto *rowstring = String::createWithFormat("%i行目",row);

    //auto *rowstring = String::createWithFormat("行目");

    // キャスト変換

    string _rowstring = rowstring->getCString();

    // ラベル生成

    auto label01 = Label::createWithSystemFont(_rowstring, "arial", 140);

    // ラベルの色:ホワイト

    label01->setColor(Color3B::WHITE);

    //画面の中央に表示

    label01->setPosition(Point(winSize.width/2, winSize.height/2 - 150));

    // Layerにラベルを追加

    this->addChild(label01);

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    

    // タイトルを設置

    auto lbl_title = Label::createWithSystemFont("Second", "arial", 100);

    lbl_title->setPosition(Point(origin.x + winSize.width/2,

                                     origin.y + winSize.height

                                     -lbl_title->getContentSize().height));

    this->addChild(lbl_title,1);

    

    //戻るボタンを設置

    auto backButton = MenuItemImage::create("CloseNormalBack.png"//表示

                                            "CloseSelected.png"//タップ時の画像

                                            CC_CALLBACK_1(SecondScene::pushBack, this));

    

    backButton->setPosition(Point(winSize.width /2 ,winSize.height/2 + 100));

    

    //create menu, it's an autorelease object

    auto menu = Menu::create(backButton, NULL);

    

    menu->setPosition(Point::ZERO);

    

    this->addChild(menu, 1);

    

    return true;

}


// pushBackボタン

void SecondScene::pushBack(Ref *pSender)

{

    // 効果音を鳴らす

    CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("onepoint26.mp3");


    // 遷移先の画面のインスタンス

    Scene *pScene = Overview::createScene();


    // 0.5秒かけてフェードアウトしながら次の画面に遷移します

    //    引数1:フィードの時間

    //    引数2:移動先のシーン

    //    引数3:フィードの色(オプション)

    TransitionFade* transition = TransitionFade::create(0.5f, pScene);


    //遷移実行  遷移時のアニメーション http://study-cocos2d-x.info/scenelayer/55/

    Director::getInstance()->replaceScene(transition);

    

}

 

※重要

本やWebサイトにも載っていない「UserDefault」の保存記述での注意!

TableViewの行番号保存で「UserDefault」を使うが記述によっては「iPhone」では動作するが「Android」では落ちてしまうことが判明。

なぜ「Android」では落ちるかは原因は不明だがOSバージョンの違う2台のAndroidとも落ちたので注意されたし。 落ちない記述を試した結果を示しておきます。

// O落ちない行番号保存記述「setIntegerForKey」

UserDefault::getInstance()->setIntegerForKey(ROW_KEY, row);

// X落ちる行番号保存記述「flush」

cocos2d::UserDefault* user = cocos2d::UserDefault::sharedUserDefault();

user->setIntegerForKey("row", row);

user->flush(); // X Androidでは落ちる