2014年01月21日

[Android] 画像と文字列を下端で揃えたいとき

画像と文字列の下端を揃えたいという要望がありました。
RelativeLayoutでlayout_alignBottomを設定すると以下のようになります。
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp" >
<ImageView
android:id="@+id/green"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:src="@drawable/green" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/green"
android:background="#ddf"
android:layout_toRightOf="@id/green"
android:text="テスト"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>

align_bottom.png
しかし、これでは上の画像のように、文字列の下に少し隙間が開いてしまいます。
フォントにはdescentという部分があるためですね。

descentを考慮して画像と文字列の下端を合わせたいときはlayout_alignBaselineを使います。
同時に画像を表示するImageViewにはbaselineAlignBottomをtrueにしておく必要があります。
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp" >
<ImageView
android:id="@+id/green"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:baselineAlignBottom="true"
android:src="@drawable/green" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/green"
android:layout_toRightOf="@id/green"
android:background="#ddf"
android:text="テスト"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>

align_baseline.png
こんな感じです。
これで画像と文字列の下端が揃いました。

posted by t2low at 22:00| Android

2014年01月20日

[Android] デフォルトで起動するアプリの判定

デフォルトで起動するように設定されているホームアプリの取得方法を調べてみました。
PackageManagerから簡単に習得できるんじゃないかと考えて、適当にクラスを眺めていましたが、見つからないので結局コードを追いかけることに…。

どうやらgetPreferredActivities()というメソッドを使えば良いようです。
String defaultHomeApp = "";

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);

PackageManager pm = getPackageManager();
List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
for (ResolveInfo info : list) {
List<IntentFilter> filters = new ArrayList<IntentFilter>();
List<ComponentName> activities = new ArrayList<ComponentName>();
pm.getPreferredActivities(filters, activities, info.activityInfo.packageName);
if (activities.size() > 0) {
defaultHomeApp = activities.get(0).toString();
break;
}
}
Log.d("LOG", "Home app : " + defaultHomeApp);



posted by t2low at 23:00| Android

2014年01月19日

[Mac] テレビとHDMI接続した

職場はデュアルモニタです。が、自宅はそうではありません。
画面が狭いのは不便なので、↓の商品を買いました。



送料無料で400円。
なんでこんなに安くできるんでしょうか。
16日に注文して、18日に届きました。
早いですね。
安かったので若干不安はありましたが、繋いでみたら問題なく表示されました。

大画面で表示できるのは良いのですが、自宅にあったHDMIケーブルの長さが足らないのに気づいていませんでした…。
今のままではちょっと使うのが厳しいです。どうしたものか。
posted by t2low at 00:10| Mac/iOS

2014年01月17日

[C++] double型を3桁ずつカンマで区切られた文字列に変換する

double型を3桁ずつカンマで区切られた文字列に変換する。
たったこれだけのことにえらい苦労しました。
C++の基本的なとこがわかっていないのですね。C++の基礎をひと通り勉強したほうが良さそうです。

良し悪しはともかく出来上がったのは以下のようなコード。
std:string str;
double value = 99999999.999;

std::stringstream stream;
stream << std::setprecision(2) << std::setiosflags(std::ios::fixed) << value;
stream >> str;

int signLen = value < 0 ? 1 : 0;
int dotPos = str.find('.');
for (int pos = dotPos - 3; pos > signLen; pos -= 3) {
str.insert(pos, ",", 1);
}

insert()で1個ずつカンマを挿入するようにしましたが効率は悪そう…。

参考:
cp_C++言語(予備知識) 

posted by t2low at 23:00| Cocos2d-x

2014年01月16日

[Cocos2d-x][C++] vector、mapが参照しているメモリを開放しつつ全削除

C++のmap、vectorに慣れておらず、苦労しました。
これで良いのではないかと思ってますが、間違ってたらつっこんでください…。

vector
for (vector<Hoge *>::iterator it = hoges.begin(); it != hoges.end();) {
delete *it;
it = hoges.erase(it);
}


map
for (map<int, Hoge *>::iterator it = hoges.begin(); it != hoges.end(); it++) {
delete it->second;
}
hoges.clear();

secondが値を指しているということなんですかね。わかりにくいですね。なんでこんな名前にしたんですかね。

参考:
c++ - How to erase & delete pointers to objects stored in a vector? - Stack Overflow
C++とのつきあい方(16)
posted by t2low at 23:00| Cocos2d-x

2014年01月15日

[Cocos2d-x] Resources内のファイルの読み込み

Resources内のファイルを読み込んで使うには以下のようにすれば良いみたい。
CCFileUtils *fileUtils = CCFileUtils::sharedFileUtils();
string path = fileUtils->fullPathForFilename("hoge.json");
unsigned long size = 0;
unsigned char *data = fileUtils->getFileData(path.c_str(), "r", &size);

// ... data を使ってなんかする

delete[] data;

getFileData()の中を見たら、第2引数をそのままfopen()につっこんでいたので、バイナリデータを読み込むときは"rb"にするのかな?


タグ:C++ cocos2d-x
posted by t2low at 22:00| Cocos2d-x

2014年01月10日

[Cocos2d-x] 階層化されたCCLayerの内側からモーダルレイヤを画面の中心に表示する


以下の本の「レシピ38」を参考にモーダルレイヤを作成しました。



画面の真ん中にドンとモーダルレイヤが表示される…はずだったのですが、僕の書いたコードでは上にずれて表示されてしまいました。
原因はCCLayerをいくつか階層化していたために、画面の左下とレイヤの原点がずれてしまっていたためです。

Cocos2d-xでは位置を親との相対座標で指定するようです。
これによって、階層の途中に位置が(0, 0)でないレイヤがあると、モーダルレイヤの位置を(0, 0)にしていたとしてもずれて表示されてしまいます。
少し調べただけでは、そのようなときに使う特別なメソッドはわかりませんでした。
それならばと、親階層をたどって左下の座標を計算するコードを書きました。
float x = 0;
float y = 0;
CCNode *node = modal->getParent();
while (node) {
x -= node->getPositionX();
y -= node->getPositionY();
node = node->getParent();
}
modal->setPosition(ccp(x, y));

とりあえずこれで画面の中心に表示できるようになりました。

タグ:cocos2d-x
posted by t2low at 23:00| Cocos2d-x

2014年01月07日

[Cocos2d-x] CCSpriteの重なり順

CCSpriteの重なり順を設定するには、reorderChild()というメソッドを呼べば良いらしい。

Cocos2d-x: 重なり順の取得、変更 | Lady Wendy

CCLayerを継承したクラスで以下のように呼んでみた。
for (int i = 0; i < MAX_HOGE; i++) {
CCSprite *sprite = (CCSprite *) getChildByTag(i);
if (sprite == NULL) {
continue;
}
reorderChild(sprite, HEIGHT - sprite->getPositionY());
}

結果は失敗。重なり順は変わらない。
少し調べてみると以下のような記事が見つかった。

cocos2d-x - CCSpriteBatchNodeのzOrder - Qiita [キータ]

確かにCCSpriteBatchNodeは使っているけれど、これを使ったせいで重なり順が変えられないなんてことあるわけない(はず!)。
と、ここで気がついた。
CCSpriteBatchNode *batch = (CCSpriteBatchNode *) getChildByTag(TAG_BATCH);
for (int i = 0; i < MAX_HOGE; i++) {
CCSprite *sprite = (CCSprite *) batch->getChildByTag(i);
if (sprite == NULL) {
continue;
}
batch->reorderChild(sprite, HEIGHT - sprite->getPositionY());
}

階層としては

・CCLayer
 └CCSpriteBatchNode
  ├CCSprite
  ├CCSprite
  ├CCSprite
  :
  └CCSprite

となっているのだから、CCSpriteBatchNodeのreorderChild()を呼ばなきゃダメだったわけね。
これで期待通りの重なり順になりました。

タグ:cocos2d-x
posted by t2low at 22:00| Cocos2d-x

2014年01月06日

[Cocos2d-x] テクスチャアトラスとCCSpriteBatchNodeを使ってスプライトを描画する

また忘れてしまいそうなのでメモ。
テクスチャアトラス(atlas.plist/atlas.png)があって、その中にhoge.pngがある場合、以下のようにすると良い(っぽい)。
 CCSpriteFrameCache *cache = CCSpriteFrameCache::sharedSpriteFrameCache();
cache->addSpriteFramesWithFile("atlas.plist");

CCSpriteBatchNode *batch = CCSpriteBatchNode::create("atlas.png");
addChild(batch);

for (int i = 0; i < 100; i++) {
CCSprite *sprite = CCSprite::createWithSpriteFrameName("hoge.png");
sprite->setPosition(ccp(i, i));
batch->addChild(sprite);
}


  • CCSpriteFrameCacheにはテクスチャアトラスの○○.plist

  • CCSpriteBatchNodeにはテクスチャアトラスの○○.png

  • CCSpriteにはテクスチャアトラス内の□□.png

  • をそれぞれ指定する。
    CCSpriteBatchNodeにもテクスチャアトラス内の画像名を渡していて少しハマっていた…。

posted by t2low at 22:00| Cocos2d-x

2013年12月25日

[Cocos2d-x][C++] C++で型推論

今までC++をほとんどやってこなかったので知りませんでした。
C++では型推論できたんですね。
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
CCTableView *tableView = CCTableView::create(this, CCSizeMake(visibleSize.width, visibleSize.height));
tableView->setDirection(kCCScrollViewDirectionVertical);
// 以下略

↑コレを↓のように書けます。
auto visibleSize = CCDirector::sharedDirector()->getVisibleSize();
auto tableView = CCTableView::create(this, CCSizeMake(visibleSize.width, visibleSize.height));
tableView->setDirection(kCCScrollViewDirectionVertical);
// 以下略

autoで定義された変数に対しても、Eclipse/Xcodeの補完が効きます。すごい!

どうやらC++11で導入されたようですね。
C++11 - Wikipedia



posted by t2low at 22:00| Cocos2d-x